From 6c33a05bdb9b071c358d5382145b251ae1210ad8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 2 Oct 2023 23:07:00 -0400 Subject: [PATCH 001/725] audio: Removed unused AllowsArbitraryDeviceNames variable. --- src/audio/SDL_sysaudio.h | 1 - src/audio/disk/SDL_diskaudio.c | 1 - src/audio/dsp/SDL_dspaudio.c | 1 - src/audio/netbsd/SDL_netbsdaudio.c | 1 - src/audio/sndio/SDL_sndioaudio.c | 1 - 5 files changed, 5 deletions(-) diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index e0d9316066b08..c49824dce1e09 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -143,7 +143,6 @@ typedef struct SDL_AudioDriverImpl SDL_bool HasCaptureSupport; SDL_bool OnlyHasDefaultOutputDevice; SDL_bool OnlyHasDefaultCaptureDevice; - SDL_bool AllowsArbitraryDeviceNames; } SDL_AudioDriverImpl; typedef struct SDL_AudioDriver diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index b4cf2beebb20d..be9ba9cbd7b11 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -160,7 +160,6 @@ static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl) impl->CloseDevice = DISKAUDIO_CloseDevice; impl->DetectDevices = DISKAUDIO_DetectDevices; - impl->AllowsArbitraryDeviceNames = SDL_TRUE; impl->HasCaptureSupport = SDL_TRUE; return SDL_TRUE; diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 05572d22fa02a..bcbf220c1eab3 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -293,7 +293,6 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl) impl->CaptureFromDevice = DSP_CaptureFromDevice; impl->FlushCapture = DSP_FlushCapture; - impl->AllowsArbitraryDeviceNames = SDL_TRUE; impl->HasCaptureSupport = SDL_TRUE; return SDL_TRUE; /* this audio target is available. */ diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index d8aafc08ba131..80b1767eadde8 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -317,7 +317,6 @@ static SDL_bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl) impl->FlushCapture = NETBSDAUDIO_FlushCapture; impl->HasCaptureSupport = SDL_TRUE; - impl->AllowsArbitraryDeviceNames = SDL_TRUE; return SDL_TRUE; } diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 0347c38ec66d3..2b3eeb02be5a0 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -348,7 +348,6 @@ static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl) impl->Deinitialize = SNDIO_Deinitialize; impl->DetectDevices = SNDIO_DetectDevices; - impl->AllowsArbitraryDeviceNames = SDL_TRUE; impl->HasCaptureSupport = SDL_TRUE; return SDL_TRUE; From a0820ed8332d3f049674217a6e0bb508fc863b54 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 3 Oct 2023 09:54:30 -0400 Subject: [PATCH 002/725] directsound: Cleaned up WaitDevice. This should retry until GetCurrentPosition succeeds. Otherwise, we would be going on to the next iteration too soon. Also generally streamlined the code while I was in here. --- src/audio/directsound/SDL_directsound.c | 58 +++++++------------------ 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index ab12c8cd9a333..bf812b50b4f75 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -227,61 +227,35 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi static void DSOUND_WaitDevice(SDL_AudioDevice *device) { - DWORD status = 0; - DWORD cursor = 0; - DWORD junk = 0; - HRESULT result = DS_OK; - /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ - result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf, - &junk, &cursor); - if (result != DS_OK) { - if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(device->hidden->mixbuf); - } -#ifdef DEBUG_SOUND - SetDSerror("DirectSound GetCurrentPosition", result); -#endif - return; - } - - while ((cursor / device->buffer_size) == device->hidden->lastchunk) { - if (SDL_AtomicGet(&device->shutdown)) { - return; - } - - SDL_Delay(1); + while (!SDL_AtomicGet(&device->shutdown)) { + DWORD status = 0; + DWORD cursor = 0; + DWORD junk = 0; + HRESULT result = DS_OK; // Try to restore a lost sound buffer IDirectSoundBuffer_GetStatus(device->hidden->mixbuf, &status); if (status & DSBSTATUS_BUFFERLOST) { IDirectSoundBuffer_Restore(device->hidden->mixbuf); - IDirectSoundBuffer_GetStatus(device->hidden->mixbuf, &status); - if (status & DSBSTATUS_BUFFERLOST) { - break; + } else if (!(status & DSBSTATUS_PLAYING)) { + result = IDirectSoundBuffer_Play(device->hidden->mixbuf, 0, 0, DSBPLAY_LOOPING); + } else { + // Find out where we are playing + result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf, &junk, &cursor); + if ((result == DS_OK) && ((cursor / device->buffer_size) != device->hidden->lastchunk)) { + break; // ready for next chunk! } } - if (!(status & DSBSTATUS_PLAYING)) { - result = IDirectSoundBuffer_Play(device->hidden->mixbuf, 0, 0, - DSBPLAY_LOOPING); - if (result == DS_OK) { - continue; - } -#ifdef DEBUG_SOUND - SetDSerror("DirectSound Play", result); -#endif - return; - } - // Find out where we are playing - result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf, - &junk, &cursor); - if (result != DS_OK) { - SetDSerror("DirectSound GetCurrentPosition", result); + if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) { + SDL_AudioDeviceDisconnected(device); return; } + + SDL_Delay(1); // not ready yet; sleep a bit. } } From d2d4914ac3e5233947c081ea5d68755f4ee80282 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 3 Oct 2023 10:35:18 -0400 Subject: [PATCH 003/725] audio: WaitDevice/WaitCaptureDevice now returns a result. This is an attempt to centralize all the error handling, instead of implicitly counting on WaitDevice implementations to disconnect the device to report an error. --- src/audio/SDL_audio.c | 14 ++++++++++---- src/audio/SDL_sysaudio.h | 4 ++-- src/audio/aaudio/SDL_aaudio.c | 3 ++- src/audio/alsa/SDL_alsa_audio.c | 8 +++++--- src/audio/directsound/SDL_directsound.c | 16 +++++++++------- src/audio/disk/SDL_diskaudio.c | 3 ++- src/audio/dsp/SDL_dspaudio.c | 7 ++++--- src/audio/dummy/SDL_dummyaudio.c | 3 ++- src/audio/n3ds/SDL_n3dsaudio.c | 3 ++- src/audio/netbsd/SDL_netbsdaudio.c | 7 ++++--- src/audio/openslES/SDL_openslES.c | 4 ++-- src/audio/ps2/SDL_ps2audio.c | 3 ++- src/audio/psp/SDL_pspaudio.c | 4 ++-- src/audio/pulseaudio/SDL_pulseaudio.c | 18 +++++++++++++----- src/audio/qnx/SDL_qsa_audio.c | 16 ++++++++-------- src/audio/sndio/SDL_sndioaudio.c | 17 ++++++++--------- src/audio/vita/SDL_vitaaudio.c | 6 ++++-- src/audio/wasapi/SDL_wasapi.c | 6 ++++-- 18 files changed, 85 insertions(+), 57 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 078e3793c53f9..b9a73247bc4c5 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -524,9 +524,9 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) // stubs for audio drivers that don't need a specific entry point... static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ } -static void SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } +static int SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ } -static void SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } +static int SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } @@ -938,7 +938,10 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point SDL_assert(!device->iscapture); SDL_OutputAudioThreadSetup(device); do { - current_audio.impl.WaitDevice(device); + if (current_audio.impl.WaitDevice(device) < 0) { + SDL_AudioDeviceDisconnected(device); // doh. + break; + } } while (SDL_OutputAudioThreadIterate(device)); SDL_OutputAudioThreadShutdown(device); @@ -1039,7 +1042,10 @@ static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point SDL_CaptureAudioThreadSetup(device); do { - current_audio.impl.WaitCaptureDevice(device); + if (current_audio.impl.WaitCaptureDevice(device) < 0) { + SDL_AudioDeviceDisconnected(device); // doh. + break; + } } while (SDL_CaptureAudioThreadIterate(device)); SDL_CaptureAudioThreadShutdown(device); diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index c49824dce1e09..284a718241acd 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -128,10 +128,10 @@ typedef struct SDL_AudioDriverImpl int (*OpenDevice)(SDL_AudioDevice *device); void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end - void (*WaitDevice)(SDL_AudioDevice *device); + int (*WaitDevice)(SDL_AudioDevice *device); int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience. Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); - void (*WaitCaptureDevice)(SDL_AudioDevice *device); + int (*WaitCaptureDevice)(SDL_AudioDevice *device); int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); void (*FlushCapture)(SDL_AudioDevice *device); void (*CloseDevice)(SDL_AudioDevice *device); diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 47fbcbb12e372..9a35ec50f21db 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -164,9 +164,10 @@ static Uint8 *AAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) return &hidden->mixbuf[offset]; } -static void AAUDIO_WaitDevice(SDL_AudioDevice *device) +static int AAUDIO_WaitDevice(SDL_AudioDevice *device) { SDL_WaitSemaphore(device->hidden->semaphore); + return 0; } static int BuildAAudioStream(SDL_AudioDevice *device); diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 74b097269a466..0826c551b6ece 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -326,7 +326,7 @@ static void no_swizzle(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen) #endif // SND_CHMAP_API_VERSION // This function waits until it is possible to write a full sound buffer -static void ALSA_WaitDevice(SDL_AudioDevice *device) +static int ALSA_WaitDevice(SDL_AudioDevice *device) { const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq); const int delay = SDL_max(fulldelay, 10); @@ -338,9 +338,9 @@ static void ALSA_WaitDevice(SDL_AudioDevice *device) if (status < 0) { // Hmm, not much we can do - abort SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc)); - SDL_AudioDeviceDisconnected(device); + return -1; } - return; + continue; } if (rc > 0) { @@ -349,6 +349,8 @@ static void ALSA_WaitDevice(SDL_AudioDevice *device) // Timed out! Make sure we aren't shutting down and then wait again. } + + return 0; } static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index bf812b50b4f75..ad0d9db375bb2 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -225,7 +225,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi } -static void DSOUND_WaitDevice(SDL_AudioDevice *device) +static int DSOUND_WaitDevice(SDL_AudioDevice *device) { /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) @@ -251,12 +251,13 @@ static void DSOUND_WaitDevice(SDL_AudioDevice *device) } if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) { - SDL_AudioDeviceDisconnected(device); - return; + return -1; } SDL_Delay(1); // not ready yet; sleep a bit. } + + return 0; } static int DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) @@ -328,19 +329,20 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->locked_buf; } -static void DSOUND_WaitCaptureDevice(SDL_AudioDevice *device) +static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; while (!SDL_AtomicGet(&device->shutdown)) { DWORD junk, cursor; if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) { - SDL_AudioDeviceDisconnected(device); - return; + return -1; } else if ((cursor / device->buffer_size) != h->lastchunk) { - return; + break; } SDL_Delay(1); } + + return 0; } static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index be9ba9cbd7b11..695360aa3ba9a 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -35,9 +35,10 @@ #define DISKDEFAULT_INFILE "sdlaudio-in.raw" #define DISKENVR_IODELAY "SDL_DISKAUDIODELAY" -static void DISKAUDIO_WaitDevice(SDL_AudioDevice *device) +static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device) { SDL_Delay(device->hidden->io_delay); + return 0; } static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index bcbf220c1eab3..b75b6d9f20d58 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -201,7 +201,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) return 0; // We're ready to rock and roll. :-) } -static void DSP_WaitDevice(SDL_AudioDevice *device) +static int DSP_WaitDevice(SDL_AudioDevice *device) { const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE; struct SDL_PrivateAudioData *h = device->hidden; @@ -215,14 +215,15 @@ static void DSP_WaitDevice(SDL_AudioDevice *device) } // Hmm, not much we can do - abort fprintf(stderr, "dsp WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); - SDL_AudioDeviceDisconnected(device); - return; + return -1; } else if (info.bytes < device->buffer_size) { SDL_Delay(10); } else { break; // ready to go! } } + + return 0; } static int DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index bd3002daa724d..aa0c51ecfd851 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -28,9 +28,10 @@ // !!! FIXME: this should be an SDL hint, not an environment variable. #define DUMMYENVR_IODELAY "SDL_DUMMYAUDIODELAY" -static void DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device) +static int DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device) { SDL_Delay(device->hidden->io_delay); + return 0; } static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device) diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index a7dc9fb069973..efc26542aeb88 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -200,7 +200,7 @@ static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in return 0; } -static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) +static int N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) { contextLock(device); while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) && @@ -208,6 +208,7 @@ static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) CondVar_Wait(&device->hidden->cv, &device->hidden->lock); } contextUnlock(device); + return 0; } static Uint8 *N3DSAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index 80b1767eadde8..0340bfb23f284 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -115,7 +115,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device) #endif // DEBUG_AUDIO } -static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) +static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) { const SDL_bool iscapture = device->iscapture; while (!SDL_AtomicGet(&device->shutdown)) { @@ -127,8 +127,7 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) } // Hmm, not much we can do - abort fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); - SDL_AudioDeviceDisconnected(device); - return; + return -1; } const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format)); if (!iscapture && (remain >= device->buffer_size)) { @@ -139,6 +138,8 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) break; /* ready to go! */ } } + + return 0; } static int NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index c4855eaefa4fe..de041e6b4895c 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -628,14 +628,14 @@ static int openslES_OpenDevice(SDL_AudioDevice *device) return 0; } -static void openslES_WaitDevice(SDL_AudioDevice *device) +static int openslES_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; LOGV("openslES_WaitDevice()"); // Wait for an audio chunk to finish - SDL_WaitSemaphore(audiodata->playsem); + return SDL_WaitSemaphore(audiodata->playsem); } static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/ps2/SDL_ps2audio.c b/src/audio/ps2/SDL_ps2audio.c index 2165194eb182f..4debff45d8340 100644 --- a/src/audio/ps2/SDL_ps2audio.c +++ b/src/audio/ps2/SDL_ps2audio.c @@ -91,9 +91,10 @@ static int PS2AUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int return (audsrv_play_audio((char *)buffer, buflen) != buflen) ? -1 : 0; } -static void PS2AUDIO_WaitDevice(SDL_AudioDevice *device) +static int PS2AUDIO_WaitDevice(SDL_AudioDevice *device) { audsrv_wait_audio(device->buffer_size); + return 0; } static Uint8 *PS2AUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index d701b5f2c9fa0..8e35897600629 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -118,9 +118,9 @@ static int PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int return (rc == 0) ? 0 : -1; } -static void PSPAUDIO_WaitDevice(SDL_AudioDevice *device) +static int PSPAUDIO_WaitDevice(SDL_AudioDevice *device) { - // Because we block when sending audio, there's no need for this function to do anything. + return 0; // Because we block when sending audio, there's no need for this function to do anything. } static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 4d9c8cd072c30..a554fcd322d7e 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -396,9 +396,10 @@ static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata) } /* This function waits until it is possible to write a full sound buffer */ -static void PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) +static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; + int retval = 0; /*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/ @@ -410,11 +411,14 @@ static void PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { /*printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n");*/ - SDL_AudioDeviceDisconnected(device); + retval = -1; break; } } + PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); + + return retval; } static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) @@ -462,21 +466,23 @@ static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata) PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* the capture code queries what it needs, we just need to signal to end any wait */ } -static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) +static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; if (h->capturebuf != NULL) { - return; // there's still data available to read. + return 0; // there's still data available to read. } + int retval = 0; + PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); while (!SDL_AtomicGet(&device->shutdown)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { //printf("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!\n"); - SDL_AudioDeviceDisconnected(device); + retval = -1; break; } else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { // a new fragment is available! @@ -497,6 +503,8 @@ static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) } PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); + + return retval; } static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) diff --git a/src/audio/qnx/SDL_qsa_audio.c b/src/audio/qnx/SDL_qsa_audio.c index 7103716875c00..7c242ce94d6bc 100644 --- a/src/audio/qnx/SDL_qsa_audio.c +++ b/src/audio/qnx/SDL_qsa_audio.c @@ -86,21 +86,19 @@ static void QSA_InitAudioParams(snd_pcm_channel_params_t * cpars) } // This function waits until it is possible to write a full sound buffer -static void QSA_WaitDevice(SDL_AudioDevice *device) +static int QSA_WaitDevice(SDL_AudioDevice *device) { - int result; - // Setup timeout for playing one fragment equal to 2 seconds // If timeout occurred than something wrong with hardware or driver // For example, Vortex 8820 audio driver stucks on second DAC because // it doesn't exist ! - result = SDL_IOReady(device->hidden->audio_fd, - device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE, - 2 * 1000); + const int result = SDL_IOReady(device->hidden->audio_fd, + device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE, + 2 * 1000); switch (result) { case -1: - SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno)); // !!! FIXME: Should we just disconnect the device in this case? - break; + SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "QSA: SDL_IOReady() failed: %s", strerror(errno)); + return -1; case 0: device->hidden->timeout_on_wait = SDL_TRUE; // !!! FIXME: Should we just disconnect the device in this case? break; @@ -108,6 +106,8 @@ static void QSA_WaitDevice(SDL_AudioDevice *device) device->hidden->timeout_on_wait = SDL_FALSE; break; } + + return 0; } static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 2b3eeb02be5a0..4319d385b8832 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -147,32 +147,31 @@ static int LoadSNDIOLibrary(void) #endif // SDL_AUDIO_DRIVER_SNDIO_DYNAMIC -static void SNDIO_WaitDevice(SDL_AudioDevice *device) +static int SNDIO_WaitDevice(SDL_AudioDevice *device) { const SDL_bool iscapture = device->iscapture; while (!SDL_AtomicGet(&device->shutdown)) { if (SNDIO_sio_eof(device->hidden->dev)) { - SDL_AudioDeviceDisconnected(device); - return; + return -1; } const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT); if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) { - SDL_AudioDeviceDisconnected(device); - return; + return -1; } const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd); if (iscapture && (revents & POLLIN)) { - return; + break; } else if (!iscapture && (revents & POLLOUT)) { - return; + break; } else if (revents & POLLHUP) { - SDL_AudioDeviceDisconnected(device); - return; + return -1; } } + + return 0; } static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index 53a54d104cba0..7f13f0e4ead29 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -136,12 +136,13 @@ static int VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int } // This function waits until it is possible to write a full sound buffer -static void VITAAUD_WaitDevice(SDL_AudioDevice *device) +static int VITAAUD_WaitDevice(SDL_AudioDevice *device) { // !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc. while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) { SDL_Delay(1); } + return 0; } static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -172,7 +173,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device) } } -static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) +static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) { // there's only a blocking call to obtain more data, so we'll just sleep as // long as a buffer would run. @@ -180,6 +181,7 @@ static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) { SDL_Delay(1); } + return 0; } static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index ab081af54daec..42aa8ef57716f 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -431,7 +431,7 @@ static int WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int b return 0; } -static void WASAPI_WaitDevice(SDL_AudioDevice *device) +static int WASAPI_WaitDevice(SDL_AudioDevice *device) { // WaitDevice does not hold the device lock, so check for recovery/disconnect details here. while (RecoverWasapiIfLost(device) && device->hidden->client && device->hidden->event) { @@ -450,9 +450,11 @@ static void WASAPI_WaitDevice(SDL_AudioDevice *device) } else if (waitResult != WAIT_TIMEOUT) { //SDL_Log("WASAPI FAILED EVENT!");*/ IAudioClient_Stop(device->hidden->client); - WASAPI_DisconnectDevice(device); + return -1; } } + + return 0; } static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) From ff57867516d4f8044283ec4a8554c27782e525a6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 3 Oct 2023 14:58:05 -0400 Subject: [PATCH 004/725] audio: Fixed copy/paste error that was checking wrong variable. Fixes #8342. --- src/audio/SDL_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b9a73247bc4c5..cb2736982cc60 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1565,7 +1565,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac SDL_AudioDevice *device = logdev->physical_device; if (callback && !device->postmix_buffer) { device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); - if (device->mix_buffer == NULL) { + if (device->postmix_buffer == NULL) { retval = SDL_OutOfMemory(); } } From 0eb8651d5ec7c229f5c29436dd58f4752b40b07a Mon Sep 17 00:00:00 2001 From: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:36:04 +0200 Subject: [PATCH 005/725] Do not report gyro/accelerometer if we can't read axes info --- src/joystick/linux/SDL_sysjoystick.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 992a0d824c390..ade45ed90116c 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -1261,9 +1261,11 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) /* Sensors are only available through the new unified event API */ if (fd_sensor >= 0 && (ioctl(fd_sensor, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0)) { if (test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && test_bit(ABS_Z, absbit)) { + joystick->hwdata->has_accelerometer = SDL_TRUE; for (i = 0; i < 3; ++i) { struct input_absinfo absinfo; if (ioctl(fd_sensor, EVIOCGABS(ABS_X + i), &absinfo) < 0) { + joystick->hwdata->has_accelerometer = SDL_FALSE; break; /* do not report an accelerometer if we can't read all axes */ } joystick->hwdata->accelerometer_scale[i] = absinfo.resolution; @@ -1274,14 +1276,15 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) absinfo.fuzz, absinfo.flat, absinfo.resolution); #endif /* DEBUG_INPUT_EVENTS */ } - joystick->hwdata->has_accelerometer = SDL_TRUE; } if (test_bit(ABS_RX, absbit) && test_bit(ABS_RY, absbit) && test_bit(ABS_RZ, absbit)) { + joystick->hwdata->has_gyro = SDL_TRUE; for (i = 0; i < 3; ++i) { struct input_absinfo absinfo; if (ioctl(fd_sensor, EVIOCGABS(ABS_RX + i), &absinfo) < 0) { - break; /* do not report an gyro if we can't read all axes */ + joystick->hwdata->has_gyro = SDL_FALSE; + break; /* do not report a gyro if we can't read all axes */ } joystick->hwdata->gyro_scale[i] = absinfo.resolution; #ifdef DEBUG_INPUT_EVENTS @@ -1291,7 +1294,6 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) absinfo.fuzz, absinfo.flat, absinfo.resolution); #endif /* DEBUG_INPUT_EVENTS */ } - joystick->hwdata->has_gyro = SDL_TRUE; } } From 49abb9c1fa954bf2fa3e8fdce6d99803c3701b05 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 4 Oct 2023 14:06:16 -0400 Subject: [PATCH 006/725] aaudio: Fixed a comment. --- src/audio/aaudio/SDL_aaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 9a35ec50f21db..977d84e4c557a 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -83,7 +83,7 @@ static void AAUDIO_errorCallback(AAudioStream *stream, void *userData, aaudio_re LOGI("SDL AAUDIO_errorCallback: %d - %s", error, ctx.AAudio_convertResultToText(error)); // You MUST NOT close the audio stream from this callback, so we cannot call SDL_AudioDeviceDisconnected here. - // Just flag the device so we can kill it in WaitDevice/PlayDevice instead. + // Just flag the device so we can kill it in PlayDevice instead. SDL_AudioDevice *device = (SDL_AudioDevice *) userData; SDL_AtomicSet(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error. SDL_PostSemaphore(device->hidden->semaphore); // in case we're blocking in WaitDevice. From 4cd0c13823551cce279c9ff3d284c41c28deb3d8 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 4 Oct 2023 21:17:13 +0200 Subject: [PATCH 007/725] blit_slow: don't read destination pixel when you're going to discard it anyways --- src/video/SDL_blit_slow.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index 6348fbf26f284..3c2730c05a378 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -105,15 +105,20 @@ void SDL_Blit_Slow(SDL_BlitInfo *info) continue; } } - if (FORMAT_HAS_ALPHA(dstfmt_val)) { - DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA); - } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { - DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB); - dstA = 0xFF; + if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) { + if (FORMAT_HAS_ALPHA(dstfmt_val)) { + DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA); + } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { + DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB); + dstA = 0xFF; + } else { + /* SDL_PIXELFORMAT_ARGB2101010 */ + dstpixel = *((Uint32 *) (dst)); + RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA); + } } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ - dstpixel = *((Uint32 *)(dst)); - RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA); + /* don't care */ + dstR = dstG = dstB = dstA = 0; } if (flags & SDL_COPY_MODULATE_COLOR) { From 4f0642bf47e3e2458bc1780844f35613f96b9323 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 5 Oct 2023 13:40:09 +0200 Subject: [PATCH 008/725] triangle: don't read destination pixel when you're going to discard it anyways --- src/render/software/SDL_triangle.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index 3b6e37d03a16d..090ebdf4ff461 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -788,15 +788,20 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info, continue; } } - if (FORMAT_HAS_ALPHA(dstfmt_val)) { - DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA); - } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { - DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB); - dstA = 0xFF; + if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) { + if (FORMAT_HAS_ALPHA(dstfmt_val)) { + DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA); + } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { + DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB); + dstA = 0xFF; + } else { + /* SDL_PIXELFORMAT_ARGB2101010 */ + dstpixel = *((Uint32 *) (dst)); + RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA); + } } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ - dstpixel = *((Uint32 *)(dst)); - RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA); + /* don't care */ + dstR = dstG = dstB = dstA = 0; } if (!is_uniform) { From 183606d3d41750909a147137d9311ca4fa6efdbd Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 5 Oct 2023 13:41:01 +0200 Subject: [PATCH 009/725] testdrawchessboard: clean up renderer and window --- test/testdrawchessboard.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index 75a0e7d749025..375410590c379 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -151,6 +151,9 @@ int main(int argc, char *argv[]) } #endif + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); SDLTest_CommonDestroyState(state); return 0; From b028fd9604186c7a921e161d098361e3fba85441 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 29 Sep 2023 12:52:17 +0100 Subject: [PATCH 010/725] SDLTest_CompareSurfaces: Log better messages if NULL or different sizes Signed-off-by: Simon McVittie --- src/test/SDL_test_compare.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index 023723de3bdbb..c65b75c72a442 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -67,12 +67,19 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, char referenceFilename[FILENAME_SIZE]; /* Validate input surfaces */ - if (surface == NULL || referenceSurface == NULL) { + if (surface == NULL) { + SDLTest_LogError("Cannot compare NULL surface"); + return -1; + } + + if (referenceSurface == NULL) { + SDLTest_LogError("Cannot compare NULL reference surface"); return -1; } /* Make sure surface size is the same. */ if ((surface->w != referenceSurface->w) || (surface->h != referenceSurface->h)) { + SDLTest_LogError("Expected %dx%d surface, got %dx%d", referenceSurface->w, referenceSurface->h, surface->w, surface->h); return -2; } From b2ddfbbec3c28ec6085bf9bedcaf00c0a34e86a4 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 29 Sep 2023 12:52:32 +0100 Subject: [PATCH 011/725] SDLTest_CompareSurfaces: If surfaces differ, log their formats Signed-off-by: Simon McVittie --- src/test/SDL_test_compare.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index c65b75c72a442..8101d0aae55de 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -52,6 +52,16 @@ GetPixel(Uint8 *p, size_t bytes_per_pixel) return ret; } +static void +LogErrorFormat(const char *name, const SDL_PixelFormat *format) +{ + SDLTest_LogError("%s: %08" SDL_PRIx32 " %s, %u bits/%u bytes per pixel", name, format->format, SDL_GetPixelFormatName(format->format), format->BitsPerPixel, format->BytesPerPixel); + SDLTest_LogError("%s: R mask %08" SDL_PRIx32 ", loss %u, shift %u", name, format->Rmask, format->Rloss, format->Rshift); + SDLTest_LogError("%s: G mask %08" SDL_PRIx32 ", loss %u, shift %u", name, format->Gmask, format->Gloss, format->Gshift); + SDLTest_LogError("%s: B mask %08" SDL_PRIx32 ", loss %u, shift %u", name, format->Bmask, format->Bloss, format->Bshift); + SDLTest_LogError("%s: A mask %08" SDL_PRIx32 ", loss %u, shift %u", name, format->Amask, format->Aloss, format->Ashift); +} + /* Compare surfaces */ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error) { @@ -130,6 +140,8 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, _CompareSurfaceCount++; if (ret != 0) { SDLTest_LogError("Comparison of pixels with allowable error of %i failed %i times.", allowable_error, ret); + LogErrorFormat("Reference surface format", referenceSurface->format); + LogErrorFormat("Actual surface format ", surface->format); SDLTest_LogError("First detected occurrence at position %i,%i with a squared RGB-difference of %i.", sampleErrorX, sampleErrorY, sampleDist); (void)SDL_snprintf(imageFilename, FILENAME_SIZE - 1, "CompareSurfaces%04d_TestOutput.bmp", _CompareSurfaceCount); SDL_SaveBMP(surface, imageFilename); From 4e59bf6cb9358d7595dec9a0dea49bf5f161243b Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 29 Sep 2023 13:00:43 +0100 Subject: [PATCH 012/725] SDLTest_CompareSurfaces: Output RGBA values of first differing pixel Signed-off-by: Simon McVittie --- src/test/SDL_test_compare.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index 8101d0aae55de..bc3c484bdb9c1 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -71,6 +71,8 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, Uint8 *p, *p_reference; int dist; int sampleErrorX = 0, sampleErrorY = 0, sampleDist = 0; + SDL_Color sampleReference = { 0, 0, 0, 0 }; + SDL_Color sampleActual = { 0, 0, 0, 0 }; Uint8 R, G, B, A; Uint8 Rd, Gd, Bd, Ad; char imageFilename[FILENAME_SIZE]; @@ -128,6 +130,14 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, sampleErrorX = i; sampleErrorY = j; sampleDist = dist; + sampleReference.r = Rd; + sampleReference.g = Gd; + sampleReference.b = Bd; + sampleReference.a = Ad; + sampleActual.r = R; + sampleActual.g = G; + sampleActual.b = B; + sampleActual.a = A; } } } @@ -143,6 +153,8 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, LogErrorFormat("Reference surface format", referenceSurface->format); LogErrorFormat("Actual surface format ", surface->format); SDLTest_LogError("First detected occurrence at position %i,%i with a squared RGB-difference of %i.", sampleErrorX, sampleErrorY, sampleDist); + SDLTest_LogError("Reference pixel: R=%u G=%u B=%u A=%u", sampleReference.r, sampleReference.g, sampleReference.b, sampleReference.a); + SDLTest_LogError("Actual pixel : R=%u G=%u B=%u A=%u", sampleActual.r, sampleActual.g, sampleActual.b, sampleActual.a); (void)SDL_snprintf(imageFilename, FILENAME_SIZE - 1, "CompareSurfaces%04d_TestOutput.bmp", _CompareSurfaceCount); SDL_SaveBMP(surface, imageFilename); (void)SDL_snprintf(referenceFilename, FILENAME_SIZE - 1, "CompareSurfaces%04d_Reference.bmp", _CompareSurfaceCount); From f30392da5bd51da3fb8b74eab3f9193d0194ee2a Mon Sep 17 00:00:00 2001 From: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:44:15 +0200 Subject: [PATCH 013/725] Fix assertion in LINUX_JoystickSetSensorsEnabled() Calling LINUX_JoystickSetSensorsEnabled() after the joystick is unplugged will trigger this assertion. --- src/joystick/linux/SDL_sysjoystick.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index ade45ed90116c..fea20069544f7 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -1565,7 +1565,9 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab } if (enabled) { - SDL_assert(joystick->hwdata->item_sensor); + if (joystick->hwdata->item_sensor == NULL) { + return SDL_SetError("Sensors unplugged."); + } joystick->hwdata->fd_sensor = open(joystick->hwdata->item_sensor->path, O_RDONLY | O_CLOEXEC, 0); if (joystick->hwdata->fd_sensor < 0) { return SDL_SetError("Couldn't open sensor file %s.", joystick->hwdata->item_sensor->path); From 2a9480c81581bb81cb265844d54e7ee16a69c4ec Mon Sep 17 00:00:00 2001 From: Etaash Mathamsetty Date: Fri, 6 Oct 2023 14:58:45 -0400 Subject: [PATCH 014/725] wayland: Add null check for zenity version string --- src/video/wayland/SDL_waylandmessagebox.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/wayland/SDL_waylandmessagebox.c b/src/video/wayland/SDL_waylandmessagebox.c index 03149f82ca022..a7d96cbbc27ae 100644 --- a/src/video/wayland/SDL_waylandmessagebox.c +++ b/src/video/wayland/SDL_waylandmessagebox.c @@ -96,6 +96,10 @@ static int get_zenity_version(int *major, int *minor) { version_ptr = fgets(version_str, ZENITY_VERSION_LEN, outputfp); (void)fclose(outputfp); /* will close underlying fd */ + if (version_ptr == NULL) { + return SDL_SetError("failed to read zenity version string"); + } + /* we expect the version string is in the form of MAJOR.MINOR.MICRO * as described in meson.build. We'll ignore everything after that. */ From 836927edf8da93ca2d3c8dddf7653113da65ce65 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 9 Oct 2023 11:44:32 -0400 Subject: [PATCH 015/725] wayland: Try to skip the Wayland driver if not connecting to or in a Wayland session When initializing the Wayland driver, check if the application is being started in, or trying to connect to, a Wayland session and skip to another driver if not. If neither WAYLAND_DISPLAY nor XDG_SESSION_TYPE are set, try to start anyway, and if the Wayland library is missing or no Wayland sessions are started, initialization will fail later in the process as it previously did. This fixes the case where a Wayland session is running on a different VT, but an application wishes to run via KMSDRM on the current VT. --- src/video/wayland/SDL_waylandvideo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index bd9b7d4041a49..9117410e23e65 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -128,6 +128,14 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) SDL_VideoData *data; struct wl_display *display; + /* Are we trying to connect to or are currently in a Wayland session? */ + if (!getenv("WAYLAND_DISPLAY")) { + const char *session = getenv("XDG_SESSION_TYPE"); + if (session && SDL_strcasecmp(session, "wayland")) { + return NULL; + } + } + if (!SDL_WAYLAND_LoadSymbols()) { return NULL; } From 8745a9949b360a4165047ad0b1ee99380a3c09e5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 9 Oct 2023 19:15:54 -0400 Subject: [PATCH 016/725] add-source-to-projects.pl: Fix adding files in the base src dir. --- build-scripts/add-source-to-projects.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/build-scripts/add-source-to-projects.pl b/build-scripts/add-source-to-projects.pl index 4530e92dfa22d..6d703dc36b00f 100755 --- a/build-scripts/add-source-to-projects.pl +++ b/build-scripts/add-source-to-projects.pl @@ -438,6 +438,7 @@ sub process_visualstudio { $filter = lc(dirname($addpath)); $filter =~ s/\Asrc\///; # there's no filter for the base "src/" dir, where SDL.c and friends live. $filter =~ s/\//\\/g; + $filter = '' if $filter eq 'src'; if ($filter ne '') { # see if the filter already exists, otherwise add it. From 568902b64e708fd54f9c6857a615cf4c767ff0ed Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 9 Oct 2023 19:17:05 -0400 Subject: [PATCH 017/725] hashtable: Added src/SDL_hashtable.[ch]. Reference Issue #7799. --- VisualC-GDK/SDL/SDL.vcxproj | 2 + VisualC-GDK/SDL/SDL.vcxproj.filters | 2 + VisualC-WinRT/SDL-UWP.vcxproj | 2 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 2 + VisualC/SDL/SDL.vcxproj | 4 +- VisualC/SDL/SDL.vcxproj.filters | 2 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 7 + src/SDL_hashtable.c | 259 ++++++++++++++++++++++++ src/SDL_hashtable.h | 53 +++++ 9 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 src/SDL_hashtable.c create mode 100644 src/SDL_hashtable.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 0545d3c4224ac..d222f42cd6a39 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -468,6 +468,7 @@ $(IntDir)$(TargetName)_cpp.pch + @@ -540,6 +541,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 62f79c6b1fa7f..683d6b4f3e765 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -397,6 +397,7 @@ API Headers + API Headers @@ -845,6 +846,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index f45e82404f959..863b0e3e397a3 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -151,6 +151,7 @@ + @@ -391,6 +392,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 8edd716fe4664..a1c99a51e712d 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -324,6 +324,7 @@ Source Files + Source Files @@ -639,6 +640,7 @@ Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index e35540408280d..31263605cea0b 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -395,6 +395,7 @@ Create + @@ -466,6 +467,7 @@ + @@ -662,4 +664,4 @@ - \ No newline at end of file + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index dbf4e543eef0f..df44db6b2de10 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -388,6 +388,7 @@ API Headers + API Headers @@ -824,6 +825,7 @@ + diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 90e2ccb99b63e..2ed36dcb0408d 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -469,6 +469,8 @@ F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E72933074E00816151 /* SDL_begin_code.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E52933074E00816151 /* SDL_system.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E82933074E00816151 /* SDL_system.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; + 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; + 0000CE8F0EF0E7EF781D0000 /* SDL_hashtable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -962,6 +964,8 @@ F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; }; F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; }; FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_hashtable.c; path = SDL_hashtable.c; sourceTree = ""; }; + 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_hashtable.h; path = SDL_hashtable.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1129,6 +1133,8 @@ F386F6E52884663E001840AA /* SDL_utils_c.h */, F386F6E62884663E001840AA /* SDL_utils.c */, A7D8A57123E2513D00DCD162 /* SDL.c */, + 000078E1881E857EBB6C0000 /* SDL_hashtable.c */, + 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */, ); name = "Library Source"; path = ../../src; @@ -2584,6 +2590,7 @@ A7D8AEA023E2514100DCD162 /* SDL_cocoavulkan.m in Sources */, A7D8AB6123E2514100DCD162 /* SDL_offscreenwindow.c in Sources */, 566E26D8246274CC00718109 /* SDL_locale.c in Sources */, + 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c new file mode 100644 index 0000000000000..59f2999c99065 --- /dev/null +++ b/src/SDL_hashtable.c @@ -0,0 +1,259 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" +#include "SDL_hashtable.h" + +typedef struct SDL_HashItem +{ + const void *key; + const void *value; + struct SDL_HashItem *next; +} SDL_HashItem; + +struct SDL_HashTable +{ + SDL_HashItem **table; + Uint32 table_len; + SDL_bool stackable; + void *data; + SDL_HashTable_HashFn hash; + SDL_HashTable_KeyMatchFn keymatch; + SDL_HashTable_NukeFn nuke; +}; + +SDL_HashTable *SDL_NewHashTable(void *data, const Uint32 num_buckets, const SDL_HashTable_HashFn hashfn, + const SDL_HashTable_KeyMatchFn keymatchfn, + const SDL_HashTable_NukeFn nukefn, + const SDL_bool stackable) +{ + SDL_HashTable *table; + + /* num_buckets must be a power of two so we get a solid block of bits to mask hash values against. */ + if ((num_buckets == 0) || ((num_buckets & (num_buckets - 1)) != 0)) { + SDL_SetError("num_buckets must be a power of two"); + return NULL; + } + + table = (SDL_HashTable *) SDL_calloc(1, sizeof (SDL_HashTable)); + if (table == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + table->table = (SDL_HashItem **) SDL_calloc(num_buckets, sizeof (SDL_HashItem *)); + if (table->table == NULL) { + SDL_free(table); + SDL_OutOfMemory(); + return NULL; + } + + table->table_len = num_buckets; + table->stackable = stackable; + table->data = data; + table->hash = hashfn; + table->keymatch = keymatchfn; + table->nuke = nukefn; + return table; +} + +static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *table, const void *key) +{ + return table->hash(key, table->data) & (table->table_len - 1); +} + + +SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value) +{ + SDL_HashItem *item; + const Uint32 hash = calc_hash(table, key); + + if ( (!table->stackable) && (SDL_FindInHashTable(table, key, NULL)) ) { + return SDL_FALSE; + } + + /* !!! FIXME: grow and rehash table if it gets too saturated. */ + item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem)); + if (item == NULL) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + + item->key = key; + item->value = value; + item->next = table->table[hash]; + table->table[hash] = item; + + return SDL_TRUE; +} + +SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value) +{ + const Uint32 hash = calc_hash(table, key); + void *data = table->data; + SDL_HashItem *prev = NULL; + SDL_HashItem *i; + + for (i = table->table[hash]; i != NULL; i = i->next) { + if (table->keymatch(key, i->key, data)) { + if (_value != NULL) { + *_value = i->value; + } + + /* Matched! Move to the front of list for faster lookup next time. + (stackable tables have to remain in the same order, though!) */ + if ((!table->stackable) && (prev != NULL)) { + SDL_assert(prev->next == i); + prev->next = i->next; + i->next = table->table[hash]; + table->table[hash] = i; + } + + return SDL_TRUE; + } + + prev = i; + } + + return SDL_FALSE; +} + +SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key) +{ + const Uint32 hash = calc_hash(table, key); + SDL_HashItem *item = NULL; + SDL_HashItem *prev = NULL; + void *data = table->data; + + for (item = table->table[hash]; item != NULL; item = item->next) { + if (table->keymatch(key, item->key, data)) { + if (prev != NULL) { + prev->next = item->next; + } else { + table->table[hash] = item->next; + } + + table->nuke(item->key, item->value, data); + SDL_free(item); + return SDL_TRUE; + } + + prev = item; + } + + return SDL_FALSE; +} + +SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const void **_value, void **iter) +{ + SDL_HashItem *item = iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)]; + + while (item != NULL) { + if (table->keymatch(key, item->key, table->data)) { + *_value = item->value; + *iter = item; + return SDL_TRUE; + } + item = item->next; + } + + /* no more matches. */ + *_value = NULL; + *iter = NULL; + return SDL_FALSE; +} + +SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, void **iter) +{ + SDL_HashItem *item = (SDL_HashItem *) *iter; + Uint32 idx = 0; + + if (item != NULL) { + const SDL_HashItem *orig = item; + item = item->next; + if (item == NULL) { + idx = calc_hash(table, orig->key) + 1; + } + } + + while (!item && (idx < table->table_len)) { + item = table->table[idx++]; /* skip empty buckets... */ + } + + if (item == NULL) { /* no more matches? */ + *_key = NULL; + *iter = NULL; + return SDL_FALSE; + } + + *_key = item->key; + *iter = item; + return SDL_TRUE; +} + +void SDL_FreeHashTable(SDL_HashTable *table) +{ + if (table != NULL) { + void *data = table->data; + Uint32 i; + + for (i = 0; i < table->table_len; i++) { + SDL_HashItem *item = table->table[i]; + while (item != NULL) { + SDL_HashItem *next = item->next; + table->nuke(item->key, item->value, data); + SDL_free(item); + item = next; + } + } + + SDL_free(table->table); + SDL_free(table); + } +} + +/* this is djb's xor hashing function. */ +static SDL_INLINE Uint32 hash_string_djbxor(const char *str, size_t len) +{ + Uint32 hash = 5381; + while (len--) { + hash = ((hash << 5) + hash) ^ *(str++); + } + return hash; +} + +Uint32 SDL_HashString(const void *sym, void *data) +{ + const char *str = (const char*) sym; + return hash_string_djbxor(str, SDL_strlen((const char *) str)); +} + +SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) +{ + if (a == b) { + return SDL_TRUE; /* same pointer, must match. */ + } else if (!a || !b) { + return SDL_FALSE; /* one pointer is NULL (and first test shows they aren't the same pointer), must not match. */ + } + return (SDL_strcmp((const char *) a, (const char *) b) == 0) ? SDL_TRUE : SDL_FALSE; /* Check against actual string contents. */ +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h new file mode 100644 index 0000000000000..1e0a611c1e76e --- /dev/null +++ b/src/SDL_hashtable.h @@ -0,0 +1,53 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef SDL_hashtable_h_ +#define SDL_hashtable_h_ + +/* this is not (currently) a public API. But maybe it should be! */ + +struct SDL_HashTable; +typedef struct SDL_HashTable SDL_HashTable; +typedef Uint32 (*SDL_HashTable_HashFn)(const void *key, void *data); +typedef SDL_bool (*SDL_HashTable_KeyMatchFn)(const void *a, const void *b, void *data); +typedef void (*SDL_HashTable_NukeFn)(const void *key, const void *value, void *data); + +SDL_HashTable *SDL_NewHashTable(void *data, + const Uint32 num_buckets, + const SDL_HashTable_HashFn hashfn, + const SDL_HashTable_KeyMatchFn keymatchfn, + const SDL_HashTable_NukeFn nukefn, + const SDL_bool stackable); + +void SDL_FreeHashTable(SDL_HashTable *table); +SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value); +SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); +SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); + +SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const void **_value, void **iter); +SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, void **iter); + +Uint32 SDL_HashString(const void *sym, void *unused); +SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *unused); + +#endif /* SDL_hashtable_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ + From 8e03ea438342d6228e3b81fef9a8d4bab6327a01 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 9 Oct 2023 19:20:43 -0400 Subject: [PATCH 018/725] hashtable: Use Create/Destroy naming, in the SDL3 style. --- src/SDL_hashtable.c | 10 +++++----- src/SDL_hashtable.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 59f2999c99065..e4b301c54776b 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -40,10 +40,10 @@ struct SDL_HashTable SDL_HashTable_NukeFn nuke; }; -SDL_HashTable *SDL_NewHashTable(void *data, const Uint32 num_buckets, const SDL_HashTable_HashFn hashfn, - const SDL_HashTable_KeyMatchFn keymatchfn, - const SDL_HashTable_NukeFn nukefn, - const SDL_bool stackable) +SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const SDL_HashTable_HashFn hashfn, + const SDL_HashTable_KeyMatchFn keymatchfn, + const SDL_HashTable_NukeFn nukefn, + const SDL_bool stackable) { SDL_HashTable *table; @@ -209,7 +209,7 @@ SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, return SDL_TRUE; } -void SDL_FreeHashTable(SDL_HashTable *table) +void SDL_DestroyHashTable(SDL_HashTable *table) { if (table != NULL) { void *data = table->data; diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h index 1e0a611c1e76e..cb03b0c1fd78a 100644 --- a/src/SDL_hashtable.h +++ b/src/SDL_hashtable.h @@ -29,14 +29,14 @@ typedef Uint32 (*SDL_HashTable_HashFn)(const void *key, void *data); typedef SDL_bool (*SDL_HashTable_KeyMatchFn)(const void *a, const void *b, void *data); typedef void (*SDL_HashTable_NukeFn)(const void *key, const void *value, void *data); -SDL_HashTable *SDL_NewHashTable(void *data, - const Uint32 num_buckets, - const SDL_HashTable_HashFn hashfn, - const SDL_HashTable_KeyMatchFn keymatchfn, - const SDL_HashTable_NukeFn nukefn, - const SDL_bool stackable); - -void SDL_FreeHashTable(SDL_HashTable *table); +SDL_HashTable *SDL_CreateHashTable(void *data, + const Uint32 num_buckets, + const SDL_HashTable_HashFn hashfn, + const SDL_HashTable_KeyMatchFn keymatchfn, + const SDL_HashTable_NukeFn nukefn, + const SDL_bool stackable); + +void SDL_DestroyHashTable(SDL_HashTable *table); SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value); SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); From 55a1458ed00644f5fccbeb6b95d4e567240e6284 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 9 Oct 2023 20:28:58 -0400 Subject: [PATCH 019/725] audio: Changes to one logical device must update all sibling logical devices. Fixes #8226. --- src/audio/SDL_audio.c | 56 ++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index cb2736982cc60..f6bdfc83a1faf 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -186,31 +186,27 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) ) ? SDL_TRUE : SDL_FALSE; } -// should hold logdev's physical device's lock before calling. -static void UpdateAudioStreamFormatsLogical(SDL_LogicalAudioDevice *logdev) +// should hold device->lock before calling. +static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) { - SDL_AudioDevice *device = logdev->physical_device; const SDL_bool iscapture = device->iscapture; + const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device); SDL_AudioSpec spec; + + device->simple_copy = simple_copy; SDL_copyp(&spec, &device->spec); - if (!AudioDeviceCanUseSimpleCopy(device)) { + if (!simple_copy) { spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format. } - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { - // set the proper end of the stream to the device's format. - // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. - SDL_LockMutex(stream->lock); - SDL_copyp(iscapture ? &stream->src_spec : &stream->dst_spec, &spec); - SDL_UnlockMutex(stream->lock); - } -} - -// should hold device->lock before calling. -static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) -{ for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - UpdateAudioStreamFormatsLogical(logdev); + for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + // set the proper end of the stream to the device's format. + // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. + SDL_LockMutex(stream->lock); + SDL_copyp(iscapture ? &stream->src_spec : &stream->dst_spec, &spec); + SDL_UnlockMutex(stream->lock); + } } } @@ -276,8 +272,7 @@ static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) SDL_UnlockMutex(stream->lock); } - logdev->physical_device->simple_copy = AudioDeviceCanUseSimpleCopy(logdev->physical_device); - + UpdateAudioStreamFormatsPhysical(logdev->physical_device); SDL_free(logdev); } @@ -1514,7 +1509,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp device->logical_devices->prev = logdev; } device->logical_devices = logdev; - device->simple_copy = AudioDeviceCanUseSimpleCopy(device); + UpdateAudioStreamFormatsPhysical(device); } SDL_UnlockMutex(device->lock); } @@ -1529,7 +1524,6 @@ static int SetLogicalAudioDevicePauseState(SDL_AudioDeviceID devid, int value) return -1; // ObtainLogicalAudioDevice will have set an error. } SDL_AtomicSet(&logdev->paused, value); - logdev->physical_device->simple_copy = AudioDeviceCanUseSimpleCopy(logdev->physical_device); SDL_UnlockMutex(logdev->physical_device->lock); return 0; } @@ -1575,9 +1569,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac logdev->postmix_userdata = userdata; } - UpdateAudioStreamFormatsLogical(logdev); - device->simple_copy = AudioDeviceCanUseSimpleCopy(device); - + UpdateAudioStreamFormatsPhysical(device); SDL_UnlockMutex(device->lock); } return retval; @@ -1649,11 +1641,9 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int SDL_UnlockMutex(stream->lock); } - - UpdateAudioStreamFormatsLogical(logdev); } - device->simple_copy = AudioDeviceCanUseSimpleCopy(device); + UpdateAudioStreamFormatsPhysical(device); SDL_UnlockMutex(device->lock); @@ -1725,7 +1715,7 @@ void SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams) stream->bound_device = NULL; SDL_UnlockMutex(stream->lock); if (logdev) { - logdev->physical_device->simple_copy = AudioDeviceCanUseSimpleCopy(logdev->physical_device); + UpdateAudioStreamFormatsPhysical(logdev->physical_device); SDL_UnlockMutex(logdev->physical_device->lock); } } @@ -1767,9 +1757,8 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au SDL_assert(physdevice != NULL); SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. - physdevice->simple_copy = AudioDeviceCanUseSimpleCopy(physdevice); - SDL_UnlockMutex(physdevice->lock); // we don't need to hold the lock for any of this. + const SDL_bool iscapture = physdevice->iscapture; SDL_AudioStream *stream = NULL; @@ -1921,9 +1910,6 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) logdev->next = new_default_device->logical_devices; new_default_device->logical_devices = logdev; - // make sure all our streams are targeting the new device's format. - UpdateAudioStreamFormatsLogical(logdev); - // Post an event for each logical device we moved. if (post_fmt_event) { SDL_Event event; @@ -1936,8 +1922,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) } } - current_default_device->simple_copy = AudioDeviceCanUseSimpleCopy(current_default_device); - new_default_device->simple_copy = AudioDeviceCanUseSimpleCopy(new_default_device); + UpdateAudioStreamFormatsPhysical(current_default_device); + UpdateAudioStreamFormatsPhysical(new_default_device); if (current_default_device->logical_devices == NULL) { // nothing left on the current physical device, close it. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. From 0d68f45879ebf83202da2a7ad7897fe51798d8a6 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 2 Oct 2023 19:43:44 +0100 Subject: [PATCH 020/725] test: Extract SDLTest_ReadSurfacePixel This is essentially the same as was added in d95d2d70, but with clearer error handling. It's implemented in a private header file so that it can be shared with SDL_shape, which also wants this functionality. Resolves: https://github.com/libsdl-org/SDL/issues/8319 Signed-off-by: Simon McVittie --- include/SDL3/SDL_test_compare.h | 21 ++++++++ src/test/SDL_test_compare.c | 48 ++++++++---------- src/video/SDL_surface_pixel_impl.h | 81 ++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 28 deletions(-) create mode 100644 src/video/SDL_surface_pixel_impl.h diff --git a/include/SDL3/SDL_test_compare.h b/include/SDL3/SDL_test_compare.h index 6de16a623df71..f3ac606c3f9f7 100644 --- a/include/SDL3/SDL_test_compare.h +++ b/include/SDL3/SDL_test_compare.h @@ -44,6 +44,27 @@ extern "C" { #endif +/** + * \brief Retrieves a single pixel from a surface. + * + * This function prioritizes correctness over speed: it is suitable for + * unit tests, but is not intended for use in a game engine. + * + * Like SDL_GetRGBA, this uses the entire 0..255 range when converting + * color components from pixel formats with less than 8 bits per RGB + * component. + * + * \param surface The surface + * \param x Horizontal coordinate, 0 <= x < width + * \param y Vertical coordinate, 0 <= y < height + * \param r Pointer to location to store red channel, 0-255 + * \param g Pointer to location to store green channel, 0-255 + * \param b Pointer to location to store blue channel, 0-255 + * \param a Pointer to location to store alpha channel, 0-255 + * \returns 0 if the surface is valid and the coordinates are in-bounds + */ +int SDLTest_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + /** * \brief Compares a surface and with reference image data for equality * diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index bc3c484bdb9c1..1bb5c8b50450c 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -28,28 +28,17 @@ */ #include +#include "../video/SDL_surface_pixel_impl.h" + #define FILENAME_SIZE 128 /* Counter for _CompareSurface calls; used for filename creation when comparisons fail */ static int _CompareSurfaceCount = 0; -static Uint32 -GetPixel(Uint8 *p, size_t bytes_per_pixel) +int +SDLTest_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { - Uint32 ret = 0; - - SDL_assert(bytes_per_pixel <= sizeof(ret)); - - /* Fill the appropriate number of least-significant bytes of ret, - * leaving the most-significant bytes set to zero, so that ret can - * be decoded with SDL_GetRGBA afterwards. */ -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_memcpy(((Uint8 *) &ret) + (sizeof(ret) - bytes_per_pixel), p, bytes_per_pixel); -#else - SDL_memcpy(&ret, p, bytes_per_pixel); -#endif - - return ret; + return SDL_ReadSurfacePixel_impl(surface, x, y, r, g, b, a); } static void @@ -67,8 +56,6 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, { int ret; int i, j; - int bpp, bpp_reference; - Uint8 *p, *p_reference; int dist; int sampleErrorX = 0, sampleErrorY = 0, sampleDist = 0; SDL_Color sampleReference = { 0, 0, 0, 0 }; @@ -104,19 +91,24 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, SDL_LockSurface(referenceSurface); ret = 0; - bpp = surface->format->BytesPerPixel; - bpp_reference = referenceSurface->format->BytesPerPixel; /* Compare image - should be same format. */ for (j = 0; j < surface->h; j++) { for (i = 0; i < surface->w; i++) { - Uint32 pixel; - p = (Uint8 *)surface->pixels + j * surface->pitch + i * bpp; - p_reference = (Uint8 *)referenceSurface->pixels + j * referenceSurface->pitch + i * bpp_reference; - - pixel = GetPixel(p, bpp); - SDL_GetRGBA(pixel, surface->format, &R, &G, &B, &A); - pixel = GetPixel(p_reference, bpp_reference); - SDL_GetRGBA(pixel, referenceSurface->format, &Rd, &Gd, &Bd, &Ad); + int temp; + + temp = SDLTest_ReadSurfacePixel(surface, i, j, &R, &G, &B, &A); + if (temp != 0) { + SDLTest_LogError("Failed to retrieve pixel (%d,%d): %s", i, j, SDL_GetError()); + ret++; + continue; + } + + temp = SDLTest_ReadSurfacePixel(referenceSurface, i, j, &Rd, &Gd, &Bd, &Ad); + if (temp != 0) { + SDLTest_LogError("Failed to retrieve reference pixel (%d,%d): %s", i, j, SDL_GetError()); + ret++; + continue; + } dist = 0; dist += (R - Rd) * (R - Rd); diff --git a/src/video/SDL_surface_pixel_impl.h b/src/video/SDL_surface_pixel_impl.h new file mode 100644 index 0000000000000..591ac1e9eb654 --- /dev/null +++ b/src/video/SDL_surface_pixel_impl.h @@ -0,0 +1,81 @@ +/* + Copyright 1997-2023 Sam Lantinga + Copyright 2023 Collabora Ltd. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL3/SDL.h" + +/* Internal implementation of SDL_ReadSurfacePixel, shared between SDL_shape + * and SDLTest */ +static inline int +SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + Uint32 pixel = 0; + size_t bytes_per_pixel; + void *p; + + if (surface == NULL || surface->format == NULL || surface->pixels == NULL) { + return SDL_InvalidParamError("surface"); + } + + if (x < 0 || x >= surface->w) { + return SDL_InvalidParamError("x"); + } + + if (y < 0 || y >= surface->h) { + return SDL_InvalidParamError("y"); + } + + if (r == NULL) { + return SDL_InvalidParamError("r"); + } + + if (g == NULL) { + return SDL_InvalidParamError("g"); + } + + if (b == NULL) { + return SDL_InvalidParamError("b"); + } + + if (a == NULL) { + return SDL_InvalidParamError("a"); + } + + bytes_per_pixel = surface->format->BytesPerPixel; + + if (bytes_per_pixel > sizeof(pixel)) { + return SDL_InvalidParamError("surface->format->BytesPerPixel"); + } + + SDL_LockSurface(surface); + + p = (Uint8 *)surface->pixels + y * surface->pitch + x * bytes_per_pixel; + /* Fill the appropriate number of least-significant bytes of pixel, + * leaving the most-significant bytes set to zero */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + SDL_memcpy(((Uint8 *) &pixel) + (sizeof(pixel) - bytes_per_pixel), p, bytes_per_pixel); +#else + SDL_memcpy(&pixel, p, bytes_per_pixel); +#endif + SDL_GetRGBA(pixel, surface->format, r, g, b, a); + + SDL_UnlockSurface(surface); + return 0; +} From f5745c3a678fb90c3a9e2bb90a9e882aeb974952 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 2 Oct 2023 19:45:49 +0100 Subject: [PATCH 021/725] surface: Add a private SDL_ReadSurfacePixel This shares its implementation with SDLTest_ReadSurfacePixel: the same code is compiled twice, to get it into the static test library and also the public shared library. Signed-off-by: Simon McVittie --- src/video/SDL_surface.c | 7 +++++++ src/video/SDL_video_c.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 4a5d29853a0cc..fe43b2f26f328 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -23,6 +23,7 @@ #include "SDL_sysvideo.h" #include "SDL_blit.h" #include "SDL_RLEaccel_c.h" +#include "SDL_surface_pixel_impl.h" #include "SDL_pixels_c.h" #include "SDL_yuv_c.h" #include "../render/SDL_sysrender.h" @@ -34,6 +35,12 @@ SDL_COMPILE_TIME_ASSERT(surface_size_assumptions, SDL_COMPILE_TIME_ASSERT(can_indicate_overflow, SDL_SIZE_MAX > SDL_MAX_SINT32); +int +SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + return SDL_ReadSurfacePixel_impl(surface, x, y, r, g, b, a); +} + /* Public routines */ /* diff --git a/src/video/SDL_video_c.h b/src/video/SDL_video_c.h index 6282e770e4537..78f3a3abe9920 100644 --- a/src/video/SDL_video_c.h +++ b/src/video/SDL_video_c.h @@ -57,4 +57,6 @@ extern void SDL_VideoQuit(void); extern int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync); +extern int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + #endif /* SDL_video_c_h_ */ From 04edb38cdf856c367ba1c167f6d485c21bbcfdb1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 2 Oct 2023 19:50:47 +0100 Subject: [PATCH 022/725] shape: Use SDL[Test]_ReadSurfacePixel This avoids assuming that the pixels are suitably aligned for direct access, which there's no guarantee that they are; in particular, 3-bytes-per-pixel RGB images are likely to have 3 out of 4 pixels misaligned. On x86, dereferencing a misaligned pointer does what you would expect, but on other architectures it's undefined whether it will work, crash with SIGBUS, or silently give a wrong answer. Signed-off-by: Simon McVittie --- src/video/SDL_shape.c | 44 +++++++------------------------------------ test/testshape.c | 22 ++++------------------ 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index 3082c1bdcfb9f..cbbfa7e61621b 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -22,6 +22,7 @@ #include "SDL_sysvideo.h" #include "SDL_shape_internals.h" +#include "SDL_video_c.h" SDL_Window *SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags) { @@ -60,8 +61,7 @@ void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint int x = 0; int y = 0; Uint8 r = 0, g = 0, b = 0, alpha = 0; - Uint8 *pixel = NULL; - Uint32 pixel_value = 0, mask_value = 0; + Uint32 mask_value = 0; size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb; Uint8 *bitmap_scanline; SDL_Color key; @@ -75,24 +75,10 @@ void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint for (y = 0; y < shape->h; y++) { bitmap_scanline = bitmap + y * bytes_per_scanline; for (x = 0; x < shape->w; x++) { - alpha = 0; - pixel_value = 0; - pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel); - switch (shape->format->BytesPerPixel) { - case (1): - pixel_value = *pixel; - break; - case (2): - pixel_value = *(Uint16 *)pixel; - break; - case (3): - pixel_value = *(Uint32 *)pixel & (~shape->format->Amask); - break; - case (4): - pixel_value = *(Uint32 *)pixel; - break; + if (SDL_ReadSurfacePixel(shape, x, y, &r, &g, &b, &alpha) != 0) { + continue; } - SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha); + switch (mode.mode) { case (ShapeModeDefault): mask_value = (alpha >= 1 ? 1 : 0); @@ -120,8 +106,6 @@ void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions) { int x = 0, y = 0; - Uint8 *pixel = NULL; - Uint32 pixel_value = 0; Uint8 r = 0, g = 0, b = 0, a = 0; SDL_bool pixel_opaque = SDL_FALSE; int last_opaque = -1; @@ -136,23 +120,9 @@ static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SD for (y = dimensions.y; y < dimensions.y + dimensions.h; y++) { for (x = dimensions.x; x < dimensions.x + dimensions.w; x++) { - pixel_value = 0; - pixel = (Uint8 *)(mask->pixels) + (y * mask->pitch) + (x * mask->format->BytesPerPixel); - switch (mask->format->BytesPerPixel) { - case (1): - pixel_value = *pixel; - break; - case (2): - pixel_value = *(Uint16 *)pixel; - break; - case (3): - pixel_value = *(Uint32 *)pixel & (~mask->format->Amask); - break; - case (4): - pixel_value = *(Uint32 *)pixel; - break; + if (SDL_ReadSurfacePixel(mask, x, y, &r, &g, &b, &a) != 0) { + continue; } - SDL_GetRGBA(pixel_value, mask->format, &r, &g, &b, &a); switch (mode.mode) { case (ShapeModeDefault): pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE); diff --git a/test/testshape.c b/test/testshape.c index 078319794a993..6965b3aca73e8 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -42,8 +42,7 @@ static void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shap int x = 0; int y = 0; Uint8 r = 0, g = 0, b = 0, alpha = 0; - Uint8 *pixel = NULL; - Uint32 pixel_value = 0, mask_value = 0; + Uint32 mask_value = 0; size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb; Uint8 *bitmap_scanline; SDL_Color key; @@ -58,23 +57,10 @@ static void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shap bitmap_scanline = bitmap + y * bytes_per_scanline; for (x = 0; x < shape->w; x++) { alpha = 0; - pixel_value = 0; - pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel); - switch (shape->format->BytesPerPixel) { - case (1): - pixel_value = *pixel; - break; - case (2): - pixel_value = *(Uint16 *)pixel; - break; - case (3): - pixel_value = *(Uint32 *)pixel & (~shape->format->Amask); - break; - case (4): - pixel_value = *(Uint32 *)pixel; - break; + if (SDLTest_ReadSurfacePixel(shape, x, y, &r, &g, &b, &alpha) != 0) { + continue; } - SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha); + switch (mode.mode) { case (ShapeModeDefault): mask_value = (alpha >= 1 ? 1 : 0); From 3698630bbc8e2ac501127c9c522cc0463a6c1565 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 29 Sep 2023 15:49:24 +0100 Subject: [PATCH 023/725] pixels: Document the naming convention Whenever I have to fix something endianness-related, I always get confused about whether the byte-oriented format that guarantees to put red in byte 0 is RGBA8888 or RGBA32. (The answer is that it's RGBA32.) Signed-off-by: Simon McVittie --- include/SDL3/SDL_pixels.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 6da0b93a8b134..82d4feb338006 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -23,6 +23,42 @@ * \file SDL_pixels.h * * \brief Header for the enumerated pixel format definitions. + * + * SDL's pixel formats have the following naming convention: + * + * * Names with a list of components and a single bit count, such as + * RGB24 and ABGR32, define a platform-independent encoding into + * bytes in the order specified. For example, in RGB24 data, each + * pixel is encoded in 3 bytes (red, green, blue) in that order, + * and in ABGR32 data, each pixel is encoded in 4 bytes + * (alpha, blue, green, red) in that order. Use these names if the + * property of a format that is important to you is the order of + * the bytes in memory or on disk. + * + * * Names with a bit count per component, such as ARGB8888 and + * XRGB1555, are "packed" into an appropriately-sized integer in + * the platform's native endianness. For example, ARGB8888 is + * a sequence of 32-bit integers; in each integer, the most + * significant bits are alpha, and the least significant bits are + * blue. On a little-endian CPU such as x86, the least significant + * bits of each integer are arranged first in memory, but on a + * big-endian CPU such as s390x, the most significant bits are + * arranged first. Use these names if the property of a format that + * is important to you is the meaning of each bit position within a + * native-endianness integer. + * + * * In indexed formats such as INDEX4LSB, each pixel is represented + * by encoding an index into the palette into the indicated number + * of bits, with multiple pixels packed into each byte if appropriate. + * In LSB formats, the first (leftmost) pixel is stored in the + * least-significant bits of the byte; in MSB formats, it's stored + * in the most-significant bits. INDEX8 does not need LSB/MSB + * variants, because each pixel exactly fills one byte. + * + * The 32-bit byte-array encodings such as RGBA32 are aliases for the + * appropriate 8888 encoding for the current platform. For example, + * RGBA32 is an alias for ABGR8888 on little-endian CPUs like x86, + * or an alias for RGBA8888 on big-endian CPUs. */ #ifndef SDL_pixels_h_ From d88bf687a8b2825bfb81fa253e30e2fde60b7bf7 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 29 Sep 2023 15:54:32 +0100 Subject: [PATCH 024/725] surface: Document the in-memory layout of the pixels I don't think we ever explicitly said this. Signed-off-by: Simon McVittie --- include/SDL3/SDL_surface.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index bdba4d07f3f24..6bf4b1d94c8b8 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -66,8 +66,22 @@ typedef struct SDL_BlitMap SDL_BlitMap; /* this is an opaque type. */ /** * \brief A collection of pixels used in software blitting. * + * Pixels are arranged in memory in rows, with the top row first. + * Each row occupies an amount of memory given by the pitch (sometimes + * known as the row stride in non-SDL APIs). + * + * Within each row, pixels are arranged from left to right until the + * width is reached. + * Each pixel occupies a number of bits appropriate for its format, with + * most formats representing each pixel as one or more whole bytes + * (in some indexed formats, instead multiple pixels are packed into + * each byte), and a byte order given by the format. + * After encoding all pixels, any remaining bytes to reach the pitch are + * used as padding to reach a desired alignment, and have undefined contents. + * * \note This structure should be treated as read-only, except for \c pixels, * which, if not NULL, contains the raw pixel data for the surface. + * \sa SDL_CreateSurfaceFrom */ typedef struct SDL_Surface { From 88f2fb9dcf5a55d2c5932ab28b492bac9ad5e062 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 7 Oct 2023 02:01:35 -0700 Subject: [PATCH 025/725] Added an example of video decoding with ffmpeg --- cmake/FindFFmpeg.cmake | 151 +++++++++++ test/CMakeLists.txt | 10 + test/testspriteffmpeg.c | 555 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 716 insertions(+) create mode 100644 cmake/FindFFmpeg.cmake create mode 100644 test/testspriteffmpeg.c diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake new file mode 100644 index 0000000000000..ce5c3b9fc9bfd --- /dev/null +++ b/cmake/FindFFmpeg.cmake @@ -0,0 +1,151 @@ +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionally set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVFILTER +# - AVUTIL +# - POSTPROC +# - SWSCALE +# the following variables will be defined +# _FOUND - System has +# _INCLUDE_DIRS - Include directory necessary for using the headers +# _LIBRARIES - Link these to use +# _DEFINITIONS - Compiler switches required for using +# _VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(FindPackageHandleStandardArgs) + +# The default components were taken from a survey over other FindFFMPEG.cmake files +if (NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) +endif () + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component ) + if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + # message(STATUS " - ${_component} found.") + set(${_component}_FOUND TRUE) + else () + # message(STATUS " - ${_component} not found.") + endif () +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + + if (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + endif () + endif (NOT WIN32) + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + ${PC_${_component}_INCLUDEDIR} + ${PC_${_component}_INCLUDE_DIRS} + PATH_SUFFIXES + ffmpeg + ) + + find_library(${_component}_LIBRARIES NAMES ${_library} + HINTS + ${PC_${_component}_LIBDIR} + ${PC_${_component}_LIBRARY_DIRS} + ) + + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + + set_component_found(${_component}) + + mark_as_advanced( + ${_component}_INCLUDE_DIRS + ${_component}_LIBRARIES + ${_component}_DEFINITIONS + ${_component}_VERSION) + +endmacro() + + +# Check for cached results. If there are skip the costly part. +if (NOT FFMPEG_LIBRARIES) + + # Check for all possible component. + find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) + find_component(AVFORMAT libavformat avformat libavformat/avformat.h) + find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) + find_component(AVUTIL libavutil avutil libavutil/avutil.h) + find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) + find_component(SWSCALE libswscale swscale libswscale/swscale.h) + find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) + find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) + + # Check if the required components were found and add their stuff to the FFMPEG_* vars. + foreach (_component ${FFmpeg_FIND_COMPONENTS}) + if (${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else () + # message(STATUS "Required component ${_component} missing.") + endif () + endforeach () + + # Build the include path with duplicates removed. + if (FFMPEG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) + endif () + + # cache the vars. + set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) + + mark_as_advanced(FFMPEG_INCLUDE_DIRS + FFMPEG_LIBRARIES + FFMPEG_DEFINITIONS) + +endif () + +# Now set the noncached _FOUND vars for the components. +foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) +foreach (_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach () + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9f65a59efc8ca..2c79df9b09711 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -182,6 +182,16 @@ if(HAVE_LIBUDEV_H) add_definitions(-DHAVE_LIBUDEV_H) endif() +set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) +include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") +if(FFMPEG_FOUND) + add_sdl_test_executable(testspriteffmpeg NO_C90 SOURCES testspriteffmpeg.c ${icon_bmp_header}) + target_include_directories(testspriteffmpeg PRIVATE ${FFMPEG_INCLUDE_DIRS}) + target_link_libraries(testspriteffmpeg PRIVATE ${FFMPEG_LIBRARIES}) +else() + message(STATUS "Cannot find ffmpeg, skipping testspriteffmpeg") +endif() + add_sdl_test_executable(checkkeys SOURCES checkkeys.c) add_sdl_test_executable(checkkeysthreads SOURCES checkkeysthreads.c) add_sdl_test_executable(loopwave NEEDS_RESOURCES TESTUTILS SOURCES loopwave.c) diff --git a/test/testspriteffmpeg.c b/test/testspriteffmpeg.c new file mode 100644 index 0000000000000..e251b675db3d2 --- /dev/null +++ b/test/testspriteffmpeg.c @@ -0,0 +1,555 @@ +/* + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ +/* Simple program: Display a video with a sprite bouncing around over it + * + * For a more complete video example, see ffplay.c in the ffmpeg sources. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "icon.h" + +#define WINDOW_WIDTH 640 +#define WINDOW_HEIGHT 480 + +static SDL_Texture *sprite; +static SDL_FRect position; +static SDL_FRect velocity; +static int sprite_w, sprite_h; + +static SDL_Window *window; +static SDL_Renderer *renderer; +static SDL_AudioStream *audio; +static SDL_Texture *video_texture; +static SDL_PixelFormatEnum video_format; +static int video_width; +static int video_height; +static Uint64 video_start; +static struct SwsContext *video_conversion_context; +static int done; + +static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) { + SDL_Texture *texture = NULL; + SDL_Surface *surface; + SDL_RWops *src = SDL_RWFromConstMem(data, len); + if (src) { + surface = SDL_LoadBMP_RW(src, SDL_TRUE); + if (surface) { + /* Treat white as transparent */ + SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255)); + + texture = SDL_CreateTextureFromSurface(r, surface); + *w = surface->w; + *h = surface->h; + SDL_DestroySurface(surface); + } + } + return texture; +} + +static void MoveSprite(void) +{ + int max_w, max_h; + + SDL_GetCurrentRenderOutputSize(renderer, &max_w, &max_h); + + /* Move the sprite, bounce at the wall, and draw */ + position.x += velocity.x; + if ((position.x < 0) || (position.x >= (max_w - sprite_w))) { + velocity.x = -velocity.x; + position.x += velocity.x; + } + position.y += velocity.y; + if ((position.y < 0) || (position.y >= (max_h - sprite_h))) { + velocity.y = -velocity.y; + position.y += velocity.y; + } + + /* Blit the sprite onto the screen */ + SDL_RenderTexture(renderer, sprite, NULL, &position); +} + +static AVCodecContext *OpenStream(AVFormatContext *ic, int stream) +{ + AVCodecContext *context; + const AVCodec *codec; + int result; + + context = avcodec_alloc_context3(NULL); + if (!context) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_alloc_context3 failed"); + return NULL; + } + + if (avcodec_parameters_to_context(context, ic->streams[stream]->codecpar) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_parameters_to_context failed"); + avcodec_free_context(&context); + return NULL; + } + context->pkt_timebase = ic->streams[stream]->time_base; + + codec = avcodec_find_decoder(context->codec_id); + if (!codec) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find codec %s", avcodec_get_name(context->codec_id)); + avcodec_free_context(&context); + return NULL; + } + + context->codec_id = codec->id; + result = avcodec_open2(context, codec, NULL); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open codec %s: %s", avcodec_get_name(context->codec_id), av_err2str(result)); + avcodec_free_context(&context); + return NULL; + } + + return context; +} + +static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream) +{ + AVStream *st = ic->streams[stream]; + AVCodecParameters *codecpar = st->codecpar; + AVCodecContext *context = OpenStream(ic, stream); + + if (context) { + SDL_Log("Audio stream: %s %d channels, %d Hz\n", avcodec_get_name(context->codec_id), codecpar->ch_layout.nb_channels, codecpar->sample_rate); + + SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate }; + audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); + if (audio) { + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio)); + } else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s", SDL_GetError()); + } + } + return context; +} + +static SDL_AudioFormat GetAudioFormat(enum AVSampleFormat format) +{ + switch (format) { + case AV_SAMPLE_FMT_U8: + case AV_SAMPLE_FMT_U8P: + return SDL_AUDIO_U8; + case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_S16P: + return SDL_AUDIO_S16; + case AV_SAMPLE_FMT_S32: + case AV_SAMPLE_FMT_S32P: + return SDL_AUDIO_S32; + case AV_SAMPLE_FMT_FLT: + case AV_SAMPLE_FMT_FLTP: + return SDL_AUDIO_F32; + default: + /* Unsupported */ + return 0; + } +} + +static SDL_bool IsPlanarAudioFormat(enum AVSampleFormat format) +{ + switch (format) { + case AV_SAMPLE_FMT_U8P: + case AV_SAMPLE_FMT_S16P: + case AV_SAMPLE_FMT_S32P: + case AV_SAMPLE_FMT_FLTP: + case AV_SAMPLE_FMT_DBLP: + case AV_SAMPLE_FMT_S64P: + return SDL_TRUE; + default: + return SDL_FALSE; + } +} + +static void InterleaveAudio(AVFrame *frame, const SDL_AudioSpec *spec) +{ + int samplesize = SDL_AUDIO_BYTESIZE(spec->format); + int framesize = SDL_AUDIO_FRAMESIZE(*spec); + Uint8 *data = (Uint8 *)SDL_malloc(frame->nb_samples * framesize); + if (!data) { + return; + } + + /* This could be optimized with SIMD and not allocating memory each time */ + for (int c = 0; c < spec->channels; ++c) { + const Uint8 *src = frame->data[c]; + Uint8 *dst = data + c * samplesize; + for (int n = frame->nb_samples; n--; ) { + SDL_memcpy(dst, src, samplesize); + src += samplesize; + dst += framesize; + } + } + SDL_PutAudioStreamData(audio, data, frame->nb_samples * framesize); + SDL_free(data); +} + +static void HandleAudioFrame(AVFrame *frame) +{ + if (audio) { + SDL_AudioSpec spec = { GetAudioFormat(frame->format), frame->ch_layout.nb_channels, frame->sample_rate }; + SDL_SetAudioStreamFormat(audio, &spec, NULL); + + if (frame->ch_layout.nb_channels > 1 && IsPlanarAudioFormat(frame->format)) { + InterleaveAudio(frame, &spec); + } else { + SDL_PutAudioStreamData(audio, frame->data[0], frame->nb_samples * SDL_AUDIO_FRAMESIZE(spec)); + } + } +} + +static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream) +{ + AVStream *st = ic->streams[stream]; + AVCodecParameters *codecpar = st->codecpar; + AVCodecContext *context = OpenStream(ic, stream); + + if (context) { + SDL_Log("Video stream: %s %dx%d\n", avcodec_get_name(context->codec_id), codecpar->width, codecpar->height); + SDL_SetWindowSize(window, codecpar->width, codecpar->height); + } + return context; +} + +static SDL_PixelFormatEnum GetVideoFormat(enum AVPixelFormat format) +{ + switch (format) { + case AV_PIX_FMT_RGB8: + return SDL_PIXELFORMAT_RGB332; + case AV_PIX_FMT_RGB444: + return SDL_PIXELFORMAT_RGB444; + case AV_PIX_FMT_RGB555: + return SDL_PIXELFORMAT_RGB555; + case AV_PIX_FMT_BGR555: + return SDL_PIXELFORMAT_BGR555; + case AV_PIX_FMT_RGB565: + return SDL_PIXELFORMAT_RGB565; + case AV_PIX_FMT_BGR565: + return SDL_PIXELFORMAT_BGR565; + case AV_PIX_FMT_RGB24: + return SDL_PIXELFORMAT_RGB24; + case AV_PIX_FMT_BGR24: + return SDL_PIXELFORMAT_BGR24; + case AV_PIX_FMT_0RGB32: + return SDL_PIXELFORMAT_XRGB8888; + case AV_PIX_FMT_0BGR32: + return SDL_PIXELFORMAT_XBGR8888; + case AV_PIX_FMT_NE(RGB0, 0BGR): + return SDL_PIXELFORMAT_RGBX8888; + case AV_PIX_FMT_NE(BGR0, 0RGB): + return SDL_PIXELFORMAT_BGRX8888; + case AV_PIX_FMT_RGB32: + return SDL_PIXELFORMAT_ARGB8888; + case AV_PIX_FMT_RGB32_1: + return SDL_PIXELFORMAT_RGBA8888; + case AV_PIX_FMT_BGR32: + return SDL_PIXELFORMAT_ABGR8888; + case AV_PIX_FMT_BGR32_1: + return SDL_PIXELFORMAT_BGRA8888; + case AV_PIX_FMT_YUV420P: + return SDL_PIXELFORMAT_IYUV; + case AV_PIX_FMT_YUYV422: + return SDL_PIXELFORMAT_YUY2; + case AV_PIX_FMT_UYVY422: + return SDL_PIXELFORMAT_UYVY; + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +static void SetYUVConversionMode(AVFrame *frame) +{ + SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC; + if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) { + if (frame->color_range == AVCOL_RANGE_JPEG) + mode = SDL_YUV_CONVERSION_JPEG; + else if (frame->colorspace == AVCOL_SPC_BT709) + mode = SDL_YUV_CONVERSION_BT709; + else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M) + mode = SDL_YUV_CONVERSION_BT601; + } + SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */ +} + +static void HandleVideoFrame(AVFrame *frame, double pts) +{ + SDL_RendererFlip flip = SDL_FLIP_NONE; + + /* Update the video texture */ + SDL_PixelFormatEnum format = GetVideoFormat(frame->format); + if (!video_texture || format != video_format || frame->width != video_width || frame->height != video_height) { + if (video_texture) { + SDL_DestroyTexture(video_texture); + } + + if (format == SDL_PIXELFORMAT_UNKNOWN) { + video_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + } else { + video_texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + } + video_format = format; + video_width = frame->width; + video_height = frame->height; + } + + switch (format) { + case SDL_PIXELFORMAT_UNKNOWN: + video_conversion_context = sws_getCachedContext(video_conversion_context, + frame->width, frame->height, frame->format, frame->width, frame->height, + AV_PIX_FMT_BGRA, SWS_POINT, NULL, NULL, NULL); + if (video_conversion_context != NULL) { + uint8_t *pixels[4]; + int pitch[4]; + if (SDL_LockTexture(video_texture, NULL, (void **)pixels, pitch) == 0) { + sws_scale(video_conversion_context, (const uint8_t * const *)frame->data, frame->linesize, + 0, frame->height, pixels, pitch); + SDL_UnlockTexture(video_texture); + } + } + break; + case SDL_PIXELFORMAT_IYUV: + if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { + SDL_UpdateYUVTexture(video_texture, NULL, frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2]); + } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { + SDL_UpdateYUVTexture(video_texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0], + frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], + frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + flip = SDL_FLIP_VERTICAL; + } + SetYUVConversionMode(frame); + break; + default: + if (frame->linesize[0] < 0) { + SDL_UpdateTexture(video_texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + flip = SDL_FLIP_VERTICAL; + } else { + SDL_UpdateTexture(video_texture, NULL, frame->data[0], frame->linesize[0]); + } + break; + } + + /* Quick and dirty PTS handling */ + if (!video_start) { + video_start = SDL_GetTicks(); + } + double now = (double)(SDL_GetTicks() - video_start) / 1000.0; + while (now < pts - 0.001) { + SDL_Delay(1); + now = (double)(SDL_GetTicks() - video_start) / 1000.0; + } + + SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, flip); + MoveSprite(); + SDL_RenderPresent(renderer); +} + +int main(int argc, char *argv[]) +{ + AVFormatContext *ic = NULL; + int audio_stream = -1; + int video_stream = -1; + AVCodecContext *audio_context = NULL; + AVCodecContext *video_context = NULL; + AVPacket *pkt = NULL; + AVFrame *frame = NULL; + double first_pts = -1.0; + int result; + int return_code = -1; + SDL_bool flushing = SDL_FALSE; + SDL_bool decoded = SDL_FALSE; + + /* Enable standard application logging */ + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + if (argc != 2) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s video_file\n", argv[0]); + return_code = 1; + goto quit; + } + + if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0) { + return_code = 2; + goto quit; + } + + if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer) < 0) { + return_code = 2; + goto quit; + } + + if (SDL_SetWindowTitle(window, argv[1]) < 0) { + SDL_Log("SDL_SetWindowTitle: %s", SDL_GetError()); + } + + /* Open the media file */ + result = avformat_open_input(&ic, argv[1], NULL, NULL); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open %s: %d", argv[1], result); + return_code = 4; + goto quit; + } + video_stream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); + if (video_stream >= 0) { + video_context = OpenVideoStream(ic, video_stream); + if (!video_context) { + return_code = 4; + goto quit; + } + } + audio_stream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, video_stream, NULL, 0); + if (audio_stream >= 0) { + audio_context = OpenAudioStream(ic, audio_stream); + if (!audio_context) { + return_code = 4; + goto quit; + } + } + pkt = av_packet_alloc(); + if (!pkt) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "av_packet_alloc failed"); + return_code = 4; + goto quit; + } + frame = av_frame_alloc(); + if (!frame) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "av_frame_alloc failed"); + return_code = 4; + goto quit; + } + + /* Create the sprite */ + sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h); + + if (sprite == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture (%s)", SDL_GetError()); + return_code = 3; + goto quit; + } + + /* Initialize the sprite position */ + int max_w, max_h; + SDL_GetCurrentRenderOutputSize(renderer, &max_w, &max_h); + srand((unsigned int)time(NULL)); + position.x = (float)(rand() % (max_w - sprite_w)); + position.y = (float)(rand() % (max_h - sprite_h)); + position.w = (float)sprite_w; + position.h = (float)sprite_h; + velocity.x = 0.0f; + velocity.y = 0.0f; + while (!velocity.x || !velocity.y) { + velocity.x = (float)((rand() % (2 + 1)) - 1); + velocity.y = (float)((rand() % (2 + 1)) - 1); + } + + /* Main render loop */ + done = 0; + + while (!done) { + SDL_Event event; + + /* Check for events */ + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT || event.type == SDL_EVENT_KEY_DOWN) { + done = 1; + } + } + + if (!flushing) { + result = av_read_frame(ic, pkt); + if (result < 0) { + SDL_Log("End of stream, finishing decode\n"); + if (audio_context) { + avcodec_flush_buffers(audio_context); + } + if (video_context) { + avcodec_flush_buffers(video_context); + } + flushing = SDL_TRUE; + } else { + if (pkt->stream_index == audio_stream) { + result = avcodec_send_packet(audio_context, pkt); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_send_packet(audio_context) failed: %s", av_err2str(result)); + } + } else if (pkt->stream_index == video_stream) { + result = avcodec_send_packet(video_context, pkt); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_send_packet(video_context) failed: %s", av_err2str(result)); + } + } + av_packet_unref(pkt); + } + } + + decoded = SDL_FALSE; + if (audio_context) { + while (avcodec_receive_frame(audio_context, frame) >= 0) { + HandleAudioFrame(frame); + decoded = SDL_TRUE; + } + if (flushing) { + /* Let SDL know we're done sending audio */ + SDL_FlushAudioStream(audio); + } + } + if (video_context) { + while (avcodec_receive_frame(video_context, frame) >= 0) { + double pts = ((double)frame->pts * video_context->pkt_timebase.num) / video_context->pkt_timebase.den; + if (first_pts < 0.0) { + first_pts = pts; + } + pts -= first_pts; + + HandleVideoFrame(frame, pts); + decoded = SDL_TRUE; + } + } else { + /* Update video rendering */ + SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); + SDL_RenderClear(renderer); + MoveSprite(); + SDL_RenderPresent(renderer); + } + + if (flushing && !decoded) { + if (SDL_GetAudioStreamQueued(audio) > 0) { + /* Wait a little bit for the audio to finish */ + SDL_Delay(10); + } else { + done = 1; + } + } + } + return_code = 0; +quit: + av_frame_free(&frame); + av_packet_free(&pkt); + avcodec_free_context(&audio_context); + avcodec_free_context(&video_context); + avformat_close_input(&ic); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return return_code; +} From ebf5e08fa1ca9ee784ccf27341243f8f1bbd0c80 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sat, 7 Oct 2023 18:20:24 +0200 Subject: [PATCH 026/725] cmake: use *_STATIC_* variables when linking to a static ffmpeg --- .github/workflows/vita.yml | 5 ++ cmake/FindFFmpeg.cmake | 173 +++++++++++++++++------------------- cmake/PkgConfigHelper.cmake | 5 -- test/CMakeLists.txt | 3 +- 4 files changed, 86 insertions(+), 100 deletions(-) diff --git a/.github/workflows/vita.yml b/.github/workflows/vita.yml index 32d7f4d57ca19..6c8f14a5bc836 100644 --- a/.github/workflows/vita.yml +++ b/.github/workflows/vita.yml @@ -87,6 +87,11 @@ jobs: run: | cp -rv /vita/dependencies/* ${VITASDK}/arm-vita-eabi + - name: Fix vita.toolchain.cmake + run: | + # cache PKG_CONFIG_PATH + sed -i -E 's/set\( PKG_CONFIG_EXECUTABLE "\$\{VITASDK}\/bin\/arm-vita-eabi-pkg-config" )/set( PKG_CONFIG_EXECUTABLE "${VITASDK}\/bin\/arm-vita-eabi-pkg-config" CACHE PATH "Path of pkg-config executable" )/' ${VITASDK}/share/vita.toolchain.cmake + - name: Configure (CMake) run: | cmake -S . -B build -G Ninja \ diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake index ce5c3b9fc9bfd..62950c011846f 100644 --- a/cmake/FindFFmpeg.cmake +++ b/cmake/FindFFmpeg.cmake @@ -1,11 +1,8 @@ -# vim: ts=2 sw=2 # - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) # # Once done this will define # FFMPEG_FOUND - System has the all required components. -# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. # FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. -# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. # # For each of the components it will additionally set. # - AVCODEC @@ -15,40 +12,35 @@ # - AVUTIL # - POSTPROC # - SWSCALE +# the following target will be defined +# FFmpeg::SDL:: - link to this target to # the following variables will be defined -# _FOUND - System has -# _INCLUDE_DIRS - Include directory necessary for using the headers -# _LIBRARIES - Link these to use -# _DEFINITIONS - Compiler switches required for using -# _VERSION - The components version +# FFmpeg__FOUND - System has +# FFmpeg__INCLUDE_DIRS - Include directory necessary for using the headers +# FFmpeg__LIBRARIES - Link these to use +# FFmpeg__DEFINITIONS - Compiler switches required for using +# FFmpeg__VERSION - The components version # # Copyright (c) 2006, Matthias Kretz, # Copyright (c) 2008, Alexander Neundorf, # Copyright (c) 2011, Michael Jansen, +# Copyright (c) 2023, Sam lantinga, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(FindPackageHandleStandardArgs) +include("${CMAKE_CURRENT_LIST_DIR}/PkgConfigHelper.cmake") # The default components were taken from a survey over other FindFFMPEG.cmake files -if (NOT FFmpeg_FIND_COMPONENTS) +if(NOT FFmpeg_FIND_COMPONENTS) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) -endif () + foreach(_component IN LISTS FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_REQUIRED_${_component} TRUE) + endforeach() +endif() -# -### Macro: set_component_found -# -# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. -# -macro(set_component_found _component ) - if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) - # message(STATUS " - ${_component} found.") - set(${_component}_FOUND TRUE) - else () - # message(STATUS " - ${_component} not found.") - endif () -endmacro() +find_package(PkgConfig QUIET) # ### Macro: find_component @@ -58,94 +50,89 @@ endmacro() # macro(find_component _component _pkgconfig _library _header) - if (NOT WIN32) - # use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(PC_${_component} ${_pkgconfig}) - endif () - endif (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} QUIET ${_pkgconfig}) + endif() - find_path(${_component}_INCLUDE_DIRS ${_header} + find_path(FFmpeg_${_component}_INCLUDE_DIRS + NAMES ${_header} HINTS - ${PC_${_component}_INCLUDEDIR} ${PC_${_component}_INCLUDE_DIRS} PATH_SUFFIXES ffmpeg ) - find_library(${_component}_LIBRARIES NAMES ${_library} - HINTS - ${PC_${_component}_LIBDIR} + find_library(FFmpeg_${_component}_LIBRARY + NAMES ${_library} + HINTS ${PC_${_component}_LIBRARY_DIRS} ) - set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") - set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + if(FFmpeg_${_component}_INCLUDE_DIRS AND FFmpeg_${_component}_LIBRARY) + set(FFmpeg_${_component}_FOUND TRUE) + endif() - set_component_found(${_component}) + if(PC_${_component}_FOUND) + get_flags_from_pkg_config("${FFmpeg_${_component}_LIBRARY}" "PC_${_component}" "${_component}") + endif() - mark_as_advanced( - ${_component}_INCLUDE_DIRS - ${_component}_LIBRARIES - ${_component}_DEFINITIONS - ${_component}_VERSION) + set(FFmpeg_${_component}_VERSION "${PC_${_component}_VERSION}") -endmacro() + set(FFmpeg_${_component}_COMPILE_OPTIONS "${${_component}_options}" CACHE STRING "Extra compile options of FFmpeg ${_component}") + set(FFmpeg_${_component}_LIBRARIES "${${_component}_link_libraries}" CACHE STRING "Extra link libraries of FFmpeg ${_component}") -# Check for cached results. If there are skip the costly part. -if (NOT FFMPEG_LIBRARIES) - - # Check for all possible component. - find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) - find_component(AVFORMAT libavformat avformat libavformat/avformat.h) - find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) - find_component(AVUTIL libavutil avutil libavutil/avutil.h) - find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) - find_component(SWSCALE libswscale swscale libswscale/swscale.h) - find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) - find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) - - # Check if the required components were found and add their stuff to the FFMPEG_* vars. - foreach (_component ${FFmpeg_FIND_COMPONENTS}) - if (${_component}_FOUND) - # message(STATUS "Required component ${_component} present.") - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) - set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) - list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) - else () - # message(STATUS "Required component ${_component} missing.") - endif () - endforeach () - - # Build the include path with duplicates removed. - if (FFMPEG_INCLUDE_DIRS) - list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) - endif () - - # cache the vars. - set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) - set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) - - mark_as_advanced(FFMPEG_INCLUDE_DIRS - FFMPEG_LIBRARIES - FFMPEG_DEFINITIONS) - -endif () - -# Now set the noncached _FOUND vars for the components. -foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE) - set_component_found(${_component}) -endforeach () + set(FFmpeg_${_component}_LINK_OPTIONS "${${_component}_link_options}" CACHE STRING "Extra link flags of FFmpeg ${_component}") + + set(FFmpeg_${_component}_LINK_DIRECTORIES "${${_component}_link_directories}" CACHE PATH "Extra link directories of FFmpeg ${_component}") + + mark_as_advanced( + FFmpeg_${_component}_INCLUDE_DIRS + FFmpeg_${_component}_LIBRARY + FFmpeg_${_component}_COMPILE_OPTIONS + FFmpeg_${_component}_LIBRARIES + FFmpeg_${_component}_LINK_OPTIONS + FFmpeg_${_component}_LINK_DIRECTORIES + ) +endmacro() + +# Check for all possible component. +find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) +find_component(AVFORMAT libavformat avformat libavformat/avformat.h) +find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) +find_component(AVUTIL libavutil avutil libavutil/avutil.h) +find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) +find_component(SWSCALE libswscale swscale libswscale/swscale.h) +find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) +find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) # Compile the list of required vars -set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) -foreach (_component ${FFmpeg_FIND_COMPONENTS}) - list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +set(_FFmpeg_REQUIRED_VARS) +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_${_component}_INCLUDE_DIRS FFmpeg_${_component}_LIBRARY) endforeach () # Give a nice error message if some of the required vars are missing. find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) + +set(FFMPEG_LIBRARIES) +if(FFmpeg_FOUND) + foreach(_component IN LISTS FFmpeg_FIND_COMPONENTS) + if(FFmpeg_${_component}_FOUND) + list(APPEND FFMPEG_LIBRARIES FFmpeg::SDL::${_component}) + if(NOT TARGET FFmpeg::SDL::${_component}) + add_library(FFmpeg::SDL::${_component} UNKNOWN IMPORTED) + set_target_properties(FFmpeg::SDL::${_component} PROPERTIES + IMPORTED_LOCATION "${FFmpeg_${_component}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${FFmpeg_${_component}_INCLUDE_DIRS}" + INTERFACE_COMPILE_OPTIONS "${FFmpeg_${_component}_COMPILE_OPTIONS}" + INTERFACE_LINK_LIBRARIES "${FFmpeg_${_component}_LIBRARIES}" + INTERFACE_LINK_OPTIONS "${FFmpeg_${_component}_LINK_OPTIONS}" + INTERFACE_LINK_DIRECTORIES "${FFmpeg_${_component}_LINK_DIRECTORIES}" + ) + endif() + endif() + endforeach() +endif() diff --git a/cmake/PkgConfigHelper.cmake b/cmake/PkgConfigHelper.cmake index c25fbd51871da..7070fac795d81 100644 --- a/cmake/PkgConfigHelper.cmake +++ b/cmake/PkgConfigHelper.cmake @@ -2,13 +2,11 @@ function(get_flags_from_pkg_config _library _pc_prefix _out_prefix) if("${_library}" MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$") - set(_include_dirs ${_pc_prefix}_STATIC_INCLUDE_DIRS) set(_cflags ${_pc_prefix}_STATIC_CFLAGS_OTHER) set(_link_libraries ${_pc_prefix}_STATIC_LIBRARIES) set(_link_options ${_pc_prefix}_STATIC_LDFLAGS_OTHER) set(_library_dirs ${_pc_prefix}_STATIC_LIBRARY_DIRS) else() - set(_include_dirs ${_pc_prefix}_INCLUDE_DIRS) set(_cflags ${_pc_prefix}_CFLAGS_OTHER) set(_link_libraries ${_pc_prefix}_LIBRARIES) set(_link_options ${_pc_prefix}_LDFLAGS_OTHER) @@ -21,9 +19,6 @@ function(get_flags_from_pkg_config _library _pc_prefix _out_prefix) # Work around CMake's flag deduplication when pc files use `-framework A` instead of `-Wl,-framework,A` string(REPLACE "-framework;" "-Wl,-framework," "_filtered_link_options" "${${_link_options}}") - set(${_out_prefix}_include_dirs - "${${_include_dirs}}" - PARENT_SCOPE) set(${_out_prefix}_compile_options "${${_cflags}}" PARENT_SCOPE) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2c79df9b09711..d8230184cc094 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,9 +184,8 @@ endif() set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") -if(FFMPEG_FOUND) +if(FFmpeg_FOUND) add_sdl_test_executable(testspriteffmpeg NO_C90 SOURCES testspriteffmpeg.c ${icon_bmp_header}) - target_include_directories(testspriteffmpeg PRIVATE ${FFMPEG_INCLUDE_DIRS}) target_link_libraries(testspriteffmpeg PRIVATE ${FFMPEG_LIBRARIES}) else() message(STATUS "Cannot find ffmpeg, skipping testspriteffmpeg") From ed6381b68d4053aba65c08857d62b852f0db6832 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 7 Oct 2023 13:01:52 -0700 Subject: [PATCH 027/725] Allow setting any number of sprites over the video Default to no sprites over the video --- test/CMakeLists.txt | 6 +- test/{testspriteffmpeg.c => testffmpeg.c} | 102 +++++++++++++++------- 2 files changed, 72 insertions(+), 36 deletions(-) rename test/{testspriteffmpeg.c => testffmpeg.c} (87%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d8230184cc094..f7d46f101bf5a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -185,10 +185,10 @@ endif() set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") if(FFmpeg_FOUND) - add_sdl_test_executable(testspriteffmpeg NO_C90 SOURCES testspriteffmpeg.c ${icon_bmp_header}) - target_link_libraries(testspriteffmpeg PRIVATE ${FFMPEG_LIBRARIES}) + add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) + target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) else() - message(STATUS "Cannot find ffmpeg, skipping testspriteffmpeg") + message(STATUS "Can't find ffmpeg, skipping testffmpeg") endif() add_sdl_test_executable(checkkeys SOURCES checkkeys.c) diff --git a/test/testspriteffmpeg.c b/test/testffmpeg.c similarity index 87% rename from test/testspriteffmpeg.c rename to test/testffmpeg.c index e251b675db3d2..f207bf3e56328 100644 --- a/test/testspriteffmpeg.c +++ b/test/testffmpeg.c @@ -31,9 +31,10 @@ #define WINDOW_HEIGHT 480 static SDL_Texture *sprite; -static SDL_FRect position; -static SDL_FRect velocity; +static SDL_FRect *positions; +static SDL_FRect *velocities; static int sprite_w, sprite_h; +static int num_sprites = 0; static SDL_Window *window; static SDL_Renderer *renderer; @@ -67,24 +68,34 @@ static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned static void MoveSprite(void) { - int max_w, max_h; - - SDL_GetCurrentRenderOutputSize(renderer, &max_w, &max_h); - - /* Move the sprite, bounce at the wall, and draw */ - position.x += velocity.x; - if ((position.x < 0) || (position.x >= (max_w - sprite_w))) { - velocity.x = -velocity.x; - position.x += velocity.x; - } - position.y += velocity.y; - if ((position.y < 0) || (position.y >= (max_h - sprite_h))) { - velocity.y = -velocity.y; - position.y += velocity.y; + SDL_Rect viewport; + SDL_FRect *position, *velocity; + int i; + + SDL_GetRenderViewport(renderer, &viewport); + + for (i = 0; i < num_sprites; ++i) { + position = &positions[i]; + velocity = &velocities[i]; + position->x += velocity->x; + if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) { + velocity->x = -velocity->x; + position->x += velocity->x; + } + position->y += velocity->y; + if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) { + velocity->y = -velocity->y; + position->y += velocity->y; + } } /* Blit the sprite onto the screen */ - SDL_RenderTexture(renderer, sprite, NULL, &position); + for (i = 0; i < num_sprites; ++i) { + position = &positions[i]; + + /* Blit the sprite onto the screen */ + SDL_RenderTexture(renderer, sprite, NULL, position); + } } static AVCodecContext *OpenStream(AVFormatContext *ic, int stream) @@ -366,6 +377,7 @@ static void HandleVideoFrame(AVFrame *frame, double pts) int main(int argc, char *argv[]) { + const char *file = NULL; AVFormatContext *ic = NULL; int audio_stream = -1; int video_stream = -1; @@ -374,6 +386,7 @@ int main(int argc, char *argv[]) AVPacket *pkt = NULL; AVFrame *frame = NULL; double first_pts = -1.0; + int i; int result; int return_code = -1; SDL_bool flushing = SDL_FALSE; @@ -382,8 +395,18 @@ int main(int argc, char *argv[]) /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); - if (argc != 2) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s video_file\n", argv[0]); + for (i = 1; i < argc; ++i) { + if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) { + num_sprites = SDL_atoi(argv[i+1]); + ++i; + } else { + /* We'll try to open this as a media file */ + file = argv[i]; + break; + } + } + if (!file) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s [--sprites N] video_file\n", argv[0]); return_code = 1; goto quit; } @@ -398,12 +421,12 @@ int main(int argc, char *argv[]) goto quit; } - if (SDL_SetWindowTitle(window, argv[1]) < 0) { + if (SDL_SetWindowTitle(window, file) < 0) { SDL_Log("SDL_SetWindowTitle: %s", SDL_GetError()); } /* Open the media file */ - result = avformat_open_input(&ic, argv[1], NULL, NULL); + result = avformat_open_input(&ic, file, NULL, NULL); if (result < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open %s: %d", argv[1], result); return_code = 4; @@ -447,19 +470,30 @@ int main(int argc, char *argv[]) goto quit; } - /* Initialize the sprite position */ - int max_w, max_h; - SDL_GetCurrentRenderOutputSize(renderer, &max_w, &max_h); + /* Allocate memory for the sprite info */ + positions = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*positions)); + velocities = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*velocities)); + if (positions == NULL || velocities == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); + return_code = 3; + goto quit; + } + + /* Position sprites and set their velocities */ + SDL_Rect viewport; + SDL_GetRenderViewport(renderer, &viewport); srand((unsigned int)time(NULL)); - position.x = (float)(rand() % (max_w - sprite_w)); - position.y = (float)(rand() % (max_h - sprite_h)); - position.w = (float)sprite_w; - position.h = (float)sprite_h; - velocity.x = 0.0f; - velocity.y = 0.0f; - while (!velocity.x || !velocity.y) { - velocity.x = (float)((rand() % (2 + 1)) - 1); - velocity.y = (float)((rand() % (2 + 1)) - 1); + for (i = 0; i < num_sprites; ++i) { + positions[i].x = (float)(rand() % (viewport.w - sprite_w)); + positions[i].y = (float)(rand() % (viewport.h - sprite_h)); + positions[i].w = (float)sprite_w; + positions[i].h = (float)sprite_h; + velocities[i].x = 0.0f; + velocities[i].y = 0.0f; + while (!velocities[i].x || !velocities[i].y) { + velocities[i].x = (float)((rand() % (2 + 1)) - 1); + velocities[i].y = (float)((rand() % (2 + 1)) - 1); + } } /* Main render loop */ @@ -543,6 +577,8 @@ int main(int argc, char *argv[]) } return_code = 0; quit: + SDL_free(positions); + SDL_free(velocities); av_frame_free(&frame); av_packet_free(&pkt); avcodec_free_context(&audio_context); From ce8161e0cf7610fdf956027ba337ee14ecde6c78 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 7 Oct 2023 13:08:15 -0700 Subject: [PATCH 028/725] Make sure we're building with ffmpeg 6.0 or newer --- test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f7d46f101bf5a..296904534d09b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,11 +184,11 @@ endif() set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") -if(FFmpeg_FOUND) +if(FFmpeg_FOUND AND FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60") add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) else() - message(STATUS "Can't find ffmpeg, skipping testffmpeg") + message(STATUS "Can't find ffmpeg 6.0 or newer, skipping testffmpeg") endif() add_sdl_test_executable(checkkeys SOURCES checkkeys.c) From 1bf913b29a77b89f23ffc75b8f9a80d68be1045b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Oct 2023 12:27:56 -0700 Subject: [PATCH 029/725] Added support for 0-copy decode and display using VAAPI and EGL --- test/CMakeLists.txt | 8 +- test/testffmpeg.c | 611 +++++++++++++++++++++++++++++++------------- 2 files changed, 440 insertions(+), 179 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 296904534d09b..62f0eb7c3b8d7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -182,11 +182,17 @@ if(HAVE_LIBUDEV_H) add_definitions(-DHAVE_LIBUDEV_H) endif() -set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") if(FFmpeg_FOUND AND FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60") add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) + if(HAVE_OPENGLES_V2) + #message(STATUS "Enabling EGL support in testffmpeg") + target_compile_definitions(testffmpeg PRIVATE HAVE_EGL) + if(TARGET OpenGL::EGL) + target_link_libraries(testffmpeg PRIVATE OpenGL::EGL) + endif() + endif() else() message(STATUS "Can't find ffmpeg 6.0 or newer, skipping testffmpeg") endif() diff --git a/test/testffmpeg.c b/test/testffmpeg.c index f207bf3e56328..301a819fbb0ef 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -20,10 +20,27 @@ #include #include +#ifdef HAVE_EGL +#include +#include +#include + +#ifndef fourcc_code +#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) +#endif +#ifndef DRM_FORMAT_R8 +#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') +#endif +#ifndef DRM_FORMAT_GR88 +#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') +#endif +#endif + #include #include #include -#include +#include +#include #include "icon.h" @@ -40,13 +57,68 @@ static SDL_Window *window; static SDL_Renderer *renderer; static SDL_AudioStream *audio; static SDL_Texture *video_texture; -static SDL_PixelFormatEnum video_format; -static int video_width; -static int video_height; static Uint64 video_start; -static struct SwsContext *video_conversion_context; +static SDL_bool has_eglCreateImage; +#ifdef HAVE_EGL +static SDL_bool has_EGL_EXT_image_dma_buf_import; +static PFNGLACTIVETEXTUREARBPROC glActiveTextureARBFunc; +static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESFunc; +#endif static int done; +static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) +{ + SDL_RendererInfo info; + + if (useEGL) { + SDL_SetHint( SDL_HINT_VIDEO_FORCE_EGL, "1" ); + SDL_SetHint( SDL_HINT_RENDER_DRIVER, "opengles2" ); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } else { + SDL_SetHint( SDL_HINT_VIDEO_FORCE_EGL, "0" ); + SDL_SetHint( SDL_HINT_RENDER_DRIVER, NULL ); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + } + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + + if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_HIDDEN, &window, &renderer) < 0) { + return SDL_FALSE; + } + + if (SDL_GetRendererInfo(renderer, &info) == 0) { + SDL_Log("Created renderer %s\n", info.name); + } + +#ifdef HAVE_EGL + if (useEGL) { + const char *extensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); + if (SDL_strstr(extensions, "EGL_EXT_image_dma_buf_import") != NULL) { + has_EGL_EXT_image_dma_buf_import = SDL_TRUE; + } + + if (SDL_GL_ExtensionSupported("GL_OES_EGL_image")) { + glEGLImageTargetTexture2DOESFunc = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + } + + glActiveTextureARBFunc = (PFNGLACTIVETEXTUREARBPROC)SDL_GL_GetProcAddress("glActiveTextureARB"); + + if (has_EGL_EXT_image_dma_buf_import && + glEGLImageTargetTexture2DOESFunc && + glActiveTextureARBFunc) { + has_eglCreateImage = SDL_TRUE; + } + } +#endif /* HAVE_EGL */ + + return SDL_TRUE; +} + static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) { SDL_Texture *texture = NULL; SDL_Surface *surface; @@ -98,33 +170,140 @@ static void MoveSprite(void) } } -static AVCodecContext *OpenStream(AVFormatContext *ic, int stream) +static Uint32 GetTextureFormat(enum AVPixelFormat format) +{ + switch (format) { + case AV_PIX_FMT_RGB8: + return SDL_PIXELFORMAT_RGB332; + case AV_PIX_FMT_RGB444: + return SDL_PIXELFORMAT_RGB444; + case AV_PIX_FMT_RGB555: + return SDL_PIXELFORMAT_RGB555; + case AV_PIX_FMT_BGR555: + return SDL_PIXELFORMAT_BGR555; + case AV_PIX_FMT_RGB565: + return SDL_PIXELFORMAT_RGB565; + case AV_PIX_FMT_BGR565: + return SDL_PIXELFORMAT_BGR565; + case AV_PIX_FMT_RGB24: + return SDL_PIXELFORMAT_RGB24; + case AV_PIX_FMT_BGR24: + return SDL_PIXELFORMAT_BGR24; + case AV_PIX_FMT_0RGB32: + return SDL_PIXELFORMAT_XRGB8888; + case AV_PIX_FMT_0BGR32: + return SDL_PIXELFORMAT_XBGR8888; + case AV_PIX_FMT_NE(RGB0, 0BGR): + return SDL_PIXELFORMAT_RGBX8888; + case AV_PIX_FMT_NE(BGR0, 0RGB): + return SDL_PIXELFORMAT_BGRX8888; + case AV_PIX_FMT_RGB32: + return SDL_PIXELFORMAT_ARGB8888; + case AV_PIX_FMT_RGB32_1: + return SDL_PIXELFORMAT_RGBA8888; + case AV_PIX_FMT_BGR32: + return SDL_PIXELFORMAT_ABGR8888; + case AV_PIX_FMT_BGR32_1: + return SDL_PIXELFORMAT_BGRA8888; + case AV_PIX_FMT_YUV420P: + return SDL_PIXELFORMAT_IYUV; + case AV_PIX_FMT_YUYV422: + return SDL_PIXELFORMAT_YUY2; + case AV_PIX_FMT_UYVY422: + return SDL_PIXELFORMAT_UYVY; + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +static SDL_bool SupportedPixelFormat(enum AVPixelFormat format) +{ + if (has_eglCreateImage && + (format == AV_PIX_FMT_VAAPI || format == AV_PIX_FMT_DRM_PRIME)) { + return SDL_TRUE; + } + + if (GetTextureFormat(format) != SDL_PIXELFORMAT_UNKNOWN) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +static enum AVPixelFormat GetPixelFormat(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) +{ + const enum AVPixelFormat *p; + + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { + if (SupportedPixelFormat(*p)) { + /* We support this format */ + break; + } + } + + if (*p == AV_PIX_FMT_NONE) { + SDL_Log("Couldn't find a supported pixel format:\n"); + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { + SDL_Log(" %s\n", av_get_pix_fmt_name(*p)); + } + } + + return *p; +} + +static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AVCodec *codec) { + AVStream *st = ic->streams[stream]; + AVCodecParameters *codecpar = st->codecpar; AVCodecContext *context; - const AVCodec *codec; + const AVCodecHWConfig *config; + enum AVHWDeviceType type; + int i; int result; + SDL_Log("Video stream: %s %dx%d\n", avcodec_get_name(codec->id), codecpar->width, codecpar->height); + context = avcodec_alloc_context3(NULL); if (!context) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_alloc_context3 failed"); return NULL; } - if (avcodec_parameters_to_context(context, ic->streams[stream]->codecpar) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_parameters_to_context failed"); + result = avcodec_parameters_to_context(context, ic->streams[stream]->codecpar); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_parameters_to_context failed: %s\n", av_err2str(result)); avcodec_free_context(&context); return NULL; } context->pkt_timebase = ic->streams[stream]->time_base; - codec = avcodec_find_decoder(context->codec_id); - if (!codec) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find codec %s", avcodec_get_name(context->codec_id)); - avcodec_free_context(&context); - return NULL; + /* Look for supported hardware accelerated configurations */ + i = 0; + while (!context->hw_device_ctx && + (config = avcodec_get_hw_config(codec, i++)) != NULL) { + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) || + !SupportedPixelFormat(config->pix_fmt)) { + continue; + } + + type = AV_HWDEVICE_TYPE_NONE; + while (!context->hw_device_ctx && + (type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) { + if (type != config->device_type) { + continue; + } + + result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); + } else { + SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); + } + } } - context->codec_id = codec->id; + /* Allow supported hardware accelerated pixel formats */ + context->get_format = GetPixelFormat; + result = avcodec_open2(context, codec, NULL); if (result < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open codec %s: %s", avcodec_get_name(context->codec_id), av_err2str(result)); @@ -132,25 +311,232 @@ static AVCodecContext *OpenStream(AVFormatContext *ic, int stream) return NULL; } + SDL_SetWindowSize(window, codecpar->width, codecpar->height); + return context; } -static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream) +static void SetYUVConversionMode(AVFrame *frame) { - AVStream *st = ic->streams[stream]; - AVCodecParameters *codecpar = st->codecpar; - AVCodecContext *context = OpenStream(ic, stream); + SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC; + if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) { + if (frame->color_range == AVCOL_RANGE_JPEG) + mode = SDL_YUV_CONVERSION_JPEG; + else if (frame->colorspace == AVCOL_SPC_BT709) + mode = SDL_YUV_CONVERSION_BT709; + else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M) + mode = SDL_YUV_CONVERSION_BT601; + } + SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */ +} - if (context) { - SDL_Log("Audio stream: %s %d channels, %d Hz\n", avcodec_get_name(context->codec_id), codecpar->ch_layout.nb_channels, codecpar->sample_rate); +static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) +{ + int texture_width = 0, texture_height = 0; + Uint32 texture_format = SDL_PIXELFORMAT_UNKNOWN; + Uint32 frame_format = GetTextureFormat(frame->format); + + if (*texture) { + SDL_QueryTexture(*texture, &texture_format, NULL, &texture_width, &texture_height); + } + if (!*texture || frame_format != texture_format || frame->width != texture_width || frame->height != texture_height) { + if (*texture) { + SDL_DestroyTexture(*texture); + } + + *texture = SDL_CreateTexture(renderer, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + if (!*texture) { + return SDL_FALSE; + } + } - SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate }; - audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); - if (audio) { - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio)); + switch (frame_format) { + case SDL_PIXELFORMAT_IYUV: + if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { + SDL_UpdateYUVTexture(*texture, NULL, frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2]); + } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { + SDL_UpdateYUVTexture(*texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0], + frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], + frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + } + SetYUVConversionMode(frame); + break; + default: + if (frame->linesize[0] < 0) { + SDL_UpdateTexture(*texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + } else { + SDL_UpdateTexture(*texture, NULL, frame->data[0], frame->linesize[0]); + } + break; + } + return SDL_TRUE; +} + +static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) +{ +#ifdef HAVE_EGL + const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0]; + int i, j, image_index, num_planes; + EGLDisplay display = eglGetCurrentDisplay(); + + /* FIXME: Assuming NV12 data format */ + num_planes = 0; + for (i = 0; i < desc->nb_layers; ++i) { + num_planes += desc->layers[i].nb_planes; + } + if (num_planes != 2) { + SDL_SetError("Expected NV12 frames with 2 planes, instead got %d planes", num_planes); + return SDL_FALSE; + } + + if (*texture) { + /* Free the previous texture now that we're about to render a new one */ + SDL_DestroyTexture(*texture); + } else { + /* First time set up for NV12 textures */ + SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1"); + + SetYUVConversionMode(frame); + } + + *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, frame->width, frame->height); + if (!*texture) { + return SDL_FALSE; + } + + /* Bind the texture for importing */ + SDL_GL_BindTexture(*texture, NULL, NULL); + + /* import the frame into OpenGL */ + image_index = 0; + for (i = 0; i < desc->nb_layers; ++i) { + const AVDRMLayerDescriptor *layer = &desc->layers[i]; + for (j = 0; j < layer->nb_planes; ++j) { + static const uint32_t formats[ 2 ] = { DRM_FORMAT_R8, DRM_FORMAT_GR88 }; + const AVDRMPlaneDescriptor *plane = &layer->planes[j]; + const AVDRMObjectDescriptor *object = &desc->objects[plane->object_index]; + EGLAttrib img_attr[] = { + EGL_LINUX_DRM_FOURCC_EXT, formats[i], + EGL_WIDTH, frame->width / ( image_index + 1 ), /* half size for chroma */ + EGL_HEIGHT, frame->height / ( image_index + 1 ), + EGL_DMA_BUF_PLANE0_FD_EXT, object->fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, plane->offset, + EGL_DMA_BUF_PLANE0_PITCH_EXT, plane->pitch, + EGL_NONE + }; + EGLImage pImage = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr); + + glActiveTextureARBFunc(GL_TEXTURE0_ARB + image_index); + glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, pImage); + ++image_index; + } + } + + SDL_GL_UnbindTexture(*texture); + + return SDL_TRUE; +#else + return SDL_FALSE; +#endif +} + +static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture) +{ + AVFrame *drm_frame; + SDL_bool result = SDL_FALSE; + + drm_frame = av_frame_alloc(); + if (drm_frame) { + drm_frame->format = AV_PIX_FMT_DRM_PRIME; + if (av_hwframe_map(drm_frame, frame, 0) == 0) { + result = GetTextureForDRMFrame(drm_frame, texture); } else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s", SDL_GetError()); + SDL_SetError("Couldn't map hardware frame"); } + av_frame_free(&drm_frame); + } else { + SDL_OutOfMemory(); + } + return result; +} + +static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) +{ + switch (frame->format) { + case AV_PIX_FMT_VAAPI: + return GetTextureForVAAPIFrame(frame, texture); + case AV_PIX_FMT_DRM_PRIME: + return GetTextureForDRMFrame(frame, texture); + default: + return GetTextureForMemoryFrame(frame, texture); + } +} + +static void HandleVideoFrame(AVFrame *frame, double pts) +{ + /* Update the video texture */ + GetTextureForFrame(frame, &video_texture); + + /* Quick and dirty PTS handling */ + if (!video_start) { + video_start = SDL_GetTicks(); + } + double now = (double)(SDL_GetTicks() - video_start) / 1000.0; + while (now < pts - 0.001) { + SDL_Delay(1); + now = (double)(SDL_GetTicks() - video_start) / 1000.0; + } + + if (frame->linesize[0] < 0) { + SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, SDL_FLIP_VERTICAL); + } else { + SDL_RenderTexture(renderer, video_texture, NULL, NULL); + } + + /* Render any bouncing balls */ + MoveSprite(); + + SDL_RenderPresent(renderer); +} + +static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream, const AVCodec *codec) +{ + AVStream *st = ic->streams[stream]; + AVCodecParameters *codecpar = st->codecpar; + AVCodecContext *context; + int result; + + SDL_Log("Audio stream: %s %d channels, %d Hz\n", avcodec_get_name(codec->id), codecpar->ch_layout.nb_channels, codecpar->sample_rate); + + context = avcodec_alloc_context3(NULL); + if (!context) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_alloc_context3 failed\n"); + return NULL; + } + + result = avcodec_parameters_to_context(context, ic->streams[stream]->codecpar); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "avcodec_parameters_to_context failed: %s\n", av_err2str(result)); + avcodec_free_context(&context); + return NULL; + } + context->pkt_timebase = ic->streams[stream]->time_base; + + result = avcodec_open2(context, codec, NULL); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open codec %s: %s", avcodec_get_name(context->codec_id), av_err2str(result)); + avcodec_free_context(&context); + return NULL; + } + + SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate }; + audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); + if (audio) { + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio)); + } else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s", SDL_GetError()); } return context; } @@ -228,159 +614,14 @@ static void HandleAudioFrame(AVFrame *frame) } } -static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream) -{ - AVStream *st = ic->streams[stream]; - AVCodecParameters *codecpar = st->codecpar; - AVCodecContext *context = OpenStream(ic, stream); - - if (context) { - SDL_Log("Video stream: %s %dx%d\n", avcodec_get_name(context->codec_id), codecpar->width, codecpar->height); - SDL_SetWindowSize(window, codecpar->width, codecpar->height); - } - return context; -} - -static SDL_PixelFormatEnum GetVideoFormat(enum AVPixelFormat format) -{ - switch (format) { - case AV_PIX_FMT_RGB8: - return SDL_PIXELFORMAT_RGB332; - case AV_PIX_FMT_RGB444: - return SDL_PIXELFORMAT_RGB444; - case AV_PIX_FMT_RGB555: - return SDL_PIXELFORMAT_RGB555; - case AV_PIX_FMT_BGR555: - return SDL_PIXELFORMAT_BGR555; - case AV_PIX_FMT_RGB565: - return SDL_PIXELFORMAT_RGB565; - case AV_PIX_FMT_BGR565: - return SDL_PIXELFORMAT_BGR565; - case AV_PIX_FMT_RGB24: - return SDL_PIXELFORMAT_RGB24; - case AV_PIX_FMT_BGR24: - return SDL_PIXELFORMAT_BGR24; - case AV_PIX_FMT_0RGB32: - return SDL_PIXELFORMAT_XRGB8888; - case AV_PIX_FMT_0BGR32: - return SDL_PIXELFORMAT_XBGR8888; - case AV_PIX_FMT_NE(RGB0, 0BGR): - return SDL_PIXELFORMAT_RGBX8888; - case AV_PIX_FMT_NE(BGR0, 0RGB): - return SDL_PIXELFORMAT_BGRX8888; - case AV_PIX_FMT_RGB32: - return SDL_PIXELFORMAT_ARGB8888; - case AV_PIX_FMT_RGB32_1: - return SDL_PIXELFORMAT_RGBA8888; - case AV_PIX_FMT_BGR32: - return SDL_PIXELFORMAT_ABGR8888; - case AV_PIX_FMT_BGR32_1: - return SDL_PIXELFORMAT_BGRA8888; - case AV_PIX_FMT_YUV420P: - return SDL_PIXELFORMAT_IYUV; - case AV_PIX_FMT_YUYV422: - return SDL_PIXELFORMAT_YUY2; - case AV_PIX_FMT_UYVY422: - return SDL_PIXELFORMAT_UYVY; - default: - return SDL_PIXELFORMAT_UNKNOWN; - } -} - -static void SetYUVConversionMode(AVFrame *frame) -{ - SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC; - if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) { - if (frame->color_range == AVCOL_RANGE_JPEG) - mode = SDL_YUV_CONVERSION_JPEG; - else if (frame->colorspace == AVCOL_SPC_BT709) - mode = SDL_YUV_CONVERSION_BT709; - else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M) - mode = SDL_YUV_CONVERSION_BT601; - } - SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */ -} - -static void HandleVideoFrame(AVFrame *frame, double pts) -{ - SDL_RendererFlip flip = SDL_FLIP_NONE; - - /* Update the video texture */ - SDL_PixelFormatEnum format = GetVideoFormat(frame->format); - if (!video_texture || format != video_format || frame->width != video_width || frame->height != video_height) { - if (video_texture) { - SDL_DestroyTexture(video_texture); - } - - if (format == SDL_PIXELFORMAT_UNKNOWN) { - video_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); - } else { - video_texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); - } - video_format = format; - video_width = frame->width; - video_height = frame->height; - } - - switch (format) { - case SDL_PIXELFORMAT_UNKNOWN: - video_conversion_context = sws_getCachedContext(video_conversion_context, - frame->width, frame->height, frame->format, frame->width, frame->height, - AV_PIX_FMT_BGRA, SWS_POINT, NULL, NULL, NULL); - if (video_conversion_context != NULL) { - uint8_t *pixels[4]; - int pitch[4]; - if (SDL_LockTexture(video_texture, NULL, (void **)pixels, pitch) == 0) { - sws_scale(video_conversion_context, (const uint8_t * const *)frame->data, frame->linesize, - 0, frame->height, pixels, pitch); - SDL_UnlockTexture(video_texture); - } - } - break; - case SDL_PIXELFORMAT_IYUV: - if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { - SDL_UpdateYUVTexture(video_texture, NULL, frame->data[0], frame->linesize[0], - frame->data[1], frame->linesize[1], - frame->data[2], frame->linesize[2]); - } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { - SDL_UpdateYUVTexture(video_texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0], - frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], - frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); - flip = SDL_FLIP_VERTICAL; - } - SetYUVConversionMode(frame); - break; - default: - if (frame->linesize[0] < 0) { - SDL_UpdateTexture(video_texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); - flip = SDL_FLIP_VERTICAL; - } else { - SDL_UpdateTexture(video_texture, NULL, frame->data[0], frame->linesize[0]); - } - break; - } - - /* Quick and dirty PTS handling */ - if (!video_start) { - video_start = SDL_GetTicks(); - } - double now = (double)(SDL_GetTicks() - video_start) / 1000.0; - while (now < pts - 0.001) { - SDL_Delay(1); - now = (double)(SDL_GetTicks() - video_start) / 1000.0; - } - - SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, flip); - MoveSprite(); - SDL_RenderPresent(renderer); -} - int main(int argc, char *argv[]) { const char *file = NULL; AVFormatContext *ic = NULL; int audio_stream = -1; int video_stream = -1; + const AVCodec *audio_decoder = NULL; + const AVCodec *video_decoder = NULL; AVCodecContext *audio_context = NULL; AVCodecContext *video_context = NULL; AVPacket *pkt = NULL; @@ -389,6 +630,7 @@ int main(int argc, char *argv[]) int i; int result; int return_code = -1; + Uint32 window_flags; SDL_bool flushing = SDL_FALSE; SDL_bool decoded = SDL_FALSE; @@ -416,7 +658,17 @@ int main(int argc, char *argv[]) goto quit; } - if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer) < 0) { + window_flags = SDL_WINDOW_HIDDEN; +#ifdef __APPLE__ + window_flags |= SDL_WINDOW_METAL; +#elif !defined(__WIN32__) + window_flags |= SDL_WINDOW_OPENGL; +#endif +#ifdef HAVE_EGL + /* Try to create an EGL compatible window for DRM hardware frame support */ + CreateWindow(window_flags, SDL_TRUE); +#endif + if (!window && !CreateWindow(window_flags, SDL_FALSE)) { return_code = 2; goto quit; } @@ -432,17 +684,17 @@ int main(int argc, char *argv[]) return_code = 4; goto quit; } - video_stream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); + video_stream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, &video_decoder, 0); if (video_stream >= 0) { - video_context = OpenVideoStream(ic, video_stream); + video_context = OpenVideoStream(ic, video_stream, video_decoder); if (!video_context) { return_code = 4; goto quit; } } - audio_stream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, video_stream, NULL, 0); + audio_stream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, video_stream, &audio_decoder, 0); if (audio_stream >= 0) { - audio_context = OpenAudioStream(ic, audio_stream); + audio_context = OpenAudioStream(ic, audio_stream, audio_decoder); if (!audio_context) { return_code = 4; goto quit; @@ -496,6 +748,9 @@ int main(int argc, char *argv[]) } } + /* We're ready to go! */ + SDL_ShowWindow(window); + /* Main render loop */ done = 0; From d830cd140b6e5701a9d90b7b0fe10ed292baf46e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Oct 2023 17:55:06 -0700 Subject: [PATCH 030/725] Added support for 0-copy decode and display using Apple VideoToolbox --- test/CMakeLists.txt | 7 +- test/testffmpeg.c | 61 ++++++++++++-- test/testffmpeg_videotoolbox.h | 15 ++++ test/testffmpeg_videotoolbox.m | 147 +++++++++++++++++++++++++++++++++ 4 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 test/testffmpeg_videotoolbox.h create mode 100644 test/testffmpeg_videotoolbox.m diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 62f0eb7c3b8d7..9ca6ab796b262 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,7 +184,12 @@ endif() include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") if(FFmpeg_FOUND AND FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60") - add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) + if(APPLE) + add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c testffmpeg_videotoolbox.m ${icon_bmp_header}) + target_link_options(testffmpeg PRIVATE "-Wl,-framework,CoreFoundation" "-Wl,-framework,CoreVideo" "-Wl,-framework,Metal") + else() + add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) + endif() target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) if(HAVE_OPENGLES_V2) #message(STATUS "Enabling EGL support in testffmpeg") diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 301a819fbb0ef..5e2dbfc1d12f9 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -36,6 +36,10 @@ #endif #endif +#ifdef __APPLE__ +#include "testffmpeg_videotoolbox.h" +#endif + #include #include #include @@ -64,6 +68,9 @@ static SDL_bool has_EGL_EXT_image_dma_buf_import; static PFNGLACTIVETEXTUREARBPROC glActiveTextureARBFunc; static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESFunc; #endif +#ifdef __APPLE__ +static SDL_bool has_videotoolbox_output; +#endif static int done; static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) @@ -87,7 +94,7 @@ static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_HIDDEN, &window, &renderer) < 0) { + if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, window_flags, &window, &renderer) < 0) { return SDL_FALSE; } @@ -116,6 +123,10 @@ static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) } #endif /* HAVE_EGL */ +#ifdef __APPLE__ + has_videotoolbox_output = SetupVideoToolboxOutput(renderer); +#endif + return SDL_TRUE; } @@ -222,6 +233,11 @@ static SDL_bool SupportedPixelFormat(enum AVPixelFormat format) (format == AV_PIX_FMT_VAAPI || format == AV_PIX_FMT_DRM_PRIME)) { return SDL_TRUE; } +#ifdef __APPLE__ + if (has_videotoolbox_output && format == AV_PIX_FMT_VIDEOTOOLBOX) { + return SDL_TRUE; + } +#endif if (GetTextureFormat(format) != SDL_PIXELFORMAT_UNKNOWN) { return SDL_TRUE; @@ -474,11 +490,41 @@ static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) } } -static void HandleVideoFrame(AVFrame *frame, double pts) +static void DisplayVideoTexture(AVFrame *frame) { /* Update the video texture */ GetTextureForFrame(frame, &video_texture); + if (frame->linesize[0] < 0) { + SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, SDL_FLIP_VERTICAL); + } else { + SDL_RenderTexture(renderer, video_texture, NULL, NULL); + } +} + +static void DisplayVideoToolbox(AVFrame *frame) +{ +#ifdef __APPLE__ + SDL_Rect viewport; + SDL_GetRenderViewport(renderer, &viewport); + DisplayVideoToolboxFrame(renderer, frame->data[3], 0, 0, frame->width, frame->height, viewport.x, viewport.y, viewport.w, viewport.h); +#endif +} + +static void DisplayVideoFrame(AVFrame *frame) +{ + switch (frame->format) { + case AV_PIX_FMT_VIDEOTOOLBOX: + DisplayVideoToolbox(frame); + break; + default: + DisplayVideoTexture(frame); + break; + } +} + +static void HandleVideoFrame(AVFrame *frame, double pts) +{ /* Quick and dirty PTS handling */ if (!video_start) { video_start = SDL_GetTicks(); @@ -489,11 +535,7 @@ static void HandleVideoFrame(AVFrame *frame, double pts) now = (double)(SDL_GetTicks() - video_start) / 1000.0; } - if (frame->linesize[0] < 0) { - SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, SDL_FLIP_VERTICAL); - } else { - SDL_RenderTexture(renderer, video_texture, NULL, NULL); - } + DisplayVideoFrame(frame); /* Render any bouncing balls */ MoveSprite(); @@ -658,7 +700,7 @@ int main(int argc, char *argv[]) goto quit; } - window_flags = SDL_WINDOW_HIDDEN; + window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; #ifdef __APPLE__ window_flags |= SDL_WINDOW_METAL; #elif !defined(__WIN32__) @@ -832,6 +874,9 @@ int main(int argc, char *argv[]) } return_code = 0; quit: +#ifdef __APPLE__ + CleanupVideoToolboxOutput(); +#endif SDL_free(positions); SDL_free(velocities); av_frame_free(&frame); diff --git a/test/testffmpeg_videotoolbox.h b/test/testffmpeg_videotoolbox.h new file mode 100644 index 0000000000000..21242955cbca2 --- /dev/null +++ b/test/testffmpeg_videotoolbox.h @@ -0,0 +1,15 @@ +/* + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ + +extern SDL_bool SetupVideoToolboxOutput(SDL_Renderer *renderer); +extern SDL_bool DisplayVideoToolboxFrame(SDL_Renderer *renderer, void *buffer, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH ); +extern void CleanupVideoToolboxOutput(); diff --git a/test/testffmpeg_videotoolbox.m b/test/testffmpeg_videotoolbox.m new file mode 100644 index 0000000000000..e7d580cae0fb8 --- /dev/null +++ b/test/testffmpeg_videotoolbox.m @@ -0,0 +1,147 @@ +/* + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ +#include + +#include "testffmpeg_videotoolbox.h" + +#include +#include +#include +#include + + +// Metal BT.601 to RGB conversion shader +static NSString *drawMetalShaderSource = +@" using namespace metal;\n" +"\n" +" struct Vertex\n" +" {\n" +" float4 position [[position]];\n" +" float2 texCoords;\n" +" };\n" +"\n" +" constexpr sampler s(coord::normalized, address::clamp_to_edge, filter::linear);\n" +"\n" +" vertex Vertex draw_vs(constant Vertex *vertices [[ buffer(0) ]], uint vid [[ vertex_id ]])\n" +" {\n" +" return vertices[ vid ];\n" +" }\n" +"\n" +" fragment float4 draw_ps_bt601(Vertex in [[ stage_in ]],\n" +" texture2d textureY [[ texture(0) ]],\n" +" texture2d textureUV [[ texture(1) ]])\n" +" {\n" +" float3 yuv = float3(textureY.sample(s, in.texCoords).r, textureUV.sample(s, in.texCoords).rg);\n" +" float3 rgb;\n" +" yuv += float3(-0.0627451017, -0.501960814, -0.501960814);\n" +" rgb.r = dot(yuv, float3(1.1644, 0.000, 1.596));\n" +" rgb.g = dot(yuv, float3(1.1644, -0.3918, -0.813));\n" +" rgb.b = dot(yuv, float3(1.1644, 2.0172, 0.000));\n" +" return float4(rgb, 1.0);\n" +" }\n" +; + +// keep this structure aligned with the proceeding drawMetalShaderSource's struct Vertex +typedef struct Vertex +{ + vector_float4 position; + vector_float2 texCoord; +} Vertex; + +static void SetVertex(Vertex *vertex, float x, float y, float s, float t) +{ + vertex->position[ 0 ] = x; + vertex->position[ 1 ] = y; + vertex->position[ 2 ] = 0.0f; + vertex->position[ 3 ] = 1.0f; + vertex->texCoord[ 0 ] = s; + vertex->texCoord[ 1 ] = t; +} + +static CAMetalLayer *metal_layer; +static id library; +static id video_pipeline; + +SDL_bool SetupVideoToolboxOutput(SDL_Renderer *renderer) +{ @autoreleasepool { + NSError *error; + + // Create the metal view + metal_layer = (CAMetalLayer *)SDL_GetRenderMetalLayer(renderer); + if (!metal_layer) { + return SDL_FALSE; + } + + // FIXME: Handle other colorspaces besides BT.601 + library = [metal_layer.device newLibraryWithSource:drawMetalShaderSource options:nil error:&error]; + + MTLRenderPipelineDescriptor *videoPipelineDescriptor = [[MTLRenderPipelineDescriptor new] autorelease]; + videoPipelineDescriptor.vertexFunction = [library newFunctionWithName:@"draw_vs"]; + videoPipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"draw_ps_bt601"]; + videoPipelineDescriptor.colorAttachments[ 0 ].pixelFormat = metal_layer.pixelFormat; + + video_pipeline = [metal_layer.device newRenderPipelineStateWithDescriptor:videoPipelineDescriptor error:nil]; + if (!video_pipeline) { + SDL_SetError("Couldn't create video pipeline"); + return SDL_FALSE; + } + + return true; +}} + +SDL_bool DisplayVideoToolboxFrame(SDL_Renderer *renderer, void *buffer, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH ) +{ @autoreleasepool { + CVPixelBufferRef pPixelBuffer = (CVPixelBufferRef)buffer; + size_t nPixelBufferWidth = CVPixelBufferGetWidthOfPlane(pPixelBuffer, 0); + size_t nPixelBufferHeight = CVPixelBufferGetHeightOfPlane(pPixelBuffer, 0); + id videoFrameTextureY = nil; + id videoFrameTextureUV = nil; + + IOSurfaceRef pSurface = CVPixelBufferGetIOSurface(pPixelBuffer); + + MTLTextureDescriptor *textureDescriptorY = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Unorm width:nPixelBufferWidth height:nPixelBufferHeight mipmapped:NO]; + MTLTextureDescriptor *textureDescriptorUV = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRG8Unorm width:CVPixelBufferGetWidthOfPlane(pPixelBuffer, 1) height:CVPixelBufferGetHeightOfPlane(pPixelBuffer, 1) mipmapped:NO]; + + videoFrameTextureY = [[metal_layer.device newTextureWithDescriptor:textureDescriptorY iosurface:pSurface plane:0] autorelease]; + videoFrameTextureUV = [[metal_layer.device newTextureWithDescriptor:textureDescriptorUV iosurface:pSurface plane:1] autorelease]; + + float flMinSrcX = ( srcX + 0.5f ) / nPixelBufferWidth; + float flMaxSrcX = ( srcX + srcW + 0.5f ) / nPixelBufferWidth; + float flMinSrcY = ( srcY + 0.5f ) / nPixelBufferHeight; + float flMaxSrcY = ( srcY + srcH + 0.5f ) / nPixelBufferHeight; + + int nOutputWidth, nOutputHeight; + nOutputWidth = metal_layer.drawableSize.width; + nOutputHeight = metal_layer.drawableSize.height; + float flMinDstX = 2.0f * ( ( dstX + 0.5f ) / nOutputWidth ) - 1.0f; + float flMaxDstX = 2.0f * ( ( dstX + dstW + 0.5f ) / nOutputWidth ) - 1.0f; + float flMinDstY = 2.0f * ( ( nOutputHeight - dstY - 0.5f ) / nOutputHeight ) - 1.0f; + float flMaxDstY = 2.0f * ( ( nOutputHeight - ( dstY + dstH ) - 0.5f ) / nOutputHeight ) - 1.0f; + + Vertex arrVerts[4]; + SetVertex(&arrVerts[0], flMinDstX, flMaxDstY, flMinSrcX, flMaxSrcY); + SetVertex(&arrVerts[1], flMinDstX, flMinDstY, flMinSrcX, flMinSrcY); + SetVertex(&arrVerts[2], flMaxDstX, flMaxDstY, flMaxSrcX, flMaxSrcY); + SetVertex(&arrVerts[3], flMaxDstX, flMinDstY, flMaxSrcX, flMinSrcY); + + id renderEncoder = (id)SDL_GetRenderMetalCommandEncoder(renderer); + [renderEncoder setRenderPipelineState:video_pipeline]; + [renderEncoder setFragmentTexture:videoFrameTextureY atIndex:0]; + [renderEncoder setFragmentTexture:videoFrameTextureUV atIndex:1]; + [renderEncoder setVertexBytes:arrVerts length:sizeof(arrVerts) atIndex:0]; + [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:SDL_arraysize(arrVerts)]; + return SDL_TRUE; +}} + +void CleanupVideoToolboxOutput() +{ +} From a842446f62dc0d00773d41b932f4649b6bd3da5f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Oct 2023 21:02:27 -0700 Subject: [PATCH 031/725] Added support for 0-copy decode and display using D3D11 FIXME: We need a way to do this that doesn't involve reaching into the D3D11 texture internals --- test/CMakeLists.txt | 4 +- test/testffmpeg.c | 265 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 251 insertions(+), 18 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9ca6ab796b262..527112d08b50f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -183,14 +183,13 @@ if(HAVE_LIBUDEV_H) endif() include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") -if(FFmpeg_FOUND AND FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60") +if(FFmpeg_FOUND AND (FFmpeg_AVCODEC_VERSION STREQUAL "" OR FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60")) if(APPLE) add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c testffmpeg_videotoolbox.m ${icon_bmp_header}) target_link_options(testffmpeg PRIVATE "-Wl,-framework,CoreFoundation" "-Wl,-framework,CoreVideo" "-Wl,-framework,Metal") else() add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) endif() - target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) if(HAVE_OPENGLES_V2) #message(STATUS "Enabling EGL support in testffmpeg") target_compile_definitions(testffmpeg PRIVATE HAVE_EGL) @@ -198,6 +197,7 @@ if(FFmpeg_FOUND AND FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60") target_link_libraries(testffmpeg PRIVATE OpenGL::EGL) endif() endif() + target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) else() message(STATUS "Can't find ffmpeg 6.0 or newer, skipping testffmpeg") endif() diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 5e2dbfc1d12f9..5150a4306da63 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -40,9 +40,86 @@ #include "testffmpeg_videotoolbox.h" #endif +#ifdef __WIN32__ +#define COBJMACROS +#include + +struct D3D11_TextureData +{ + ID3D11Texture2D *mainTexture; + ID3D11ShaderResourceView *mainTextureResourceView; + ID3D11RenderTargetView *mainTextureRenderTargetView; + ID3D11Texture2D *stagingTexture; + int lockedTexturePositionX; + int lockedTexturePositionY; + D3D11_FILTER scaleMode; + + /* YV12 texture support */ + SDL_bool yuv; + ID3D11Texture2D *mainTextureU; + ID3D11ShaderResourceView *mainTextureResourceViewU; + ID3D11Texture2D *mainTextureV; + ID3D11ShaderResourceView *mainTextureResourceViewV; + + /* NV12 texture support */ + SDL_bool nv12; + ID3D11Texture2D *mainTextureNV; + ID3D11ShaderResourceView *mainTextureResourceViewNV; + + Uint8 *pixels; + int pitch; + SDL_Rect locked_rect; +}; + +/* Rendering view state */ +typedef struct SDL_RenderViewState +{ + int pixel_w; + int pixel_h; + SDL_Rect viewport; + SDL_Rect clip_rect; + SDL_bool clipping_enabled; + SDL_FPoint scale; + +} SDL_RenderViewState; + +struct SDL_Texture +{ + const void *magic; + Uint32 format; /**< The pixel format of the texture */ + int access; /**< SDL_TextureAccess */ + int w; /**< The width of the texture */ + int h; /**< The height of the texture */ + int modMode; /**< The texture modulation mode */ + SDL_BlendMode blendMode; /**< The texture blend mode */ + SDL_ScaleMode scaleMode; /**< The texture scale mode */ + SDL_Color color; /**< Texture modulation values */ + SDL_RenderViewState view; /**< Target texture view state */ + + SDL_Renderer *renderer; + + /* Support for formats not supported directly by the renderer */ + SDL_Texture *native; + void /*SDL_SW_YUVTexture*/ *yuv; + void *pixels; + int pitch; + SDL_Rect locked_rect; + SDL_Surface *locked_surface; /**< Locked region exposed as a SDL surface */ + + Uint32 last_command_generation; /* last command queue generation this texture was in. */ + + struct D3D11_TextureData /*void*/ *driverdata; /**< Driver specific texture representation */ + void *userdata; + + SDL_Texture *prev; + SDL_Texture *next; +}; +#endif /* __WIN32__ */ + #include #include #include +#include #include #include @@ -51,6 +128,7 @@ #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 + static SDL_Texture *sprite; static SDL_FRect *positions; static SDL_FRect *velocities; @@ -71,21 +149,25 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESFunc; #ifdef __APPLE__ static SDL_bool has_videotoolbox_output; #endif +#ifdef __WIN32__ +static ID3D11Device *d3d11_device; +static ID3D11DeviceContext *d3d11_context; +#endif static int done; -static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) +static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) { SDL_RendererInfo info; + SDL_bool useEGL = (driver && SDL_strcmp(driver, "opengles2") == 0); + SDL_SetHint(SDL_HINT_RENDER_DRIVER, driver); if (useEGL) { - SDL_SetHint( SDL_HINT_VIDEO_FORCE_EGL, "1" ); - SDL_SetHint( SDL_HINT_RENDER_DRIVER, "opengles2" ); + SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "1"); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } else { - SDL_SetHint( SDL_HINT_VIDEO_FORCE_EGL, "0" ); - SDL_SetHint( SDL_HINT_RENDER_DRIVER, NULL ); + SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "0"); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); @@ -127,6 +209,13 @@ static SDL_bool CreateWindow(Uint32 window_flags, SDL_bool useEGL) has_videotoolbox_output = SetupVideoToolboxOutput(renderer); #endif +#ifdef __WIN32__ + d3d11_device = SDL_GetRenderD3D11Device(renderer); + if (d3d11_device) { + ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context); + } +#endif + return SDL_TRUE; } @@ -238,6 +327,11 @@ static SDL_bool SupportedPixelFormat(enum AVPixelFormat format) return SDL_TRUE; } #endif +#ifdef __WIN32__ + if (d3d11_device && format == AV_PIX_FMT_D3D11) { + return SDL_TRUE; + } +#endif if (GetTextureFormat(format) != SDL_PIXELFORMAT_UNKNOWN) { return SDL_TRUE; @@ -245,7 +339,7 @@ static SDL_bool SupportedPixelFormat(enum AVPixelFormat format) return SDL_FALSE; } -static enum AVPixelFormat GetPixelFormat(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) +static enum AVPixelFormat GetSupportedPixelFormat(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { const enum AVPixelFormat *p; @@ -296,29 +390,52 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV i = 0; while (!context->hw_device_ctx && (config = avcodec_get_hw_config(codec, i++)) != NULL) { +#if 0 + SDL_Log("Found %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); +#endif + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) || !SupportedPixelFormat(config->pix_fmt)) { continue; } type = AV_HWDEVICE_TYPE_NONE; - while (!context->hw_device_ctx && + while (!context->hw_device_ctx && (type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) { if (type != config->device_type) { continue; } - result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0); - if (result < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); + if (type == AV_HWDEVICE_TYPE_D3D11VA) { + AVD3D11VADeviceContext *device_context; + + context->hw_device_ctx = av_hwdevice_ctx_alloc(type); + + device_context = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)context->hw_device_ctx->data)->hwctx; + device_context->device = d3d11_device; + ID3D11Device_AddRef(device_context->device); + device_context->device_context = d3d11_context; + ID3D11DeviceContext_AddRef(device_context->device_context); + + result = av_hwdevice_ctx_init(context->hw_device_ctx); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); + } else { + SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); + } } else { - SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); + result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0); + if (result < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); + } else { + SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); + } } } } /* Allow supported hardware accelerated pixel formats */ - context->get_format = GetPixelFormat; + context->get_format = GetSupportedPixelFormat; result = avcodec_open2(context, codec, NULL); if (result < 0) { @@ -478,6 +595,96 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture) return result; } +static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) +{ +#ifdef __WIN32__ + ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0]; + UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1]; + + D3D11_TEXTURE2D_DESC desc; + SDL_zero(desc); + ID3D11Texture2D_GetDesc(pTexture, &desc); + if (desc.Format != DXGI_FORMAT_NV12) { + SDL_SetError("Unsupported texture format, expected DXGI_FORMAT_NV12, got %d", desc.Format); + return SDL_FALSE; + } + + if (!*texture || (UINT)(*texture)->w != desc.Width || (UINT)(*texture)->h != desc.Height) { + if (*texture) { + SDL_DestroyTexture(*texture); + } else { + /* First time set up for NV12 textures */ + SetYUVConversionMode(frame); + } + + *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, desc.Width, desc.Height); + if (!*texture) { + return SDL_FALSE; + } + + /* Set up the resource views for this texture */ + struct D3D11_TextureData *pTextureData = (*texture)->driverdata; + if (pTextureData->mainTexture) { + ID3D11Texture2D_Release(pTextureData->mainTexture); + pTextureData->mainTexture = NULL; + } + if (pTextureData->mainTextureResourceView) { + ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceView); + pTextureData->mainTextureResourceView = NULL; + } + if (pTextureData->mainTextureNV) { + ID3D11Texture2D_Release(pTextureData->mainTextureNV); + pTextureData->mainTextureNV = NULL; + } + if (pTextureData->mainTextureResourceViewNV) { + ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceViewNV); + pTextureData->mainTextureResourceViewNV = NULL; + } + + desc.ArraySize = 1; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + HRESULT result = ID3D11Device_CreateTexture2D(d3d11_device, &desc, NULL, &pTextureData->mainTexture); + if (FAILED(result)) { + SDL_SetError("Couldn't create main texture: 0x%x", result); + return SDL_FALSE; + } + + pTextureData->mainTextureNV = pTextureData->mainTexture; + ID3D11Texture2D_AddRef(pTextureData->mainTextureNV); + + D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; + resourceViewDesc.Format = DXGI_FORMAT_R8_UNORM; + resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + resourceViewDesc.Texture2D.MostDetailedMip = 0; + resourceViewDesc.Texture2D.MipLevels = 1; + result = ID3D11Device_CreateShaderResourceView(d3d11_device, + (ID3D11Resource *)pTextureData->mainTexture, + &resourceViewDesc, + &pTextureData->mainTextureResourceView); + if (FAILED(result)) { + SDL_SetError("Couldn't create main texture view: 0x%x", result); + return SDL_FALSE; + } + + resourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; + result = ID3D11Device_CreateShaderResourceView(d3d11_device, + (ID3D11Resource *)pTextureData->mainTexture, + &resourceViewDesc, + &pTextureData->mainTextureResourceViewNV); + if (FAILED(result)) { + SDL_SetError("Couldn't create secondary texture view: 0x%x", result); + return SDL_FALSE; + } + } + + ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, (ID3D11Resource *)(*texture)->driverdata->mainTexture, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); + return SDL_TRUE; +#else + return SDL_FALSE; +#endif +} + static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) { switch (frame->format) { @@ -485,6 +692,8 @@ static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) return GetTextureForVAAPIFrame(frame, texture); case AV_PIX_FMT_DRM_PRIME: return GetTextureForDRMFrame(frame, texture); + case AV_PIX_FMT_D3D11: + return GetTextureForD3D11Frame(frame, texture); default: return GetTextureForMemoryFrame(frame, texture); } @@ -708,11 +917,25 @@ int main(int argc, char *argv[]) #endif #ifdef HAVE_EGL /* Try to create an EGL compatible window for DRM hardware frame support */ - CreateWindow(window_flags, SDL_TRUE); + if (!window) { + CreateWindowAndRenderer(window_flags, "opengles2"); + } #endif - if (!window && !CreateWindow(window_flags, SDL_FALSE)) { - return_code = 2; - goto quit; +#ifdef __APPLE__ + if (!window) { + CreateWindowAndRenderer(window_flags, "metal"); + } +#endif +#ifdef __WIN32__ + if (!window) { + CreateWindowAndRenderer(window_flags, "direct3d11"); + } +#endif + if (!window) { + if (!CreateWindowAndRenderer(window_flags, NULL)) { + return_code = 2; + goto quit; + } } if (SDL_SetWindowTitle(window, file) < 0) { @@ -876,6 +1099,16 @@ int main(int argc, char *argv[]) quit: #ifdef __APPLE__ CleanupVideoToolboxOutput(); +#endif +#ifdef __WIN32__ + if (d3d11_context) { + ID3D11DeviceContext_Release(d3d11_device); + d3d11_context = NULL; + } + if (d3d11_device) { + ID3D11Device_Release(d3d11_device); + d3d11_device = NULL; + } #endif SDL_free(positions); SDL_free(velocities); From 2bd478ae65a3a7e073d4d6df2364ce970bc6ed4d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 00:04:45 -0700 Subject: [PATCH 032/725] Added SDL_GetTextureDXGIResource() to get the DXGI resource associated with a render texture. Also switched the D3D11 and D3D12 renderers to use real NV12 textures for NV12 data. The combination of these two changes allows us to implement 0-copy video decode and playback for D3D11 in testffmpeg without any access to the renderer internals. --- include/SDL3/SDL_render.h | 17 +++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/render/SDL_render.c | 13 ++ src/render/SDL_sysrender.h | 2 + src/render/direct3d11/SDL_render_d3d11.c | 187 ++++++++++++++++++----- src/render/direct3d12/SDL_render_d3d12.c | 138 +++++++++-------- test/testffmpeg.c | 166 ++++---------------- test/testoverlay.c | 77 +++++++--- 10 files changed, 337 insertions(+), 266 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index d38484a1c2327..bbd4516b782be 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -404,6 +404,23 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); +typedef struct IDXGIResource IDXGIResource; +/** + * Get the DXGI resource associated with a texture. + * + * This is available when using the direct3d11 and direct3d12 renderers. + * + * Once you are done using the resource, you should release it to avoid a + * resource leak. + * + * \param texture the texture from which to get the associated resource + * \returns the DXGI resource associated with given texture or NULL if it is + * not available; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC IDXGIResource* SDLCALL SDL_GetTextureDXGIResource(SDL_Texture *texture); + /** * Query the attributes of a texture. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 54467c5f5161b..89bf3aff6e5fe 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -907,6 +907,7 @@ SDL3_0.0.0 { SDL_SetAudioStreamFrequencyRatio; SDL_SetAudioPostmixCallback; SDL_GetAudioStreamQueued; + SDL_GetTextureDXGIResource; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index da300e291329c..e7b16789b90da 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -932,3 +932,4 @@ #define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL #define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL #define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL +#define SDL_GetTextureDXGIResource SDL_GetTextureDXGIResource_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index a4ffe8d12c677..6bb5f63da287f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -978,3 +978,4 @@ SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a), SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 1df0349806d3d..9e9fc1629bdf7 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -4186,6 +4186,19 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) return NULL; } +IDXGIResource *SDL_GetTextureDXGIResource(SDL_Texture *texture) +{ + SDL_Renderer *renderer; + + CHECK_TEXTURE_MAGIC(texture, NULL); + renderer = texture->renderer; + if (renderer && renderer->GetTextureDXGIResource) { + return renderer->GetTextureDXGIResource(texture); + } + SDL_Unsupported(); + return NULL; +} + static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode) { if (blendMode == SDL_BLENDMODE_NONE_FULL) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index c7033f8f26cf3..b1cb2e8e29e1d 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -212,6 +212,8 @@ struct SDL_Renderer void *(*GetMetalLayer)(SDL_Renderer *renderer); void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer); + IDXGIResource *(*GetTextureDXGIResource)(SDL_Texture *texture); + /* The current renderer info */ SDL_RendererInfo info; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 5e1b825b9eb6f..5df9049e065a7 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -102,7 +102,6 @@ typedef struct /* NV12 texture support */ SDL_bool nv12; - ID3D11Texture2D *mainTextureNV; ID3D11ShaderResourceView *mainTextureResourceViewNV; Uint8 *pixels; @@ -187,6 +186,7 @@ static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0 #if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } }; #endif +static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } }; static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } }; static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } }; @@ -208,7 +208,7 @@ Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) } } -static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) { switch (sdlFormat) { case SDL_PIXELFORMAT_ARGB8888: @@ -217,8 +217,26 @@ static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) return DXGI_FORMAT_B8G8R8X8_UNORM; case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: /* For the Y texture */ - case SDL_PIXELFORMAT_NV21: /* For the Y texture */ + return DXGI_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + return DXGI_FORMAT_NV12; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat) +{ + switch (sdlFormat) { + case SDL_PIXELFORMAT_ARGB8888: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case SDL_PIXELFORMAT_XRGB8888: + return DXGI_FORMAT_B8G8R8X8_UNORM; + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_NV12: /* For the Y texture */ + case SDL_PIXELFORMAT_NV21: /* For the Y texture */ return DXGI_FORMAT_R8_UNORM; default: return DXGI_FORMAT_UNKNOWN; @@ -850,8 +868,7 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer) static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer); -HRESULT -D3D11_HandleDeviceLost(SDL_Renderer *renderer) +static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer) { HRESULT result = S_OK; @@ -1055,7 +1072,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData; HRESULT result; - DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format); + DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format); D3D11_TEXTURE2D_DESC textureDesc; D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; @@ -1131,29 +1148,13 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { - D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc; - textureData->nv12 = SDL_TRUE; - - nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM; - nvTextureDesc.Width = (textureDesc.Width + 1) / 2; - nvTextureDesc.Height = (textureDesc.Height + 1) / 2; - - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &nvTextureDesc, - NULL, - &textureData->mainTextureNV); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); - } } #endif /* SDL_HAVE_YUV */ SDL_zero(resourceViewDesc); - resourceViewDesc.Format = textureDesc.Format; + resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format); resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resourceViewDesc.Texture2D.MostDetailedMip = 0; resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; @@ -1191,7 +1192,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice, - (ID3D11Resource *)textureData->mainTextureNV, + (ID3D11Resource *)textureData->mainTexture, &nvResourceViewDesc, &textureData->mainTextureResourceViewNV); if (FAILED(result)) { @@ -1239,7 +1240,6 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer, SAFE_RELEASE(data->mainTextureResourceViewU); SAFE_RELEASE(data->mainTextureV); SAFE_RELEASE(data->mainTextureResourceViewV); - SAFE_RELEASE(data->mainTextureNV); SAFE_RELEASE(data->mainTextureResourceViewNV); SDL_free(data->pixels); #endif @@ -1286,6 +1286,11 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result); } + if (stagingTextureDesc.Format == DXGI_FORMAT_NV12) { + /* Copy the UV plane as well */ + h += (h + 1) / 2; + } + src = (const Uint8 *)pixels; dst = textureMemory.pData; length = w * bpp; @@ -1355,15 +1360,6 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return -1; } } - - if (textureData->nv12) { - /* Skip to the correct offset into the next texture */ - srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2)) < 0) { - return -1; - } - } #endif /* SDL_HAVE_YUV */ return 0; } @@ -1401,18 +1397,110 @@ static int D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; + ID3D11Texture2D *stagingTexture; + const Uint8 *src; + Uint8 *dst; + int w, h, row; + UINT length; + HRESULT result; + D3D11_TEXTURE2D_DESC stagingTextureDesc; + D3D11_MAPPED_SUBRESOURCE textureMemory; if (textureData == NULL) { return SDL_SetError("Texture is not currently available"); } - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) { - return -1; + w = rect->w; + h = rect->h; + + /* Create a 'staging' texture, which will be used to write to a portion of the main texture. */ + ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc); + stagingTextureDesc.Width = w; + stagingTextureDesc.Height = h; + stagingTextureDesc.BindFlags = 0; + stagingTextureDesc.MiscFlags = 0; + stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + stagingTextureDesc.Usage = D3D11_USAGE_STAGING; + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &stagingTextureDesc, + NULL, + &stagingTexture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result); } - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch) < 0) { - return -1; + /* Get a write-only pointer to data in the staging texture: */ + result = ID3D11DeviceContext_Map(rendererData->d3dContext, + (ID3D11Resource *)stagingTexture, + 0, + D3D11_MAP_WRITE, + 0, + &textureMemory); + if (FAILED(result)) { + SAFE_RELEASE(stagingTexture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result); + } + + src = Yplane; + dst = textureMemory.pData; + length = w; + if (length == (UINT)Ypitch && length == textureMemory.RowPitch) { + SDL_memcpy(dst, src, (size_t)length * rect->h); + dst += length * rect->h; + } else { + if (length > (UINT)Ypitch) { + length = Ypitch; + } + if (length > textureMemory.RowPitch) { + length = textureMemory.RowPitch; + } + for (row = 0; row < h; ++row) { + SDL_memcpy(dst, src, length); + src += Ypitch; + dst += textureMemory.RowPitch; + } + } + + /* Adjust dimensions for the UV plane */ + w = ((w + 1) / 2) * 2; + h = ((h + 1) / 2); + + src = UVplane; + length = w; + if (length == (UINT)UVpitch && length == textureMemory.RowPitch) { + SDL_memcpy(dst, src, (size_t)length * h); + } else { + if (length > (UINT)UVpitch) { + length = UVpitch; + } + if (length > textureMemory.RowPitch) { + length = textureMemory.RowPitch; + } + for (row = 0; row < h; ++row) { + SDL_memcpy(dst, src, length); + src += UVpitch; + dst += textureMemory.RowPitch; + } } + + /* Commit the pixel buffer's changes back to the staging texture: */ + ID3D11DeviceContext_Unmap(rendererData->d3dContext, + (ID3D11Resource *)stagingTexture, + 0); + + /* Copy the staging texture's contents back to the texture: */ + ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext, + (ID3D11Resource *)textureData->mainTexture, + 0, + rect->x, + rect->y, + 0, + (ID3D11Resource *)stagingTexture, + 0, + NULL); + + SAFE_RELEASE(stagingTexture); + return 0; } #endif @@ -1548,6 +1636,26 @@ static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; } +static IDXGIResource *D3D11_GetTextureDXGIResource(SDL_Texture *texture) +{ + D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; + IDXGIResource *resource = NULL; + HRESULT result; + + if (textureData == NULL || textureData->mainTexture == NULL) { + SDL_SetError("Texture is not currently available"); + return NULL; + } + + + result = ID3D11Texture2D_QueryInterface(textureData->mainTexture, &SDL_IID_IDXGIResource, (void **)&resource); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); + return NULL; + } + return resource; +} + static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; @@ -2324,6 +2432,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D11_LockTexture; renderer->UnlockTexture = D3D11_UnlockTexture; renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode; + renderer->GetTextureDXGIResource = D3D11_GetTextureDXGIResource; renderer->SetRenderTarget = D3D11_SetRenderTarget; renderer->QueueSetViewport = D3D11_QueueSetViewport; renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 43ce78b4c2e0d..161bc700bd210 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -123,9 +123,7 @@ typedef struct /* NV12 texture support */ SDL_bool nv12; - ID3D12Resource *mainTextureNV; D3D12_CPU_DESCRIPTOR_HANDLE mainTextureResourceViewNV; - D3D12_RESOURCE_STATES mainResourceStateNV; SIZE_T mainSRVIndexNV; Uint8 *pixels; @@ -257,6 +255,7 @@ static const GUID SDL_IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { static const GUID SDL_IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } }; static const GUID SDL_IID_ID3D12GraphicsCommandList2 = { 0x38C3E585, 0xFF17, 0x412C, { 0x91, 0x50, 0x4F, 0xC6, 0xF9, 0xD7, 0x2A, 0x28 } }; static const GUID SDL_IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } }; +static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } }; static const GUID SDL_IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } }; static const GUID SDL_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } }; @@ -284,7 +283,25 @@ Uint32 D3D12_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) } } -static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) +{ + switch (sdlFormat) { + case SDL_PIXELFORMAT_ARGB8888: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case SDL_PIXELFORMAT_XRGB8888: + return DXGI_FORMAT_B8G8R8X8_UNORM; + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + return DXGI_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + return DXGI_FORMAT_NV12; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat) { switch (sdlFormat) { case SDL_PIXELFORMAT_ARGB8888: @@ -703,7 +720,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) HRESULT result = S_OK; UINT creationFlags = 0; int i, j, k, l; - SDL_bool createDebug = SDL_FALSE; + SDL_bool createDebug; D3D12_COMMAND_QUEUE_DESC queueDesc; D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc; @@ -1417,7 +1434,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData; HRESULT result; - DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format); + DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format); D3D12_RESOURCE_DESC textureDesc; D3D12_HEAP_PROPERTIES heapProps; D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; @@ -1508,34 +1525,13 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { - D3D12_RESOURCE_DESC nvTextureDesc = textureDesc; - textureData->nv12 = SDL_TRUE; - - nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM; - nvTextureDesc.Width = (textureDesc.Width + 1) / 2; - nvTextureDesc.Height = (textureDesc.Height + 1) / 2; - - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &nvTextureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureNV); - textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateTexture2D"), result); - } } #endif /* SDL_HAVE_YUV */ SDL_zero(resourceViewDesc); resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - resourceViewDesc.Format = textureDesc.Format; + resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format); resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - resourceViewDesc.Texture2D.MostDetailedMip = 0; resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; textureData->mainSRVIndex = D3D12_GetAvailableSRVIndex(renderer); @@ -1569,12 +1565,13 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc; nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; + nvResourceViewDesc.Texture2D.PlaneSlice = 1; D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewNV); textureData->mainSRVIndexNV = D3D12_GetAvailableSRVIndex(renderer); textureData->mainTextureResourceViewNV.ptr += textureData->mainSRVIndexNV * rendererData->srvDescriptorSize; D3D_CALL(rendererData->d3dDevice, CreateShaderResourceView, - textureData->mainTextureNV, + textureData->mainTexture, &nvResourceViewDesc, textureData->mainTextureResourceViewNV); } @@ -1623,8 +1620,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexU); D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexV); } - SAFE_RELEASE(textureData->mainTextureNV); - if (textureData->yuv) { + if (textureData->nv12) { D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexNV); } SDL_free(textureData->pixels); @@ -1633,22 +1629,22 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, texture->driverdata = NULL; } -static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState) +static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int plane, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState) { const Uint8 *src; Uint8 *dst; - int row; UINT length; HRESULT result; D3D12_RESOURCE_DESC textureDesc; D3D12_RESOURCE_DESC uploadDesc; D3D12_HEAP_PROPERTIES heapProps; - D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc; D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTextureDesc; D3D12_TEXTURE_COPY_LOCATION srcLocation; D3D12_TEXTURE_COPY_LOCATION dstLocation; BYTE *textureMemory; ID3D12Resource *uploadBuffer; + UINT row, NumRows, RowPitch; + UINT64 RowLength; /* Create an upload buffer, which will be used to write to the main texture. */ SDL_zero(textureDesc); @@ -1671,13 +1667,14 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res /* Figure out how much we need to allocate for the upload buffer */ D3D_CALL(rendererData->d3dDevice, GetCopyableFootprints, &textureDesc, - 0, + plane, 1, 0, - NULL, - NULL, - NULL, + &placedTextureDesc, + &NumRows, + &RowLength, &uploadDesc.Width); + RowPitch = placedTextureDesc.Footprint.RowPitch; SDL_zero(heapProps); heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; @@ -1708,33 +1705,22 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Resource::Map [map staging texture]"), result); } - SDL_zero(pitchedDesc); - pitchedDesc.Format = textureDesc.Format; - pitchedDesc.Width = w; - pitchedDesc.Height = h; - pitchedDesc.Depth = 1; - pitchedDesc.RowPitch = D3D12_Align(w * bpp, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - - SDL_zero(placedTextureDesc); - placedTextureDesc.Offset = 0; - placedTextureDesc.Footprint = pitchedDesc; - src = (const Uint8 *)pixels; dst = textureMemory; - length = w * bpp; - if (length == (UINT)pitch && length == pitchedDesc.RowPitch) { - SDL_memcpy(dst, src, (size_t)length * h); + length = RowLength; + if (length == (UINT)pitch && length == RowPitch) { + SDL_memcpy(dst, src, (size_t)length * NumRows); } else { if (length > (UINT)pitch) { length = pitch; } - if (length > pitchedDesc.RowPitch) { - length = pitchedDesc.RowPitch; + if (length > RowPitch) { + length = RowPitch; } - for (row = 0; row < h; ++row) { + for (row = NumRows; row--; ) { SDL_memcpy(dst, src, length); src += pitch; - dst += pitchedDesc.RowPitch; + dst += RowPitch; } } @@ -1748,7 +1734,7 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res SDL_zero(dstLocation); dstLocation.pResource = texture; dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstLocation.SubresourceIndex = 0; + dstLocation.SubresourceIndex = plane; SDL_zero(srcLocation); srcLocation.pResource = rendererData->uploadBuffers[rendererData->currentUploadBuffer]; @@ -1787,7 +1773,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { return -1; } #if SDL_HAVE_YUV @@ -1795,13 +1781,13 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) { return -1; } /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2)); - if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) { return -1; } } @@ -1810,7 +1796,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2), &textureData->mainResourceStateNV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { return -1; } } @@ -1832,13 +1818,13 @@ static int D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) { return -1; } return 0; @@ -1856,11 +1842,11 @@ static int D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch, &textureData->mainResourceStateNV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState) < 0) { return -1; } return 0; @@ -2078,6 +2064,25 @@ static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR; } +static IDXGIResource *D3D12_GetTextureDXGIResource(SDL_Texture *texture) +{ + D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; + IDXGIResource *resource = NULL; + HRESULT result; + + if (textureData == NULL || textureData->mainTexture == NULL) { + SDL_SetError("Texture is not currently available"); + return NULL; + } + + result = D3D_CALL(textureData->mainTexture, QueryInterface, D3D_GUID(SDL_IID_IDXGIResource), (void **)&resource); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); + return NULL; + } + return resource; +} + static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; @@ -2550,8 +2555,6 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c /* Make sure each texture is in the correct state to be accessed by the pixel shader. */ D3D12_TransitionResource(rendererData, textureData->mainTexture, textureData->mainResourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); textureData->mainResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - D3D12_TransitionResource(rendererData, textureData->mainTextureNV, textureData->mainResourceStateNV, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; return D3D12_SetDrawState(renderer, cmd, shader, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix); @@ -2979,6 +2982,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D12_LockTexture; renderer->UnlockTexture = D3D12_UnlockTexture; renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode; + renderer->GetTextureDXGIResource = D3D12_GetTextureDXGIResource; renderer->SetRenderTarget = D3D12_SetRenderTarget; renderer->QueueSetViewport = D3D12_QueueSetViewport; renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 5150a4306da63..e7cc1b89e434e 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -20,11 +20,18 @@ #include #include +#include +#include +#include +#include + #ifdef HAVE_EGL #include #include #include +#include + #ifndef fourcc_code #define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) #endif @@ -42,86 +49,8 @@ #ifdef __WIN32__ #define COBJMACROS -#include - -struct D3D11_TextureData -{ - ID3D11Texture2D *mainTexture; - ID3D11ShaderResourceView *mainTextureResourceView; - ID3D11RenderTargetView *mainTextureRenderTargetView; - ID3D11Texture2D *stagingTexture; - int lockedTexturePositionX; - int lockedTexturePositionY; - D3D11_FILTER scaleMode; - - /* YV12 texture support */ - SDL_bool yuv; - ID3D11Texture2D *mainTextureU; - ID3D11ShaderResourceView *mainTextureResourceViewU; - ID3D11Texture2D *mainTextureV; - ID3D11ShaderResourceView *mainTextureResourceViewV; - - /* NV12 texture support */ - SDL_bool nv12; - ID3D11Texture2D *mainTextureNV; - ID3D11ShaderResourceView *mainTextureResourceViewNV; - - Uint8 *pixels; - int pitch; - SDL_Rect locked_rect; -}; - -/* Rendering view state */ -typedef struct SDL_RenderViewState -{ - int pixel_w; - int pixel_h; - SDL_Rect viewport; - SDL_Rect clip_rect; - SDL_bool clipping_enabled; - SDL_FPoint scale; - -} SDL_RenderViewState; - -struct SDL_Texture -{ - const void *magic; - Uint32 format; /**< The pixel format of the texture */ - int access; /**< SDL_TextureAccess */ - int w; /**< The width of the texture */ - int h; /**< The height of the texture */ - int modMode; /**< The texture modulation mode */ - SDL_BlendMode blendMode; /**< The texture blend mode */ - SDL_ScaleMode scaleMode; /**< The texture scale mode */ - SDL_Color color; /**< Texture modulation values */ - SDL_RenderViewState view; /**< Target texture view state */ - - SDL_Renderer *renderer; - - /* Support for formats not supported directly by the renderer */ - SDL_Texture *native; - void /*SDL_SW_YUVTexture*/ *yuv; - void *pixels; - int pitch; - SDL_Rect locked_rect; - SDL_Surface *locked_surface; /**< Locked region exposed as a SDL surface */ - - Uint32 last_command_generation; /* last command queue generation this texture was in. */ - - struct D3D11_TextureData /*void*/ *driverdata; /**< Driver specific texture representation */ - void *userdata; - - SDL_Texture *prev; - SDL_Texture *next; -}; -#endif /* __WIN32__ */ - -#include -#include -#include #include -#include -#include +#endif /* __WIN32__ */ #include "icon.h" @@ -152,6 +81,7 @@ static SDL_bool has_videotoolbox_output; #ifdef __WIN32__ static ID3D11Device *d3d11_device; static ID3D11DeviceContext *d3d11_context; +static const GUID SDL_IID_ID3D11Resource = { 0xdc8e63f3, 0xd12b, 0x4952, { 0xb4, 0x7b, 0x5e, 0x45, 0x02, 0x6a, 0x86, 0x2d } }; #endif static int done; @@ -406,6 +336,7 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV continue; } +#ifdef __WIN32__ if (type == AV_HWDEVICE_TYPE_D3D11VA) { AVD3D11VADeviceContext *device_context; @@ -423,7 +354,9 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV } else { SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); } - } else { + } else +#endif + { result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0); if (result < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); @@ -598,6 +531,7 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture) static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) { #ifdef __WIN32__ + int texture_width = 0, texture_height = 0; ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0]; UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1]; @@ -609,7 +543,10 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) return SDL_FALSE; } - if (!*texture || (UINT)(*texture)->w != desc.Width || (UINT)(*texture)->h != desc.Height) { + if (*texture) { + SDL_QueryTexture(*texture, NULL, NULL, &texture_width, &texture_height); + } + if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) { if (*texture) { SDL_DestroyTexture(*texture); } else { @@ -621,64 +558,23 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) if (!*texture) { return SDL_FALSE; } + } - /* Set up the resource views for this texture */ - struct D3D11_TextureData *pTextureData = (*texture)->driverdata; - if (pTextureData->mainTexture) { - ID3D11Texture2D_Release(pTextureData->mainTexture); - pTextureData->mainTexture = NULL; - } - if (pTextureData->mainTextureResourceView) { - ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceView); - pTextureData->mainTextureResourceView = NULL; - } - if (pTextureData->mainTextureNV) { - ID3D11Texture2D_Release(pTextureData->mainTextureNV); - pTextureData->mainTextureNV = NULL; - } - if (pTextureData->mainTextureResourceViewNV) { - ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceViewNV); - pTextureData->mainTextureResourceViewNV = NULL; - } - - desc.ArraySize = 1; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - - HRESULT result = ID3D11Device_CreateTexture2D(d3d11_device, &desc, NULL, &pTextureData->mainTexture); - if (FAILED(result)) { - SDL_SetError("Couldn't create main texture: 0x%x", result); - return SDL_FALSE; - } - - pTextureData->mainTextureNV = pTextureData->mainTexture; - ID3D11Texture2D_AddRef(pTextureData->mainTextureNV); - - D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.Format = DXGI_FORMAT_R8_UNORM; - resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - resourceViewDesc.Texture2D.MostDetailedMip = 0; - resourceViewDesc.Texture2D.MipLevels = 1; - result = ID3D11Device_CreateShaderResourceView(d3d11_device, - (ID3D11Resource *)pTextureData->mainTexture, - &resourceViewDesc, - &pTextureData->mainTextureResourceView); - if (FAILED(result)) { - SDL_SetError("Couldn't create main texture view: 0x%x", result); - return SDL_FALSE; - } + IDXGIResource *dxgi_resource = SDL_GetTextureDXGIResource(*texture); + if (!dxgi_resource) { + return SDL_FALSE; + } - resourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; - result = ID3D11Device_CreateShaderResourceView(d3d11_device, - (ID3D11Resource *)pTextureData->mainTexture, - &resourceViewDesc, - &pTextureData->mainTextureResourceViewNV); - if (FAILED(result)) { - SDL_SetError("Couldn't create secondary texture view: 0x%x", result); - return SDL_FALSE; - } + ID3D11Resource *dx11_resource = NULL; + HRESULT result = IDXGIResource_QueryInterface(dxgi_resource, &SDL_IID_ID3D11Resource, (void **)&dx11_resource); + IDXGIResource_Release(dxgi_resource); + if (FAILED(result)) { + SDL_SetError("Couldn't get texture ID3D11Resource interface: 0x%x", result); + return SDL_FALSE; } + ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, dx11_resource, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); + ID3D11Resource_Release(dx11_resource); - ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, (ID3D11Resource *)(*texture)->driverdata->mainTexture, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); return SDL_TRUE; #else return SDL_FALSE; diff --git a/test/testoverlay.c b/test/testoverlay.c index abd97c40ab178..5d42efc74d7f9 100644 --- a/test/testoverlay.c +++ b/test/testoverlay.c @@ -147,6 +147,7 @@ static Uint64 next_fps_check; static Uint32 frames; static const Uint32 fps_check_delay = 5000; +static Uint32 yuv_format = SDL_PIXELFORMAT_YV12; static SDL_Surface *MooseYUVSurfaces[MOOSEFRAMES_COUNT]; static SDL_Texture *MooseTexture = NULL; static SDL_FRect displayrect; @@ -187,31 +188,58 @@ static void MoveSprites(SDL_Renderer *renderer) static int i = 0; if (streaming) { - if (!paused) { - i = (i + 1) % MOOSEFRAMES_COUNT; - SDL_UpdateTexture(MooseTexture, NULL, MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch); - } - SDL_RenderClear(renderer); - SDL_RenderTexture(renderer, MooseTexture, NULL, &displayrect); - SDL_RenderPresent(renderer); + if (!paused) { + i = (i + 1) % MOOSEFRAMES_COUNT; + /* Test both upload paths for NV12/NV21 formats */ + if ((yuv_format == SDL_PIXELFORMAT_NV12 || yuv_format == SDL_PIXELFORMAT_NV21) && + (i % 2) == 0) { +#ifdef TEST_RECT_UPDATE + SDL_Rect rect; + + if (i == 0) { + rect.x = 0; + rect.y = 0; + rect.w = MOOSEPIC_W; + rect.h = MOOSEPIC_H; + } else { + rect.x = MOOSEPIC_W / 4; + rect.y = MOOSEPIC_H / 4; + rect.w = MOOSEPIC_W / 2; + rect.h = MOOSEPIC_H / 2; + } + SDL_UpdateNVTexture(MooseTexture, &rect, + (Uint8 *)MooseYUVSurfaces[i]->pixels + rect.y * MooseYUVSurfaces[i]->pitch + rect.x, MooseYUVSurfaces[i]->pitch, + (Uint8 *)MooseYUVSurfaces[i]->pixels + MOOSEFRAME_SIZE + (rect.y + 1) / 2 * MooseYUVSurfaces[i]->pitch + (rect.x + 1) / 2, MooseYUVSurfaces[i]->pitch); +#else + SDL_UpdateNVTexture(MooseTexture, NULL, + MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch, + (Uint8 *)MooseYUVSurfaces[i]->pixels + MOOSEFRAME_SIZE, MooseYUVSurfaces[i]->pitch); +#endif + } else { + SDL_UpdateTexture(MooseTexture, NULL, MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch); + } + } + SDL_RenderClear(renderer); + SDL_RenderTexture(renderer, MooseTexture, NULL, &displayrect); + SDL_RenderPresent(renderer); } else { - SDL_Texture *tmp; - - /* Test SDL_CreateTextureFromSurface */ - if (!paused) { - i = (i + 1) % MOOSEFRAMES_COUNT; - } - - tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]); - if (tmp == NULL) { - SDL_Log("Error %s", SDL_GetError()); - quit(7); - } - - SDL_RenderClear(renderer); - SDL_RenderTexture(renderer, tmp, NULL, &displayrect); - SDL_RenderPresent(renderer); - SDL_DestroyTexture(tmp); + SDL_Texture *tmp; + + /* Test SDL_CreateTextureFromSurface */ + if (!paused) { + i = (i + 1) % MOOSEFRAMES_COUNT; + } + + tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]); + if (tmp == NULL) { + SDL_Log("Error %s", SDL_GetError()); + quit(7); + } + + SDL_RenderClear(renderer); + SDL_RenderTexture(renderer, tmp, NULL, &displayrect); + SDL_RenderPresent(renderer); + SDL_DestroyTexture(tmp); } } @@ -295,7 +323,6 @@ int main(int argc, char **argv) int nodelay = 0; int scale = 5; char *filename = NULL; - int yuv_format = SDL_PIXELFORMAT_YV12; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); From 303f4e965cec50f33fa1b7346575553e912e2edd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 03:58:57 -0700 Subject: [PATCH 033/725] testffmpeg works with ffmpeg 5.1.3 and newer --- test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 527112d08b50f..0a22daa1738d4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -183,7 +183,7 @@ if(HAVE_LIBUDEV_H) endif() include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") -if(FFmpeg_FOUND AND (FFmpeg_AVCODEC_VERSION STREQUAL "" OR FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "60")) +if(FFmpeg_FOUND AND (FFmpeg_AVCODEC_VERSION STREQUAL "" OR FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "59.37")) if(APPLE) add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c testffmpeg_videotoolbox.m ${icon_bmp_header}) target_link_options(testffmpeg PRIVATE "-Wl,-framework,CoreFoundation" "-Wl,-framework,CoreVideo" "-Wl,-framework,Metal") @@ -199,7 +199,7 @@ if(FFmpeg_FOUND AND (FFmpeg_AVCODEC_VERSION STREQUAL "" OR FFmpeg_AVCODEC_VERSIO endif() target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) else() - message(STATUS "Can't find ffmpeg 6.0 or newer, skipping testffmpeg") + message(STATUS "Can't find ffmpeg 5.1.3 or newer, skipping testffmpeg") endif() add_sdl_test_executable(checkkeys SOURCES checkkeys.c) From 86ada8a9f083aa3bbc604664f64de083f78e1a5e Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Tue, 10 Oct 2023 14:02:40 +0300 Subject: [PATCH 034/725] fix testffmpeg.c build. --- test/testffmpeg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index e7cc1b89e434e..5ef3bae73e979 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -726,6 +726,7 @@ static SDL_bool IsPlanarAudioFormat(enum AVSampleFormat format) static void InterleaveAudio(AVFrame *frame, const SDL_AudioSpec *spec) { + int c, n; int samplesize = SDL_AUDIO_BYTESIZE(spec->format); int framesize = SDL_AUDIO_FRAMESIZE(*spec); Uint8 *data = (Uint8 *)SDL_malloc(frame->nb_samples * framesize); @@ -734,10 +735,10 @@ static void InterleaveAudio(AVFrame *frame, const SDL_AudioSpec *spec) } /* This could be optimized with SIMD and not allocating memory each time */ - for (int c = 0; c < spec->channels; ++c) { + for (c = 0; c < spec->channels; ++c) { const Uint8 *src = frame->data[c]; Uint8 *dst = data + c * samplesize; - for (int n = frame->nb_samples; n--; ) { + for (n = frame->nb_samples; n--; ) { SDL_memcpy(dst, src, samplesize); src += samplesize; dst += framesize; From adcace6f95cc8bbad2ae6e9291e5a0e9b4633f23 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 04:06:44 -0700 Subject: [PATCH 035/725] Added a "--software" option to testffmpeg This allows easy performance comparison between hardware and software decoding --- test/testffmpeg.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 5ef3bae73e979..79b4014a0d9e6 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -69,6 +69,7 @@ static SDL_Renderer *renderer; static SDL_AudioStream *audio; static SDL_Texture *video_texture; static Uint64 video_start; +static SDL_bool software_only; static SDL_bool has_eglCreateImage; #ifdef HAVE_EGL static SDL_bool has_EGL_EXT_image_dma_buf_import; @@ -248,20 +249,22 @@ static Uint32 GetTextureFormat(enum AVPixelFormat format) static SDL_bool SupportedPixelFormat(enum AVPixelFormat format) { - if (has_eglCreateImage && - (format == AV_PIX_FMT_VAAPI || format == AV_PIX_FMT_DRM_PRIME)) { - return SDL_TRUE; - } + if (!software_only) { + if (has_eglCreateImage && + (format == AV_PIX_FMT_VAAPI || format == AV_PIX_FMT_DRM_PRIME)) { + return SDL_TRUE; + } #ifdef __APPLE__ - if (has_videotoolbox_output && format == AV_PIX_FMT_VIDEOTOOLBOX) { - return SDL_TRUE; - } + if (has_videotoolbox_output && format == AV_PIX_FMT_VIDEOTOOLBOX) { + return SDL_TRUE; + } #endif #ifdef __WIN32__ - if (d3d11_device && format == AV_PIX_FMT_D3D11) { - return SDL_TRUE; - } + if (d3d11_device && format == AV_PIX_FMT_D3D11) { + return SDL_TRUE; + } #endif + } if (GetTextureFormat(format) != SDL_PIXELFORMAT_UNKNOWN) { return SDL_TRUE; @@ -789,6 +792,8 @@ int main(int argc, char *argv[]) if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) { num_sprites = SDL_atoi(argv[i+1]); ++i; + } else if (SDL_strcmp(argv[i], "--software") == 0) { + software_only = SDL_TRUE; } else { /* We'll try to open this as a media file */ file = argv[i]; From 0fe95cfba3c6394157f7ce9347353cb611037a0e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 10 Oct 2023 10:49:24 -0400 Subject: [PATCH 036/725] Sync wiki -> header --- include/SDL3/SDL_render.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index bbd4516b782be..e4a2430620069 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -405,6 +405,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); typedef struct IDXGIResource IDXGIResource; + /** * Get the DXGI resource associated with a texture. * From bf72704bfdc546af3029bd8b65e68df1a567e884 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 10 Oct 2023 17:38:23 +0100 Subject: [PATCH 037/725] audio: Disable NEON sample conversion until test failures are fixed We need to do this early in the file, so that it will be taken into account when deciding whether to define NEED_SCALAR_CONVERTER_FALLBACKS and therefore provide a non-SIMD fallback. Mitigates: https://github.com/libsdl-org/SDL/issues/8352 Signed-off-by: Simon McVittie --- src/audio/SDL_audiotypecvt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 1b45a0d98fab4..a8fb65427f5e8 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -22,6 +22,10 @@ #include "SDL_audio_c.h" +/* TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 + * can be fixed */ +#undef SDL_NEON_INTRINSICS + #ifndef SDL_CPUINFO_DISABLED #if defined(__x86_64__) && defined(SDL_SSE2_INTRINSICS) #define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ From 2d62c65a7547ad0c42f3124ed7ee0bca0e85ce99 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 12:37:38 -0700 Subject: [PATCH 038/725] Fixed build warning --- src/render/direct3d12/SDL_render_d3d12.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 161bc700bd210..fb18838dce0e9 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1707,7 +1707,7 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res src = (const Uint8 *)pixels; dst = textureMemory; - length = RowLength; + length = (UINT)RowLength; if (length == (UINT)pitch && length == RowPitch) { SDL_memcpy(dst, src, (size_t)length * NumRows); } else { From ee53e4d319098efec46dea198bd32c8dd868cf9b Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 10 Oct 2023 20:36:58 +0200 Subject: [PATCH 039/725] cmake: check ffmpeg capability instead of version --- test/CMakeLists.txt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a22daa1738d4..fa4175a8df9e7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,9 @@ # # CMake script for building the SDL tests # + +include(CheckStructHasMember) + if(SDL_TESTS_LINK_SHARED) set(sdl_name_component SDL3-shared) else() @@ -183,15 +186,20 @@ if(HAVE_LIBUDEV_H) endif() include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") -if(FFmpeg_FOUND AND (FFmpeg_AVCODEC_VERSION STREQUAL "" OR FFmpeg_AVCODEC_VERSION VERSION_GREATER_EQUAL "59.37")) +if(FFmpeg_FOUND) + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_INCLUDES "${FFmpeg_AVUTIL_INCLUDE_DIRS}") + check_struct_has_member("AVFrame" "ch_layout" "libavutil/frame.h" LIBAVUTIL_AVFRAME_HAS_CH_LAYOUT) + cmake_pop_check_state() +endif() +if(FFmpeg_FOUND AND LIBAVUTIL_AVFRAME_HAS_CH_LAYOUT) + add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) if(APPLE) - add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c testffmpeg_videotoolbox.m ${icon_bmp_header}) + target_sources(testffmpeg PRIVATE testffmpeg_videotoolbox.m) target_link_options(testffmpeg PRIVATE "-Wl,-framework,CoreFoundation" "-Wl,-framework,CoreVideo" "-Wl,-framework,Metal") - else() - add_sdl_test_executable(testffmpeg NO_C90 SOURCES testffmpeg.c ${icon_bmp_header}) endif() if(HAVE_OPENGLES_V2) - #message(STATUS "Enabling EGL support in testffmpeg") + message(DEBUG "Enabling EGL support in testffmpeg") target_compile_definitions(testffmpeg PRIVATE HAVE_EGL) if(TARGET OpenGL::EGL) target_link_libraries(testffmpeg PRIVATE OpenGL::EGL) From ebfbd7327b90211a945ecdf5018cacd2c54dd014 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 10 Oct 2023 20:52:12 +0200 Subject: [PATCH 040/725] testffmpeg: use SDL_test to parse arguments and track memory --- test/testffmpeg.c | 49 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 79b4014a0d9e6..ddf375996d551 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -765,6 +766,11 @@ static void HandleAudioFrame(AVFrame *frame) } } +static void print_usage(SDLTest_CommonState *state, const char *argv0) { + static const char *options[] = { "[--sprites N]", "[--software]", "video_file", NULL }; + SDLTest_CommonLogUsage(state, argv0, options); +} + int main(int argc, char *argv[]) { const char *file = NULL; @@ -784,24 +790,44 @@ int main(int argc, char *argv[]) Uint32 window_flags; SDL_bool flushing = SDL_FALSE; SDL_bool decoded = SDL_FALSE; + SDLTest_CommonState *state; + + /* Initialize test framework */ + state = SDLTest_CommonCreateState(argv, 0); /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); - for (i = 1; i < argc; ++i) { - if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) { - num_sprites = SDL_atoi(argv[i+1]); - ++i; - } else if (SDL_strcmp(argv[i], "--software") == 0) { - software_only = SDL_TRUE; - } else { - /* We'll try to open this as a media file */ - file = argv[i]; - break; + + /* Parse commandline */ + for (i = 1; i < argc;) { + int consumed; + + consumed = SDLTest_CommonArg(state, i); + if (!consumed) { + if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) { + num_sprites = SDL_atoi(argv[i+1]); + consumed = 2; + } else if (SDL_strcmp(argv[i], "--software") == 0) { + software_only = SDL_TRUE; + consumed = 1; + } else if (!file) { + /* We'll try to open this as a media file */ + file = argv[i]; + consumed = 1; + } + } + if (consumed <= 0) { + print_usage(state, argv[0]); + return_code = 1; + goto quit; } + + i += consumed; } + if (!file) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s [--sprites N] video_file\n", argv[0]); + print_usage(state, argv[0]); return_code = 1; goto quit; } @@ -1022,5 +1048,6 @@ int main(int argc, char *argv[]) SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); + SDLTest_CommonDestroyState(state); return return_code; } From 99fa0d6caeca00e2968beb364cd0493bdd560e61 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 15:17:58 -0700 Subject: [PATCH 041/725] Disable low latency audio by default when using AAudio on Android Some devices have flat sounding audio when low latency mode is enabled. In particular this was reported on the Samsung SM-T290 running Android 11. --- src/audio/aaudio/SDL_aaudio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 977d84e4c557a..ea569503ec88a 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -312,7 +312,9 @@ static int BuildAAudioStream(SDL_AudioDevice *device) ctx.AAudioStreamBuilder_setDirection(builder, direction); ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device); ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device); +#if 0 // Some devices have flat sounding audio when low latency mode is enabled ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); +#endif LOGI("AAudio Try to open %u hz %u bit chan %u %s samples %u", device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), From aee4862958d3365d3995d017d4d3b4642edd6358 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 11 Oct 2023 00:22:30 +0200 Subject: [PATCH 042/725] ci: stop FreeBSD job after 30 minutes --- .github/workflows/vmactions.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/vmactions.yml b/.github/workflows/vmactions.yml index e78683412bc21..cdcf340b4bc60 100644 --- a/.github/workflows/vmactions.yml +++ b/.github/workflows/vmactions.yml @@ -10,6 +10,7 @@ jobs: freebsd: runs-on: macos-12 name: FreeBSD + timeout-minutes: 30 steps: - uses: actions/checkout@v3 - name: Build From 3a47fb7208b6746a36683e394e49c9f711e75133 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 15:46:15 -0700 Subject: [PATCH 043/725] The sensor and joystick instance ID generator isn't guarded by a lock. --- src/joystick/SDL_joystick.c | 2 +- src/sensor/SDL_sensor.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 48385b4b916c2..268ba9fc49ea2 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -116,7 +116,7 @@ static SDL_bool SDL_joysticks_initialized; static SDL_bool SDL_joysticks_quitting; static SDL_bool SDL_joystick_being_added; static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; -static SDL_AtomicInt SDL_last_joystick_instance_id SDL_GUARDED_BY(SDL_joystick_lock); +static SDL_AtomicInt SDL_last_joystick_instance_id; static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 26eed8984fc90..0a186e889dd85 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -58,7 +58,7 @@ static SDL_AtomicInt SDL_sensor_lock_pending; static int SDL_sensors_locked; static SDL_bool SDL_sensors_initialized; static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL; -static SDL_AtomicInt SDL_last_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock); +static SDL_AtomicInt SDL_last_sensor_instance_id; static char SDL_sensor_magic; #define CHECK_SENSOR_MAGIC(sensor, retval) \ From a7ae1de9a664748a4a4b3220c72824c26b02a9ba Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 16:37:17 -0700 Subject: [PATCH 044/725] Fixed warning C4028: formal parameter different from declaration --- src/audio/SDL_audioresample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/SDL_audioresample.h b/src/audio/SDL_audioresample.h index 84aaa2dbcfacb..fcf3f5121760b 100644 --- a/src/audio/SDL_audioresample.h +++ b/src/audio/SDL_audioresample.h @@ -26,7 +26,7 @@ // Internal functions used by SDL_AudioStream for resampling audio. // The resampler uses 32:32 fixed-point arithmetic to track its position. -Sint64 SDL_GetResampleRate(const int src_rate, const int dst_rate); +Sint64 SDL_GetResampleRate(int src_rate, int dst_rate); int SDL_GetResamplerHistoryFrames(void); int SDL_GetResamplerPaddingFrames(Sint64 resample_rate); From dc2a5f6ab20cd880a5062c293fe60c146acbd8cd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 16:38:12 -0700 Subject: [PATCH 045/725] Fixed error C2054: expected '(' to follow 'inline' --- src/video/SDL_surface_pixel_impl.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/SDL_surface_pixel_impl.h b/src/video/SDL_surface_pixel_impl.h index 591ac1e9eb654..43985b78b9bde 100644 --- a/src/video/SDL_surface_pixel_impl.h +++ b/src/video/SDL_surface_pixel_impl.h @@ -23,8 +23,7 @@ /* Internal implementation of SDL_ReadSurfacePixel, shared between SDL_shape * and SDLTest */ -static inline int -SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +static int SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { Uint32 pixel = 0; size_t bytes_per_pixel; From b6544275370e1777e7948cffebfe4bd51e3d18ca Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 17:04:00 -0700 Subject: [PATCH 046/725] Added support for the PowerA Nintendo Switch Nano Wired Controller --- src/joystick/controller_list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 0f6a589e75f0c..8d77eb89c5306 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -581,6 +581,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x20d6, 0xa714 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Spectra Controller { MAKE_CONTROLLER_ID( 0x20d6, 0xa715 ), k_eControllerType_SwitchInputOnlyController, NULL }, // Power A Fusion Wireless Arcade Stick (USB Mode) Over BT is shows up as 057e 2009 { MAKE_CONTROLLER_ID( 0x20d6, 0xa716 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Pro Controller - USB requires toggling switch on back of device + { MAKE_CONTROLLER_ID( 0x20d6, 0xa718 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Nano Wired Controller // Valve products { MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch, NULL }, // Streaming mobile touch virtual controls From 82f54af6177f3d50be1db42a528027ada6ea0a20 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 00:50:53 -0400 Subject: [PATCH 047/725] x11: Properly check for XInput2 support before using it. This specifically fixes a crash in X11_WarpMouseInternal if XInput2 was missing at runtime, but also cleans up a few other existing checks. Fixes #8378. --- src/video/x11/SDL_x11mouse.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 51eda30f32b97..7edef6a842019 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -330,13 +330,16 @@ static void X11_WarpMouseInternal(Window xwindow, float x, float y) Display *display = videodata->display; #ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 int deviceid = 0; - /* It seems XIWarpPointer() doesn't work correctly on multi-head setups: - * https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea - */ - if (ScreenCount(display) == 1) { - X11_XIGetClientPointer(display, None, &deviceid); + if (X11_Xinput2IsInitialized()) { + /* It seems XIWarpPointer() doesn't work correctly on multi-head setups: + * https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea + */ + if (ScreenCount(display) == 1) { + X11_XIGetClientPointer(display, None, &deviceid); + } } if (deviceid != 0) { + SDL_assert(SDL_X11_HAVE_XINPUT2); X11_XIWarpPointer(display, deviceid, None, xwindow, 0.0, 0.0, 0, 0, x, y); } else #endif @@ -370,12 +373,7 @@ static int X11_WarpMouseGlobal(float x, float y) static int X11_SetRelativeMouseMode(SDL_bool enabled) { -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - if (X11_Xinput2IsInitialized()) { - return 0; - } -#endif - return SDL_Unsupported(); + return X11_Xinput2IsInitialized() ? 0 : SDL_Unsupported(); } static int X11_CaptureMouse(SDL_Window *window) @@ -413,12 +411,9 @@ static Uint32 X11_GetGlobalMouseState(float *x, float *y) /* !!! FIXME: should we XSync() here first? */ -#ifndef SDL_VIDEO_DRIVER_X11_XINPUT2 - videodata->global_mouse_changed = SDL_TRUE; -#else - if (!SDL_X11_HAVE_XINPUT2) + if (!X11_Xinput2IsInitialized()) { videodata->global_mouse_changed = SDL_TRUE; -#endif + } /* check if we have this cached since XInput last saw the mouse move. */ /* !!! FIXME: can we just calculate this from XInput's events? */ From 321fc1841700a2f9920539f3caa348368fc57f64 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 01:20:18 -0400 Subject: [PATCH 048/725] README-migration.md: Added note about SDL_HasRDTSC removal. Fixes #8374. --- docs/README-migration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/README-migration.md b/docs/README-migration.md index c4dd52b5f6e48..7878b1f4d07ac 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -276,6 +276,8 @@ The intrinsics headers (mmintrin.h, etc.) have been moved to ` Date: Wed, 11 Oct 2023 10:01:52 -0400 Subject: [PATCH 049/725] testaudio: Make program usable without a 3-button mouse. --- test/testaudio.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index 94de784715d3a..3cb71a764273f 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -113,6 +113,9 @@ static Thing *mouseover_thing = NULL; static Thing *droppable_highlighted_thing = NULL; static Thing *dragging_thing = NULL; static int dragging_button = -1; +static int dragging_button_real = -1; +static SDL_bool ctrl_held = SDL_FALSE; +static SDL_bool alt_held = SDL_FALSE; static Texture *physdev_texture = NULL; static Texture *logdev_texture = NULL; @@ -1077,11 +1080,21 @@ static void Loop(void) thing = UpdateMouseOver(event.motion.x, event.motion.y); if ((dragging_button == -1) && event.motion.state) { if (event.motion.state & SDL_BUTTON_LMASK) { - dragging_button = SDL_BUTTON_LEFT; + /* for people that don't have all three buttons... */ + if (ctrl_held) { + dragging_button = SDL_BUTTON_RIGHT; + } else if (alt_held) { + dragging_button = SDL_BUTTON_MIDDLE; + } else { + dragging_button = SDL_BUTTON_LEFT; + } + dragging_button_real = SDL_BUTTON_LEFT; } else if (event.motion.state & SDL_BUTTON_RMASK) { dragging_button = SDL_BUTTON_RIGHT; + dragging_button_real = SDL_BUTTON_RIGHT; } else if (event.motion.state & SDL_BUTTON_MMASK) { dragging_button = SDL_BUTTON_MIDDLE; + dragging_button_real = SDL_BUTTON_MIDDLE; } @@ -1117,10 +1130,11 @@ static void Loop(void) break; case SDL_EVENT_MOUSE_BUTTON_UP: - if (dragging_button == event.button.button) { + if (dragging_button_real == event.button.button) { Thing *dropped_thing = dragging_thing; dragging_thing = NULL; dragging_button = -1; + dragging_button_real = -1; if (dropped_thing && dropped_thing->ondrop) { dropped_thing->ondrop(dropped_thing, event.button.button, event.button.x, event.button.y); } @@ -1133,6 +1147,12 @@ static void Loop(void) UpdateMouseOver(event.wheel.mouseX, event.wheel.mouseY); break; + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + ctrl_held = ((event.key.keysym.mod & SDL_KMOD_CTRL) != 0) ? SDL_TRUE : SDL_FALSE; + alt_held = ((event.key.keysym.mod & SDL_KMOD_ALT) != 0) ? SDL_TRUE : SDL_FALSE; + break; + case SDL_EVENT_DROP_FILE: SDL_Log("Drop file! '%s'", event.drop.file); LoadWavThing(event.drop.file, event.drop.x, event.drop.y); From 044046bc50b45c3b9ed0c00b772f48fa3918ab77 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 10:37:28 -0400 Subject: [PATCH 050/725] audio: Fixed assertions when capture devices have wrong audio formats. Fixes #8376. --- src/audio/SDL_audio.c | 44 ++++++++++++++++++++++++++-------------- src/audio/SDL_sysaudio.h | 2 ++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index f6bdfc83a1faf..d5475bbd84760 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -189,23 +189,25 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) // should hold device->lock before calling. static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; - const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device); - SDL_AudioSpec spec; + if (!device->iscapture) { // for capture devices, we only want to move to float32 for postmix, which we'll handle elsewhere. + const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device); + SDL_AudioSpec spec; - device->simple_copy = simple_copy; - SDL_copyp(&spec, &device->spec); - if (!simple_copy) { - spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format. - } + device->simple_copy = simple_copy; + SDL_copyp(&spec, &device->spec); - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { - // set the proper end of the stream to the device's format. - // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. - SDL_LockMutex(stream->lock); - SDL_copyp(iscapture ? &stream->src_spec : &stream->dst_spec, &spec); - SDL_UnlockMutex(stream->lock); + if (!simple_copy) { + spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format. + } + + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + // set the proper end of the stream to the device's format. + // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. + SDL_LockMutex(stream->lock); + SDL_copyp(&stream->dst_spec, &spec); + SDL_UnlockMutex(stream->lock); + } } } } @@ -1567,6 +1569,16 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac if (retval == 0) { logdev->postmix = callback; logdev->postmix_userdata = userdata; + + if (device->iscapture) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + // set the proper end of the stream to the device's format. + // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. + SDL_LockMutex(stream->lock); + stream->src_spec.format = callback ? SDL_AUDIO_F32 : device->spec.format; + SDL_UnlockMutex(stream->lock); + } + } } UpdateAudioStreamFormatsPhysical(device); @@ -1639,6 +1651,8 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int } logdev->bound_streams = stream; + stream->src_spec.format = logdev->postmix ? SDL_AUDIO_F32 : device->spec.format; + SDL_UnlockMutex(stream->lock); } } diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 284a718241acd..68003171563ec 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -156,6 +156,8 @@ typedef struct SDL_AudioDriver SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams. SDL_AudioDeviceID default_output_device_id; SDL_AudioDeviceID default_capture_device_id; + + // !!! FIXME: most (all?) of these don't have to be atomic. SDL_AtomicInt output_device_count; SDL_AtomicInt capture_device_count; SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs From 9a5f7b17c60c534df73cce9dacfb3a02857b5fd0 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 11 Oct 2023 11:23:24 -0400 Subject: [PATCH 051/725] Use SDL wrapped getenv function --- src/video/wayland/SDL_waylandvideo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 9117410e23e65..d6c0d0e37bb4e 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -129,8 +129,8 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) struct wl_display *display; /* Are we trying to connect to or are currently in a Wayland session? */ - if (!getenv("WAYLAND_DISPLAY")) { - const char *session = getenv("XDG_SESSION_TYPE"); + if (!SDL_getenv("WAYLAND_DISPLAY")) { + const char *session = SDL_getenv("XDG_SESSION_TYPE"); if (session && SDL_strcasecmp(session, "wayland")) { return NULL; } From c552cc6847710b50565cf71b6b2316c6d12c23b0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 09:23:23 -0700 Subject: [PATCH 052/725] We don't require the audio system to be initialized for audio format conversion This is helpful for tools pipelines where audio devices are never used. --- src/audio/SDL_audio.c | 3 --- src/audio/SDL_audiocvt.c | 6 ++---- test/testautomation_audio.c | 7 +++++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index d5475bbd84760..b6ac6517cc977 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -602,9 +602,6 @@ int SDL_InitAudio(const char *driver_name) SDL_QuitAudio(); // shutdown driver if already running. } - SDL_ChooseAudioConverters(); - SDL_SetupAudioResampler(); - SDL_RWLock *device_list_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole audio subsystem. if (!device_list_lock) { return -1; diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index b2f74f99febc5..0dc1719658ecb 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -404,10 +404,8 @@ static int UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSp SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec) { - if (!SDL_WasInit(SDL_INIT_AUDIO)) { - SDL_SetError("Audio subsystem is not initialized"); - return NULL; - } + SDL_ChooseAudioConverters(); + SDL_SetupAudioResampler(); SDL_AudioStream *retval = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream)); if (retval == NULL) { diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c index 829962fe87171..7ae022684cf1c 100644 --- a/test/testautomation_audio.c +++ b/test/testautomation_audio.c @@ -481,6 +481,10 @@ static int audio_buildAudioStream(void *arg) SDL_AudioSpec spec2; int i, ii, j, jj, k, kk; + /* Call Quit */ + SDL_QuitSubSystem(SDL_INIT_AUDIO); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); + /* No conversion needed */ spec1.format = SDL_AUDIO_S16LE; spec1.channels = 2; @@ -528,6 +532,9 @@ static int audio_buildAudioStream(void *arg) } } + /* Restart audio again */ + audioSetUp(NULL); + return TEST_COMPLETED; } From 6c8ad975c7b6e82aa8fc3e6be9fce81811eb2ba8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 09:49:44 -0700 Subject: [PATCH 053/725] Like mutexes, operations on NULL rwlocks are no-ops Fixes a crash when performing operations on a NULL rwlock before rwlock implementation is chosen --- src/thread/windows/SDL_sysrwlock_srw.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/thread/windows/SDL_sysrwlock_srw.c b/src/thread/windows/SDL_sysrwlock_srw.c index 489ea5cfb9592..bec3cb07df9a6 100644 --- a/src/thread/windows/SDL_sysrwlock_srw.c +++ b/src/thread/windows/SDL_sysrwlock_srw.c @@ -229,30 +229,52 @@ SDL_RWLock *SDL_CreateRWLock(void) void SDL_DestroyRWLock(SDL_RWLock *rwlock) { - SDL_rwlock_impl_active.Destroy(rwlock); + if (rwlock) { + SDL_rwlock_impl_active.Destroy(rwlock); + } } int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { + if (rwlock == NULL) { + return 0; + } + return SDL_rwlock_impl_active.LockForReading(rwlock); } int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { + if (rwlock == NULL) { + return 0; + } + return SDL_rwlock_impl_active.LockForWriting(rwlock); } int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) { + if (rwlock == NULL) { + return 0; + } + return SDL_rwlock_impl_active.TryLockForReading(rwlock); } int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) { + if (rwlock == NULL) { + return 0; + } + return SDL_rwlock_impl_active.TryLockForWriting(rwlock); } int SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { + if (rwlock == NULL) { + return 0; + } + return SDL_rwlock_impl_active.Unlock(rwlock); } From 0b71898cb17696240e67e505aadd176a1959b11c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 10:18:12 -0700 Subject: [PATCH 054/725] Make it clear that the string comparison isn't a boolean check --- src/video/wayland/SDL_waylandvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index d6c0d0e37bb4e..09b8368081113 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -131,7 +131,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) /* Are we trying to connect to or are currently in a Wayland session? */ if (!SDL_getenv("WAYLAND_DISPLAY")) { const char *session = SDL_getenv("XDG_SESSION_TYPE"); - if (session && SDL_strcasecmp(session, "wayland")) { + if (session && SDL_strcasecmp(session, "wayland") != 0) { return NULL; } } From 10fab3a39e2bd163cc45147b6afd517501801002 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 14:31:37 -0400 Subject: [PATCH 055/725] pulseaudio: Stop the threaded mainloop before destroying the context. Otherwise, we might trigger an assertion in libpulse. Reference Issue #8348. --- src/audio/pulseaudio/SDL_pulseaudio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index a554fcd322d7e..1ab099baa0203 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -307,13 +307,15 @@ static void WaitForPulseOperation(pa_operation *o) static void DisconnectFromPulseServer(void) { + if (pulseaudio_threaded_mainloop != NULL) { + PULSEAUDIO_pa_threaded_mainloop_stop(pulseaudio_threaded_mainloop); + } if (pulseaudio_context) { PULSEAUDIO_pa_context_disconnect(pulseaudio_context); PULSEAUDIO_pa_context_unref(pulseaudio_context); pulseaudio_context = NULL; } if (pulseaudio_threaded_mainloop != NULL) { - PULSEAUDIO_pa_threaded_mainloop_stop(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_free(pulseaudio_threaded_mainloop); pulseaudio_threaded_mainloop = NULL; } From 1c3a0ade742af1f3626b43b9c865dbb41c2aa4a3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 15:11:20 -0400 Subject: [PATCH 056/725] audio: Whoops, this stream format change is only for capture devices. --- src/audio/SDL_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b6ac6517cc977..d974ea4cefd13 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1611,6 +1611,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL)); SDL_AudioDevice *device = logdev->physical_device; + const SDL_bool iscapture = device->iscapture; int retval = 0; // lock all the streams upfront, so we can verify they aren't bound elsewhere and add them all in one block, as this is intended to add everything or nothing. @@ -1648,7 +1649,9 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int } logdev->bound_streams = stream; - stream->src_spec.format = logdev->postmix ? SDL_AUDIO_F32 : device->spec.format; + if (iscapture) { + stream->src_spec.format = logdev->postmix ? SDL_AUDIO_F32 : device->spec.format; + } SDL_UnlockMutex(stream->lock); } From 0d5cad91b1007e53a98cdc2fcf767d783fc24490 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 15:10:09 -0700 Subject: [PATCH 057/725] We need audio converters initialized in SDL_InitAudio() These are used separately from audio streams, e.g. SDL_OutputAudioThreadIterate(), so they should always be initialized when audio is initialized. --- src/audio/SDL_audio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index d974ea4cefd13..112cb20e21871 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -602,6 +602,9 @@ int SDL_InitAudio(const char *driver_name) SDL_QuitAudio(); // shutdown driver if already running. } + SDL_ChooseAudioConverters(); + SDL_SetupAudioResampler(); + SDL_RWLock *device_list_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole audio subsystem. if (!device_list_lock) { return -1; From 1ae33f675118f32b6faab7645f140bab26d432d5 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 12 Oct 2023 00:49:43 +0200 Subject: [PATCH 058/725] cmake: optionally install pdb's --- .github/workflows/msvc.yml | 19 +++++++++++++------ CMakeLists.txt | 3 +++ test/CMakeLists.txt | 5 +++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 7d5d0f5dd1181..9195a94e6abb9 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -36,13 +36,20 @@ jobs: srcdir = r"${{ github.workspace }}".replace("\\", "/") builddir = f"{ srcdir }/build" os.makedirs(builddir) + cmakelists_txt = textwrap.dedent(f"""\ + # Always build .PDB symbol file + set(CMAKE_POLICY_DEFAULT_CMP0141 "NEW" CACHE STRING "MSVC debug information format flags are selected by an abstraction") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase" CACHE STRING "MSVC debug information format") + set(CMAKE_EXE_LINKER_FLAGS "-DEBUG" CACHE STRING "Linker flags for executables") + set(CMAKE_SHARED_LINKER_FLAGS "-DEBUG" CACHE STRING "Linker flag for shared libraries") + cmake_minimum_required(VERSION 3.0...3.25) + project(sdl_user) + enable_testing() + add_subdirectory("{ srcdir }" SDL) + """) + print(cmakelists_txt) with open(f"{ builddir }/CMakeLists.txt", "w") as f: - f.write(textwrap.dedent(f"""\ - cmake_minimum_required(VERSION 3.0...3.25) - project(sdl_user) - enable_testing() - add_subdirectory("{ srcdir }" SDL) - """)) + f.write(cmakelists_txt) - name: Configure (CMake) run: cmake -S build -B build ` -Wdeprecated -Wdev -Werror ` diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f03982f36387..a5188e5380a8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3264,6 +3264,9 @@ if(NOT SDL_DISABLE_INSTALL) FRAMEWORK DESTINATION "." RESOURCE DESTINATION "${SDL_SDL_INSTALL_RESOURCEDIR}" ) + if(MSVC) + install(FILES $ DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL) + endif() endif() if(SDL_STATIC) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fa4175a8df9e7..942400ff77ec2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -557,6 +557,11 @@ if(SDL_INSTALL_TESTS) DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3 ) endif() + if(MSVC) + foreach(test IN LISTS SDL_TEST_EXECUTABLES) + install(FILES $ DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3" OPTIONAL) + endforeach() + endif() install( FILES ${RESOURCE_FILES} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3 From 2bca4671a67a3445566d50c47febf1e7bb80df8e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Oct 2023 22:42:52 -0400 Subject: [PATCH 059/725] audio: Allow audio streams to be created when the subsystem isn't initialized. You are on your own to destroy them, though! --- src/audio/SDL_audio.c | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 112cb20e21871..0608de5de3171 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -139,40 +139,47 @@ static int GetDefaultSampleFramesFromFreq(const int freq) void OnAudioStreamCreated(SDL_AudioStream *stream) { - SDL_assert(SDL_GetCurrentAudioDriver() != NULL); SDL_assert(stream != NULL); - // this isn't really part of the "device list" but it's a convenient lock to use here. - SDL_LockRWLockForWriting(current_audio.device_list_lock); - if (current_audio.existing_streams) { - current_audio.existing_streams->prev = stream; + // NOTE that you can create an audio stream without initializing the audio subsystem, + // but it will not be automatically destroyed during a later call to SDL_Quit! + // You must explicitly destroy it yourself! + if (current_audio.device_list_lock) { + // this isn't really part of the "device list" but it's a convenient lock to use here. + SDL_LockRWLockForWriting(current_audio.device_list_lock); + if (current_audio.existing_streams) { + current_audio.existing_streams->prev = stream; + } + stream->prev = NULL; + stream->next = current_audio.existing_streams; + current_audio.existing_streams = stream; + SDL_UnlockRWLock(current_audio.device_list_lock); } - stream->prev = NULL; - stream->next = current_audio.existing_streams; - current_audio.existing_streams = stream; - SDL_UnlockRWLock(current_audio.device_list_lock); } void OnAudioStreamDestroy(SDL_AudioStream *stream) { - SDL_assert(SDL_GetCurrentAudioDriver() != NULL); SDL_assert(stream != NULL); - // this isn't really part of the "device list" but it's a convenient lock to use here. - SDL_LockRWLockForWriting(current_audio.device_list_lock); - if (stream->prev) { - stream->prev->next = stream->next; - } - if (stream->next) { - stream->next->prev = stream->prev; - } - if (stream == current_audio.existing_streams) { - current_audio.existing_streams = stream->next; + // NOTE that you can create an audio stream without initializing the audio subsystem, + // but it will not be automatically destroyed during a later call to SDL_Quit! + // You must explicitly destroy it yourself! + if (current_audio.device_list_lock) { + // this isn't really part of the "device list" but it's a convenient lock to use here. + SDL_LockRWLockForWriting(current_audio.device_list_lock); + if (stream->prev) { + stream->prev->next = stream->next; + } + if (stream->next) { + stream->next->prev = stream->prev; + } + if (stream == current_audio.existing_streams) { + current_audio.existing_streams = stream->next; + } + SDL_UnlockRWLock(current_audio.device_list_lock); } - SDL_UnlockRWLock(current_audio.device_list_lock); } - // device should be locked when calling this. static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) { From 973c8b3273820f9421d85292911809f319d19964 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 12:38:22 -0700 Subject: [PATCH 060/725] Added SDL properties API Fixes https://github.com/libsdl-org/SDL/issues/7799 --- VisualC-GDK/SDL/SDL.vcxproj | 6 +- VisualC-GDK/SDL/SDL.vcxproj.filters | 5 + VisualC-WinRT/SDL-UWP.vcxproj | 3 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 26 +- VisualC/SDL/SDL.vcxproj | 9 +- VisualC/SDL/SDL.vcxproj.filters | 5 + .../testautomation/testautomation.vcxproj | 1 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 29 +- include/SDL3/SDL.h | 1 + include/SDL3/SDL_properties.h | 133 +++++++++ src/SDL.c | 3 + src/SDL_hashtable.c | 40 ++- src/SDL_hashtable.h | 11 +- src/SDL_properties.c | 278 ++++++++++++++++++ src/SDL_properties_c.h | 23 ++ src/dynapi/SDL_dynapi.sym | 6 + src/dynapi/SDL_dynapi_overrides.h | 6 + src/dynapi/SDL_dynapi_procs.h | 6 + test/testautomation.c | 1 + test/testautomation_properties.c | 190 ++++++++++++ test/testautomation_suites.h | 1 + 21 files changed, 746 insertions(+), 37 deletions(-) create mode 100644 include/SDL3/SDL_properties.h create mode 100644 src/SDL_properties.c create mode 100644 src/SDL_properties_c.h create mode 100644 test/testautomation_properties.c diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index d222f42cd6a39..7df28485fcaa0 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -473,6 +473,7 @@ + @@ -541,9 +542,6 @@ - - - @@ -714,8 +712,10 @@ + + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 683d6b4f3e765..19b7eb904b86c 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -306,6 +306,9 @@ API Headers + + API Headers + API Headers @@ -823,6 +826,7 @@ + render\direct3d12 @@ -849,6 +853,7 @@ + audio diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 863b0e3e397a3..c911765b9941b 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -71,6 +71,7 @@ + @@ -156,6 +157,7 @@ + @@ -398,6 +400,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index a1c99a51e712d..7b90f411fbee0 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -324,7 +324,9 @@ Source Files - + + Source Files + Source Files @@ -334,6 +336,9 @@ Source Files + + Source Files + Source Files @@ -640,13 +645,24 @@ Source Files - + + Source Files + Source Files + + Source Files + Source Files + + Source Files + + + Source Files + Source Files @@ -797,12 +813,6 @@ Source Files - - Source Files - - - Source Files - Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 31263605cea0b..f4d4dc002cb07 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -283,6 +283,7 @@ + @@ -400,6 +401,7 @@ + @@ -467,9 +469,6 @@ - - - @@ -590,10 +589,12 @@ - + + + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index df44db6b2de10..f72de3a0a0cfb 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -300,6 +300,9 @@ API Headers + + API Headers + API Headers @@ -814,6 +817,7 @@ + render\direct3d12 @@ -828,6 +832,7 @@ + audio diff --git a/VisualC/tests/testautomation/testautomation.vcxproj b/VisualC/tests/testautomation/testautomation.vcxproj index 2cae2109f3a7b..fd1f86c9b3f4f 100644 --- a/VisualC/tests/testautomation/testautomation.vcxproj +++ b/VisualC/tests/testautomation/testautomation.vcxproj @@ -211,6 +211,7 @@ + diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 2ed36dcb0408d..cc082179e3f58 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; 007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; platformFilters = (macos, ); }; 007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; platformFilters = (ios, maccatalyst, macos, ); }; 00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; platformFilters = (macos, ); }; @@ -405,6 +406,8 @@ F3B38CDB296E2E52005DA6D3 /* SDL_oldnames.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CDF296E2E52005DA6D3 /* SDL_intrin.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; }; + F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */; }; + F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F07D59269640160074468B /* SDL_hidapi_luna.c */; }; F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8AA2933074900816151 /* SDL_audio.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D8F12933074E00816151 /* SDL_platform.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8AB2933074900816151 /* SDL_platform.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -469,8 +472,6 @@ F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E72933074E00816151 /* SDL_begin_code.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E52933074E00816151 /* SDL_system.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E82933074E00816151 /* SDL_system.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; - 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; - 0000CE8F0EF0E7EF781D0000 /* SDL_hashtable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -497,6 +498,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hashtable.c; sourceTree = ""; }; + 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hashtable.h; sourceTree = ""; }; 0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; @@ -897,6 +900,8 @@ F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_oldnames.h; path = SDL3/SDL_oldnames.h; sourceTree = ""; }; F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_intrin.h; path = SDL3/SDL_intrin.h; sourceTree = ""; }; F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = ""; }; + F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_properties.c; sourceTree = ""; }; + F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_properties.h; path = SDL3/SDL_properties.h; sourceTree = ""; }; F3F07D59269640160074468B /* SDL_hidapi_luna.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_luna.c; sourceTree = ""; }; F3F7D8AA2933074900816151 /* SDL_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_audio.h; path = SDL3/SDL_audio.h; sourceTree = ""; }; F3F7D8AB2933074900816151 /* SDL_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_platform.h; path = SDL3/SDL_platform.h; sourceTree = ""; }; @@ -964,8 +969,6 @@ F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; }; F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; }; FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; - 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_hashtable.c; path = SDL_hashtable.c; sourceTree = ""; }; - 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_hashtable.h; path = SDL_hashtable.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -994,7 +997,6 @@ 0153844A006D81B07F000001 /* Public Headers */ = { isa = PBXGroup; children = ( - F3F7D8CF2933074C00816151 /* SDL.h */, F3F7D8E02933074D00816151 /* SDL_assert.h */, F3F7D8B92933074A00816151 /* SDL_atomic.h */, F3F7D8AA2933074900816151 /* SDL_audio.h */, @@ -1023,26 +1025,27 @@ F3F7D8D92933074C00816151 /* SDL_loadso.h */, F3F7D8C42933074B00816151 /* SDL_locale.h */, F3F7D8B72933074A00816151 /* SDL_log.h */, - F3F7D8B02933074900816151 /* SDL_main.h */, F3B38CCA296E2E52005DA6D3 /* SDL_main_impl.h */, + F3F7D8B02933074900816151 /* SDL_main.h */, F3F7D8B62933074A00816151 /* SDL_messagebox.h */, F3F7D8D22933074C00816151 /* SDL_metal.h */, F3F7D8D52933074C00816151 /* SDL_misc.h */, F3F7D8DA2933074D00816151 /* SDL_mouse.h */, F3F7D8E62933074E00816151 /* SDL_mutex.h */, F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */, - F3F7D8E12933074D00816151 /* SDL_opengl.h */, F3F7D8C02933074A00816151 /* SDL_opengl_glext.h */, + F3F7D8E12933074D00816151 /* SDL_opengl.h */, F3F7D8C62933074B00816151 /* SDL_opengles.h */, - F3F7D8C72933074B00816151 /* SDL_opengles2.h */, F3F7D8AE2933074900816151 /* SDL_opengles2_gl2.h */, F3F7D8BD2933074A00816151 /* SDL_opengles2_gl2ext.h */, F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */, F3F7D8B12933074900816151 /* SDL_opengles2_khrplatform.h */, + F3F7D8C72933074B00816151 /* SDL_opengles2.h */, F3F7D8B52933074A00816151 /* SDL_pixels.h */, - F3F7D8AB2933074900816151 /* SDL_platform.h */, F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */, + F3F7D8AB2933074900816151 /* SDL_platform.h */, F3F7D8DB2933074D00816151 /* SDL_power.h */, + F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */, F3F7D8DF2933074D00816151 /* SDL_quit.h */, F3F7D8E22933074D00816151 /* SDL_rect.h */, F3F7D8DE2933074D00816151 /* SDL_render.h */, @@ -1061,6 +1064,7 @@ F3F7D8E42933074D00816151 /* SDL_version.h */, F3F7D8C52933074B00816151 /* SDL_video.h */, F3F7D8D42933074C00816151 /* SDL_vulkan.h */, + F3F7D8CF2933074C00816151 /* SDL.h */, ); name = "Public Headers"; path = ../../include; @@ -1123,6 +1127,8 @@ A7D8A57523E2513D00DCD162 /* SDL_error_c.h */, A7D8A8BF23E2513F00DCD162 /* SDL_error.c */, F382071C284F362F004DD584 /* SDL_guid.c */, + 000078E1881E857EBB6C0000 /* SDL_hashtable.c */, + 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */, A7D8A8D123E2514000DCD162 /* SDL_hints_c.h */, A7D8A5AB23E2513D00DCD162 /* SDL_hints.c */, A7D8A58323E2513D00DCD162 /* SDL_internal.h */, @@ -1130,11 +1136,10 @@ A1BB8B6227F6CF330057CFA8 /* SDL_list.h */, F386F6E42884663E001840AA /* SDL_log_c.h */, A7D8A5DD23E2513D00DCD162 /* SDL_log.c */, + F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */, F386F6E52884663E001840AA /* SDL_utils_c.h */, F386F6E62884663E001840AA /* SDL_utils.c */, A7D8A57123E2513D00DCD162 /* SDL.c */, - 000078E1881E857EBB6C0000 /* SDL_hashtable.c */, - 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */, ); name = "Library Source"; path = ../../src; @@ -2156,6 +2161,7 @@ F3B38CDB296E2E52005DA6D3 /* SDL_oldnames.h in Headers */, F3F7D9C92933074E00816151 /* SDL_opengl.h in Headers */, F3F7D9452933074E00816151 /* SDL_opengl_glext.h in Headers */, + F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */, F3F7D95D2933074E00816151 /* SDL_opengles.h in Headers */, F3F7D9612933074E00816151 /* SDL_opengles2.h in Headers */, F3F7D8FD2933074E00816151 /* SDL_opengles2_gl2.h in Headers */, @@ -2502,6 +2508,7 @@ A7D8BBD723E2574800DCD162 /* SDL_uikitevents.m in Sources */, A7D8B5F323E2514300DCD162 /* SDL_syspower.c in Sources */, A7D8B95023E2514400DCD162 /* SDL_iconv.c in Sources */, + F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */, A7D8BA9D23E2514400DCD162 /* s_fabs.c in Sources */, F395C1B12569C6A000942BFF /* SDL_mfijoystick.m in Sources */, A7D8B99223E2514400DCD162 /* SDL_shaders_metal.metal in Sources */, diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index cb51cd7ac2f8a..498f0520c15c2 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h new file mode 100644 index 0000000000000..13a881c0b8aea --- /dev/null +++ b/include/SDL3/SDL_properties.h @@ -0,0 +1,133 @@ +/* + Simple DiretMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_properties.h + * + * \brief Header file for SDL properties. + */ + +#ifndef SDL_properties_h_ +#define SDL_properties_h_ + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * SDL properties ID + */ +typedef Uint32 SDL_PropertiesID; + +/** + * Create a set of properties + * + * \returns an ID for a new set of properties, or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_DestroyProperties + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); + +/** + * Lock a set of properties + * + * Obtain a multi-threaded lock for these properties. Other threads will wait while trying to lock these properties until they are unlocked. Properties must be unlocked before they are destroyed. + * + * The lock is automatically taken when setting individual properties, this function is only needed when you want to set several properties atomically or want to guarantee that properties being queried aren't freed in another thread. + * + * \param props the properties to lock + * + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_UnlockProperties + */ +extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props); + +/** + * Unlock a set of properties + * + * \param props the properties to unlock + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_LockProperties + */ +extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); + +/** + * Set a property on a set of properties + * + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property, or NULL to delete the property + * \param cleanup the function to call when this property is deleted, or NULL if no cleanup is necessary + * \param userdata a pointer that is passed to the cleanup function + * + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + */ +extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); + +/** + * Get a property on a set of properties + * + * \param props the properties to query + * \param name the name of the property to query + * + * \returns the value of the property, or NULL if it is not set. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetProperty + */ +extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name); + +/** + * Destroy a set of properties + * + * All properties are deleted and their cleanup functions will be called, if any. The set of properties must be unlocked when it is destroyed. + * + * \param props the properties to destroy + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProperties + */ +extern DECLSPEC void SDLCALL SDL_DestroyProperties(SDL_PropertiesID props); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_properties_h_ */ diff --git a/src/SDL.c b/src/SDL.c index f099b04826e8a..31bd02ea41998 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -38,6 +38,7 @@ #include "SDL_assert_c.h" #include "SDL_log_c.h" +#include "SDL_properties_c.h" #include "audio/SDL_audio_c.h" #include "video/SDL_video_c.h" #include "events/SDL_events_c.h" @@ -167,6 +168,7 @@ int SDL_InitSubSystem(Uint32 flags) } SDL_InitLog(); + SDL_InitProperties(); /* Clear the error message */ SDL_ClearError(); @@ -499,6 +501,7 @@ void SDL_Quit(void) SDL_DBus_Quit(); #endif + SDL_QuitProperties(); SDL_QuitLog(); /* Now that every subsystem has been quit, we reset the subsystem refcount diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index e4b301c54776b..a5fc0f09e67b8 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -18,7 +18,6 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ - #include "SDL_internal.h" #include "SDL_hashtable.h" @@ -209,6 +208,21 @@ SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, return SDL_TRUE; } +SDL_bool SDL_HashTableEmpty(SDL_HashTable *table) +{ + if (table != NULL) { + Uint32 i; + + for (i = 0; i < table->table_len; i++) { + SDL_HashItem *item = table->table[i]; + if (item != NULL) { + return SDL_FALSE; + } + } + } + return SDL_TRUE; +} + void SDL_DestroyHashTable(SDL_HashTable *table) { if (table != NULL) { @@ -240,10 +254,10 @@ static SDL_INLINE Uint32 hash_string_djbxor(const char *str, size_t len) return hash; } -Uint32 SDL_HashString(const void *sym, void *data) +Uint32 SDL_HashString(const void *key, void *data) { - const char *str = (const char*) sym; - return hash_string_djbxor(str, SDL_strlen((const char *) str)); + const char *str = (const char *)key; + return hash_string_djbxor(str, SDL_strlen(str)); } SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) @@ -253,7 +267,21 @@ SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) } else if (!a || !b) { return SDL_FALSE; /* one pointer is NULL (and first test shows they aren't the same pointer), must not match. */ } - return (SDL_strcmp((const char *) a, (const char *) b) == 0) ? SDL_TRUE : SDL_FALSE; /* Check against actual string contents. */ + return (SDL_strcmp((const char *)a, (const char *)b) == 0) ? SDL_TRUE : SDL_FALSE; /* Check against actual string contents. */ +} + +/* We assume we can fit the ID in the key directly */ +SDL_COMPILE_TIME_ASSERT(SDL_HashID_KeySize, sizeof(Uint32) <= sizeof(const void *)); + +Uint32 SDL_HashID(const void *key, void *unused) +{ + return (Uint32)(uintptr_t)key; } -/* vi: set ts=4 sw=4 expandtab: */ +SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused) +{ + if (a == b) { + return SDL_TRUE; + } + return SDL_FALSE; +} diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h index cb03b0c1fd78a..eb8d7ba3ca39a 100644 --- a/src/SDL_hashtable.h +++ b/src/SDL_hashtable.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2022 Sam Lantinga + Copyright (C) 1997-2023 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -40,14 +40,15 @@ void SDL_DestroyHashTable(SDL_HashTable *table); SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value); SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); +SDL_bool SDL_HashTableEmpty(SDL_HashTable *table); SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const void **_value, void **iter); SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, void **iter); -Uint32 SDL_HashString(const void *sym, void *unused); +Uint32 SDL_HashString(const void *key, void *unused); SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *unused); -#endif /* SDL_hashtable_h_ */ - -/* vi: set ts=4 sw=4 expandtab: */ +Uint32 SDL_HashID(const void *key, void *unused); +SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused); +#endif /* SDL_hashtable_h_ */ diff --git a/src/SDL_properties.c b/src/SDL_properties.c new file mode 100644 index 0000000000000..a83067501dc42 --- /dev/null +++ b/src/SDL_properties.c @@ -0,0 +1,278 @@ +/* + Simple DiretMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" +#include "SDL_hashtable.h" +#include "SDL_properties_c.h" + + +typedef struct +{ + void *value; + void (SDLCALL *cleanup)(void *userdata, void *value); + void *userdata; +} SDL_Property; + +typedef struct +{ + SDL_HashTable *props; + SDL_Mutex *lock; +} SDL_Properties; + +static SDL_HashTable *SDL_properties; +static SDL_RWLock *SDL_properties_lock; +static SDL_PropertiesID SDL_last_properties_id; + + +static void SDL_FreeProperty(const void *key, const void *value, void *data) +{ + SDL_Property *property = (SDL_Property *)value; + if (property->cleanup) { + property->cleanup(property->userdata, property->value); + } + SDL_free((void *)key); + SDL_free((void *)value); +} + +static void SDL_FreeProperties(const void *key, const void *value, void *data) +{ + SDL_Properties *properties = (SDL_Properties *)value; + if (properties) { + if (properties->props) { + SDL_DestroyHashTable(properties->props); + properties->props = NULL; + } + if (properties->lock) { + SDL_DestroyMutex(properties->lock); + properties->lock = NULL; + } + SDL_free(properties); + } +} + +int SDL_InitProperties(void) +{ + if (!SDL_properties_lock) { + SDL_properties_lock = SDL_CreateRWLock(); + if (!SDL_properties_lock) { + return -1; + } + } + if (!SDL_properties) { + SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, SDL_FALSE); + if (!SDL_properties) { + return -1; + } + } + return 0; +} + +void SDL_QuitProperties(void) +{ + if (SDL_properties) { + SDL_DestroyHashTable(SDL_properties); + SDL_properties = NULL; + } + if (SDL_properties_lock) { + SDL_DestroyRWLock(SDL_properties_lock); + SDL_properties_lock = NULL; + } +} + +SDL_PropertiesID SDL_CreateProperties(void) +{ + SDL_PropertiesID props; + SDL_Properties *properties = NULL; + SDL_bool inserted = SDL_FALSE; + + if (!SDL_properties && SDL_InitProperties() < 0) { + return 0; + } + + properties = SDL_malloc(sizeof(*properties)); + if (!properties) { + goto error; + } + properties->props = SDL_CreateHashTable(NULL, 4, SDL_HashString, SDL_KeyMatchString, SDL_FreeProperty, SDL_FALSE); + if (!properties->props) { + goto error; + } + properties->lock = SDL_CreateMutex(); + if (!properties->lock) { + goto error; + } + + if (SDL_InitProperties() < 0) { + goto error; + } + + if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) { + props = ++SDL_last_properties_id; + if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { + inserted = SDL_TRUE; + } + SDL_UnlockRWLock(SDL_properties_lock); + } + + if (inserted) { + /* All done! */ + return props; + } + +error: + SDL_FreeProperties(NULL, properties, NULL); + return 0; +} + +int SDL_LockProperties(SDL_PropertiesID props) +{ + SDL_Properties *properties = NULL; + + if (!props) { + return SDL_InvalidParamError("props"); + } + if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + } + if (!properties) { + SDL_InvalidParamError("props"); + return -1; + } + return SDL_LockMutex(properties->lock); +} + +void SDL_UnlockProperties(SDL_PropertiesID props) +{ + SDL_Properties *properties = NULL; + + if (!props) { + return; + } + if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + } + if (!properties) { + return; + } + SDL_UnlockMutex(properties->lock); +} + +int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) +{ + SDL_Properties *properties = NULL; + SDL_Property *property = NULL; + int result = 0; + + if (!props) { + return SDL_InvalidParamError("props"); + } + if (!name || !*name) { + return SDL_InvalidParamError("name"); + } + + if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + } + if (!properties) { + return SDL_InvalidParamError("props"); + } + + if (value) { + property = (SDL_Property *)SDL_malloc(sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + + property->value = value; + property->cleanup = cleanup; + property->userdata = userdata; + } + + SDL_LockMutex(properties->lock); + { + SDL_RemoveFromHashTable(properties->props, name); + if (property) { + char *key = SDL_strdup(name); + if (!SDL_InsertIntoHashTable(properties->props, key, property)) { + SDL_FreeProperty(key, property, NULL); + result = -1; + } + } + } + SDL_UnlockMutex(properties->lock); + + return result; +} + +void *SDL_GetProperty(SDL_PropertiesID props, const char *name) +{ + SDL_Properties *properties = NULL; + void *value = NULL; + + if (!props) { + SDL_InvalidParamError("props"); + return NULL; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return NULL; + } + + if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + } + if (!properties) { + SDL_InvalidParamError("props"); + return NULL; + } + + /* Note that taking the lock here only guarantees that we won't read the + * hashtable while it's being modified. The value itself can easily be + * freed from another thread after it is returned here. + */ + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + value = property->value; + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return value; +} + +void SDL_DestroyProperties(SDL_PropertiesID props) +{ + if (!props) { + return; + } + + if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) { + SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props); + SDL_UnlockRWLock(SDL_properties_lock); + } +} diff --git a/src/SDL_properties_c.h b/src/SDL_properties_c.h new file mode 100644 index 0000000000000..10b4df4aed186 --- /dev/null +++ b/src/SDL_properties_c.h @@ -0,0 +1,23 @@ +/* + Simple DiretMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +extern int SDL_InitProperties(void); +extern void SDL_QuitProperties(void); diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 89bf3aff6e5fe..c73472068380b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -908,6 +908,12 @@ SDL3_0.0.0 { SDL_SetAudioPostmixCallback; SDL_GetAudioStreamQueued; SDL_GetTextureDXGIResource; + SDL_CreateProperties; + SDL_LockProperties; + SDL_UnlockProperties; + SDL_SetProperty; + SDL_GetProperty; + SDL_DestroyProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index e7b16789b90da..8148554c54df8 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -933,3 +933,9 @@ #define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL #define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL #define SDL_GetTextureDXGIResource SDL_GetTextureDXGIResource_REAL +#define SDL_CreateProperties SDL_CreateProperties_REAL +#define SDL_LockProperties SDL_LockProperties_REAL +#define SDL_UnlockProperties SDL_UnlockProperties_REAL +#define SDL_SetProperty SDL_SetProperty_REAL +#define SDL_GetProperty SDL_GetProperty_REAL +#define SDL_DestroyProperties SDL_DestroyProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6bb5f63da287f..985b13eb5d6db 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -979,3 +979,9 @@ SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) +SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) +SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) diff --git a/test/testautomation.c b/test/testautomation.c index 2e483daf92f6f..8e5f002fe5c37 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -35,6 +35,7 @@ static SDLTest_TestSuiteReference *testSuites[] = { &mouseTestSuite, &pixelsTestSuite, &platformTestSuite, + &propertiesTestSuite, &rectTestSuite, &renderTestSuite, &rwopsTestSuite, diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c new file mode 100644 index 0000000000000..a02edff674b3e --- /dev/null +++ b/test/testautomation_properties.c @@ -0,0 +1,190 @@ +/** + * Properties test suite + */ + +#include +#include +#include "testautomation_suites.h" + +/* Test case functions */ + +/** + * \brief Test basic functionality + */ +static int properties_testBasic(void *arg) +{ + SDL_PropertiesID props; + char key[2], expected_value[2]; + void *value; + int i, result; + + props = SDL_CreateProperties(); + SDLTest_AssertPass("Call to SDL_CreateProperties()"); + SDLTest_AssertCheck(props != 0, + "Verify props were created, got: %" SDL_PRIu32 "", props); + + for (i = 0; i < 10; ++i) { + SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); + SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); + result = SDL_SetProperty(props, key, expected_value, NULL, NULL); + SDLTest_AssertPass("Call to SDL_SetProperty()"); + SDLTest_AssertCheck(result == 0, + "Verify property value was set, got: %d", result); + value = SDL_GetProperty(props, key); + SDLTest_AssertPass("Call to SDL_GetProperty()"); + SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, expected_value) == 0, + "Verify property value was set, got %s, expected %s", value ? (const char *)value : "NULL", expected_value); + } + + for (i = 0; i < 10; ++i) { + SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); + result = SDL_SetProperty(props, key, NULL, NULL, NULL); + SDLTest_AssertPass("Call to SDL_SetProperty(NULL)"); + SDLTest_AssertCheck(result == 0, + "Verify property value was set, got: %d", result); + value = SDL_GetProperty(props, key); + SDLTest_AssertPass("Call to SDL_GetProperty()"); + SDLTest_AssertCheck(value == NULL, + "Verify property value was set, got %s, expected NULL", (const char *)value); + } + + SDL_DestroyProperties(props); + + return TEST_COMPLETED; +} + +/** + * \brief Test cleanup functionality + */ +static void SDLCALL cleanup(void *userdata, void *value) +{ + int *count = (int *)userdata; + ++(*count); +} +static int properties_testCleanup(void *arg) +{ + SDL_PropertiesID props; + char key[2], expected_value[2]; + int i, count; + + props = SDL_CreateProperties(); + + SDLTest_AssertPass("Call to SDL_SetProperty(cleanup)"); + count = 0; + SDL_SetProperty(props, "a", "0", cleanup, &count); + SDL_SetProperty(props, "a", NULL, cleanup, &count); + SDLTest_AssertCheck(count == 1, + "Verify cleanup for deleting property, got %d, expected 1", count); + + SDLTest_AssertPass("Call to SDL_DestroyProperties()"); + count = 0; + for (i = 0; i < 10; ++i) { + SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); + SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); + SDL_SetProperty(props, key, expected_value, cleanup, &count); + } + SDL_DestroyProperties(props); + SDLTest_AssertCheck(count == 10, + "Verify cleanup for destroying properties, got %d, expected 10", count); + + return TEST_COMPLETED; +} + +/** + * \brief Test locking functionality + */ +struct properties_thread_data +{ + SDL_bool done; + SDL_PropertiesID props; +}; +static int properties_thread(void *arg) +{ + struct properties_thread_data *data = (struct properties_thread_data *)arg; + + while (!data->done) { + SDL_LockProperties(data->props); + SDL_SetProperty(data->props, "a", "thread_loop", NULL, NULL); + SDL_UnlockProperties(data->props); + } + SDL_LockProperties(data->props); + SDL_SetProperty(data->props, "a", "thread_done", NULL, NULL); + SDL_UnlockProperties(data->props); + return 0; +} +static int properties_testLocking(void *arg) +{ + struct properties_thread_data data; + SDL_Thread *thread; + void *value; + + SDLTest_AssertPass("Testing property locking"); + data.done = SDL_FALSE; + data.props = SDL_CreateProperties(); + SDLTest_AssertPass("Setting property to 'init'"); + SDL_SetProperty(data.props, "a", "init", NULL, NULL); + thread = SDL_CreateThread(properties_thread, "properties_thread", &data); + if (thread) { + SDLTest_AssertPass("Waiting for property to change to 'thread_loop'"); + for ( ; ; ) + { + SDL_Delay(10); + SDL_LockProperties(data.props); + value = SDL_GetProperty(data.props, "a"); + SDL_UnlockProperties(data.props); + + if (!value || SDL_strcmp((const char *)value, "thread_loop") == 0) { + break; + } + } + SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_loop") == 0, + "After thread loop, property is %s, expected 'thread_loop'", value ? (const char *)value : "NULL"); + + SDLTest_AssertPass("Setting property to 'main'"); + SDL_LockProperties(data.props); + SDL_SetProperty(data.props, "a", "main", NULL, NULL); + SDL_Delay(100); + value = SDL_GetProperty(data.props, "a"); + SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "main") == 0, + "After 100ms sleep, property is %s, expected 'main'", value ? (const char *)value : "NULL"); + SDL_UnlockProperties(data.props); + + data.done = SDL_TRUE; + SDL_WaitThread(thread, NULL); + + value = SDL_GetProperty(data.props, "a"); + SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_done") == 0, + "After thread complete, property is %s, expected 'thread_done'", value ? (const char *)value : "NULL"); + } + SDL_DestroyProperties(data.props); + + return TEST_COMPLETED; +} + +/* ================= Test References ================== */ + +/* Properties test cases */ +static const SDLTest_TestCaseReference propertiesTest1 = { + (SDLTest_TestCaseFp)properties_testBasic, "properties_testBasic", "Test basic property functionality", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference propertiesTest2 = { + (SDLTest_TestCaseFp)properties_testCleanup, "properties_testCleanup", "Test property cleanup functionality", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference propertiesTest3 = { + (SDLTest_TestCaseFp)properties_testLocking, "properties_testLocking", "Test property locking functionality", TEST_ENABLED +}; + +/* Sequence of Properties test cases */ +static const SDLTest_TestCaseReference *propertiesTests[] = { + &propertiesTest1, &propertiesTest2, &propertiesTest3, NULL +}; + +/* Properties test suite (global) */ +SDLTest_TestSuiteReference propertiesTestSuite = { + "Properties", + NULL, + propertiesTests, + NULL +}; diff --git a/test/testautomation_suites.h b/test/testautomation_suites.h index 3fa83ea5d9e72..e1a29e0b70e20 100644 --- a/test/testautomation_suites.h +++ b/test/testautomation_suites.h @@ -22,6 +22,7 @@ extern SDLTest_TestSuiteReference mathTestSuite; extern SDLTest_TestSuiteReference mouseTestSuite; extern SDLTest_TestSuiteReference pixelsTestSuite; extern SDLTest_TestSuiteReference platformTestSuite; +extern SDLTest_TestSuiteReference propertiesTestSuite; extern SDLTest_TestSuiteReference rectTestSuite; extern SDLTest_TestSuiteReference renderTestSuite; extern SDLTest_TestSuiteReference rwopsTestSuite; From 4368f70ff9447f5960e1afa7a2bb878414c50bc1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 16:59:51 -0700 Subject: [PATCH 061/725] Added properties to various SDL objects The following objects now have properties that can be user modified: * SDL_AudioStream * SDL_Gamepad * SDL_Joystick * SDL_RWops * SDL_Renderer * SDL_Sensor * SDL_Surface * SDL_Texture * SDL_Window --- build-scripts/SDL_migration.cocci | 10 ++ docs/README-migration.md | 6 + include/SDL3/SDL_audio.h | 17 ++- include/SDL3/SDL_gamepad.h | 19 ++- include/SDL3/SDL_joystick.h | 14 ++ include/SDL3/SDL_properties.h | 15 +++ include/SDL3/SDL_render.h | 54 ++++---- include/SDL3/SDL_rwops.h | 15 +++ include/SDL3/SDL_sensor.h | 14 ++ include/SDL3/SDL_surface.h | 18 ++- include/SDL3/SDL_video.h | 45 ++----- src/SDL_properties.c | 5 + src/audio/SDL_audiocvt.c | 14 ++ src/audio/SDL_sysaudio.h | 2 + src/dynapi/SDL_dynapi.sym | 14 +- src/dynapi/SDL_dynapi_overrides.h | 14 +- src/dynapi/SDL_dynapi_procs.h | 14 +- src/file/SDL_rwops.c | 14 ++ src/joystick/SDL_gamepad.c | 15 +++ src/joystick/SDL_joystick.c | 23 ++++ src/joystick/SDL_sysjoystick.h | 2 + src/render/SDL_render.c | 47 ++++--- src/render/SDL_sysrender.h | 5 +- src/sensor/SDL_sensor.c | 23 ++++ src/sensor/SDL_syssensor.h | 2 + src/video/SDL_surface.c | 28 ++-- src/video/SDL_sysvideo.h | 9 +- src/video/SDL_video.c | 121 +++++------------- src/video/dummy/SDL_nullframebuffer.c | 21 +-- src/video/n3ds/SDL_n3dsframebuffer.c | 35 ++--- .../offscreen/SDL_offscreenframebuffer.c | 21 +-- test/testautomation_video.c | 68 +++------- 32 files changed, 433 insertions(+), 291 deletions(-) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index df9acc0070e63..8a6012e28086a 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -2735,3 +2735,13 @@ typedef SDL_cond, SDL_Condition; - SDL_WriteBE64 + SDL_WriteU64BE (...) +@@ +expression e, n; +@@ +- SDL_GetWindowData(e, n) ++ SDL_GetProperty(SDL_GetWindowProperties(e), n) +@@ +expression e, n, v; +@@ +- SDL_SetWindowData(e, n, v) ++ SDL_SetProperty(SDL_GetWindowProperties(e), n, v, NULL, NULL) diff --git a/docs/README-migration.md b/docs/README-migration.md index 7878b1f4d07ac..db1b8db00669f 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -854,9 +854,11 @@ The following functions have been renamed: * SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow() The following functions have been removed: +* SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead * SDL_RenderGetIntegerScale() * SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE * SDL_RenderTargetSupported() - render targets are always supported +* SDL_SetTextureUserData() - use SDL_GetTextureProperties() instead The following symbols have been renamed: * SDL_ScaleModeBest => SDL_SCALEMODE_BEST @@ -1068,6 +1070,8 @@ The following functions have been renamed: ## SDL_surface.h +The userdata member of SDL_Surface has been replaced with a more general properties interface, which can be queried with SDL_GetSurfaceProperties() + Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat. SDL_CreateRGBSurface() and SDL_CreateRGBSurfaceWithFormat() have been combined into a new function SDL_CreateSurface(). @@ -1274,6 +1278,8 @@ The following functions have been removed: * SDL_GetDisplayMode() * SDL_GetNumDisplayModes() - replaced with SDL_GetFullscreenDisplayModes() * SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() +* SDL_GetWindowData() - use SDL_GetWindowProperties() instead +* SDL_SetWindowData() - use SDL_GetWindowProperties() instead SDL_Window id type is named SDL_WindowID diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 9b8737919e542..481bfc599a385 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -29,11 +29,12 @@ #define SDL_audio_h_ #include -#include #include +#include #include -#include +#include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -675,6 +676,18 @@ extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetAudioStreamDevice(SDL_AudioStre */ extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec); +/** + * Get the properties associated with an audio stream. + * + * \param stream the SDL_AudioStream to query + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_AudioStream *stream); /** * Query the current format of an audio stream. diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index b9c31e8d4d3dd..bb950272f37ba 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -30,9 +30,10 @@ #include #include +#include +#include #include #include -#include #include /* Set up for C function definitions, even when using C++ */ @@ -554,6 +555,22 @@ extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromInstanceID(SDL_JoystickID */ extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromPlayerIndex(int player_index); +/** + * Get the properties associated with an opened gamepad. + * + * These properties are shared with the underlying joystick object. + * + * \param gamepad a gamepad identifier previously returned by + * SDL_OpenGamepad() + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGamepadProperties(SDL_Gamepad *gamepad); + /** * Get the instance ID of an opened gamepad. * diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index c7985a92b2c5a..e3c9a9f8cf94d 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -42,6 +42,7 @@ #include #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -456,6 +457,19 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, */ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value); +/** + * Get the properties associated with a joystick. + * + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick *joystick); + /** * Get the implementation dependent name of a joystick. * diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 13a881c0b8aea..efa700ee9e98f 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -111,6 +111,21 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * */ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name); +/** + * Clear a property on a set of properties + * + * \param props the properties to modify + * \param name the name of the property to clear + * + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + */ +extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); + /** * Destroy a set of properties * diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index e4a2430620069..ae08703697cf0 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -50,6 +50,7 @@ #include #include +#include #include #include @@ -315,6 +316,19 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetRenderWindow(SDL_Renderer *renderer); */ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info); +/** + * Get the properties associated with a renderer. + * + * \param renderer the rendering context + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); + /** * Get the output size in pixels of a rendering context. * @@ -422,6 +436,19 @@ typedef struct IDXGIResource IDXGIResource; */ extern DECLSPEC IDXGIResource* SDLCALL SDL_GetTextureDXGIResource(SDL_Texture *texture); +/** + * Get the properties associated with a texture. + * + * \param texture the texture to query + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); + /** * Query the attributes of a texture. * @@ -590,33 +617,6 @@ extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_Sc */ extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode); -/** - * Associate a user-specified pointer with a texture. - * - * \param texture the texture to update. - * \param userdata the pointer to associate with the texture. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetTextureUserData - */ -extern DECLSPEC int SDLCALL SDL_SetTextureUserData(SDL_Texture *texture, void *userdata); - -/** - * Get the user-specified pointer associated with a texture - * - * \param texture the texture to query. - * \returns the pointer associated with the texture, or NULL if the texture is - * not valid. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetTextureUserData - */ -extern DECLSPEC void *SDLCALL SDL_GetTextureUserData(SDL_Texture *texture); - /** * Update the given texture rectangle with new pixel data. * diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 6f6c3c013cc74..74c1ec6ec1872 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -31,6 +31,7 @@ #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -99,6 +100,7 @@ typedef struct SDL_RWops Uint32 type; Uint32 status; + SDL_PropertiesID props; union { #ifdef __ANDROID__ @@ -331,6 +333,19 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_CreateRW(void); */ extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context); +/** + * Get the properties associated with an SDL_RWops. + * + * \param context a pointer to an SDL_RWops structure + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRWProperties(SDL_RWops *context); + #define SDL_RW_SEEK_SET 0 /**< Seek from the beginning of data */ #define SDL_RW_SEEK_CUR 1 /**< Seek relative to current read point */ #define SDL_RW_SEEK_END 2 /**< Seek relative to the end of data */ diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h index 5715cab9a5b4e..4829bea472e9d 100644 --- a/include/SDL3/SDL_sensor.h +++ b/include/SDL3/SDL_sensor.h @@ -30,6 +30,7 @@ #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -189,6 +190,19 @@ extern DECLSPEC SDL_Sensor *SDLCALL SDL_OpenSensor(SDL_SensorID instance_id); */ extern DECLSPEC SDL_Sensor *SDLCALL SDL_GetSensorFromInstanceID(SDL_SensorID instance_id); +/** + * Get the properties associated with a sensor. + * + * \param sensor The SDL_Sensor object + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSensorProperties(SDL_Sensor *sensor); + /** * Get the implementation dependent name of a sensor * diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 6bf4b1d94c8b8..4a782175d564a 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -29,9 +29,10 @@ #define SDL_surface_h_ #include +#include #include +#include #include -#include #include #include @@ -92,7 +93,7 @@ typedef struct SDL_Surface void *pixels; /**< Read-write */ /** Application data associated with the surface */ - void *userdata; /**< Read-write */ + SDL_PropertiesID props; /**< Read-write */ /** information needed for surfaces requiring locks */ int locked; /**< Read-only */ @@ -189,6 +190,19 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom */ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); +/** + * Get the properties associated with a surface. + * + * \param surface the SDL_Surface structure to query + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface); + /** * Set the palette used by a surface. * diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index dd018de1d1d63..c3958e37492d7 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -93,7 +94,6 @@ typedef enum * \sa SDL_CreateWindowWithPosition() * \sa SDL_DestroyWindow() * \sa SDL_FlashWindow() - * \sa SDL_GetWindowData() * \sa SDL_GetWindowFlags() * \sa SDL_GetWindowGrab() * \sa SDL_GetWindowKeyboardGrab() @@ -106,7 +106,6 @@ typedef enum * \sa SDL_MinimizeWindow() * \sa SDL_RaiseWindow() * \sa SDL_RestoreWindow() - * \sa SDL_SetWindowData() * \sa SDL_SetWindowFullscreen() * \sa SDL_SetWindowGrab() * \sa SDL_SetWindowKeyboardGrab() @@ -918,6 +917,19 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowFromID(SDL_WindowID id); */ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); +/** + * Get the properties associated with a window. + * + * \param window the window to query + * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); + /** * Get the window flags. * @@ -977,35 +989,6 @@ extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window *window); */ extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); -/** - * Associate an arbitrary named pointer with a window. - * - * `name` is case-sensitive. - * - * \param window the window to associate with the pointer - * \param name the name of the pointer - * \param userdata the associated pointer - * \returns the previous value associated with `name`. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetWindowData - */ -extern DECLSPEC void *SDLCALL SDL_SetWindowData(SDL_Window *window, const char *name, void *userdata); - -/** - * Retrieve the data pointer associated with a window. - * - * \param window the window to query - * \param name the name of the pointer - * \returns the value associated with `name`. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetWindowData - */ -extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window *window, const char *name); - /** * Set the position of a window. * diff --git a/src/SDL_properties.c b/src/SDL_properties.c index a83067501dc42..29dd2391e130c 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -265,6 +265,11 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) return value; } +int SDL_ClearProperty(SDL_PropertiesID props, const char *name) +{ + return SDL_SetProperty(props, name, NULL, NULL, NULL); +} + void SDL_DestroyProperties(SDL_PropertiesID props) { if (!props) { diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 0dc1719658ecb..126a26c64e420 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -438,6 +438,18 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_ return retval; } +SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream) +{ + if (!stream) { + SDL_InvalidParamError("stream"); + return 0; + } + if (stream->props == 0) { + stream->props = SDL_CreateProperties(); + } + return stream->props; +} + int SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata) { if (!stream) { @@ -1161,6 +1173,8 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream) return; } + SDL_DestroyProperties(stream->props); + OnAudioStreamDestroy(stream); const SDL_bool simplified = stream->simplified; diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 68003171563ec..043b562af3a12 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -170,6 +170,8 @@ struct SDL_AudioStream { SDL_Mutex* lock; + SDL_PropertiesID props; + SDL_AudioStreamCallback get_callback; void *get_callback_userdata; SDL_AudioStreamCallback put_callback; diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index c73472068380b..c53c02adc6cd8 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -330,7 +330,6 @@ SDL3_0.0.0 { SDL_GetTextureBlendMode; SDL_GetTextureColorMod; SDL_GetTextureScaleMode; - SDL_GetTextureUserData; SDL_GetThreadID; SDL_GetThreadName; SDL_GetTicks; @@ -342,7 +341,6 @@ SDL3_0.0.0 { SDL_GetVersion; SDL_GetVideoDriver; SDL_GetWindowBordersSize; - SDL_GetWindowData; SDL_GetWindowDisplayScale; SDL_GetWindowFlags; SDL_GetWindowFromID; @@ -601,11 +599,9 @@ SDL3_0.0.0 { SDL_SetTextureBlendMode; SDL_SetTextureColorMod; SDL_SetTextureScaleMode; - SDL_SetTextureUserData; SDL_SetThreadPriority; SDL_SetWindowAlwaysOnTop; SDL_SetWindowBordered; - SDL_SetWindowData; SDL_SetWindowFullscreen; SDL_SetWindowFullscreenMode; SDL_SetWindowGrab; @@ -914,6 +910,16 @@ SDL3_0.0.0 { SDL_SetProperty; SDL_GetProperty; SDL_DestroyProperties; + SDL_GetAudioStreamProperties; + SDL_GetGamepadProperties; + SDL_GetJoystickProperties; + SDL_GetRendererProperties; + SDL_GetTextureProperties; + SDL_GetRWProperties; + SDL_GetSensorProperties; + SDL_GetSurfaceProperties; + SDL_GetWindowProperties; + SDL_ClearProperty; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8148554c54df8..dc85966627dd4 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -354,7 +354,6 @@ #define SDL_GetTextureBlendMode SDL_GetTextureBlendMode_REAL #define SDL_GetTextureColorMod SDL_GetTextureColorMod_REAL #define SDL_GetTextureScaleMode SDL_GetTextureScaleMode_REAL -#define SDL_GetTextureUserData SDL_GetTextureUserData_REAL #define SDL_GetThreadID SDL_GetThreadID_REAL #define SDL_GetThreadName SDL_GetThreadName_REAL #define SDL_GetTicks SDL_GetTicks_REAL @@ -366,7 +365,6 @@ #define SDL_GetVersion SDL_GetVersion_REAL #define SDL_GetVideoDriver SDL_GetVideoDriver_REAL #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL -#define SDL_GetWindowData SDL_GetWindowData_REAL #define SDL_GetWindowDisplayScale SDL_GetWindowDisplayScale_REAL #define SDL_GetWindowFlags SDL_GetWindowFlags_REAL #define SDL_GetWindowFromID SDL_GetWindowFromID_REAL @@ -624,11 +622,9 @@ #define SDL_SetTextureBlendMode SDL_SetTextureBlendMode_REAL #define SDL_SetTextureColorMod SDL_SetTextureColorMod_REAL #define SDL_SetTextureScaleMode SDL_SetTextureScaleMode_REAL -#define SDL_SetTextureUserData SDL_SetTextureUserData_REAL #define SDL_SetThreadPriority SDL_SetThreadPriority_REAL #define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL #define SDL_SetWindowBordered SDL_SetWindowBordered_REAL -#define SDL_SetWindowData SDL_SetWindowData_REAL #define SDL_SetWindowFullscreen SDL_SetWindowFullscreen_REAL #define SDL_SetWindowFullscreenMode SDL_SetWindowFullscreenMode_REAL #define SDL_SetWindowGrab SDL_SetWindowGrab_REAL @@ -939,3 +935,13 @@ #define SDL_SetProperty SDL_SetProperty_REAL #define SDL_GetProperty SDL_GetProperty_REAL #define SDL_DestroyProperties SDL_DestroyProperties_REAL +#define SDL_GetAudioStreamProperties SDL_GetAudioStreamProperties_REAL +#define SDL_GetGamepadProperties SDL_GetGamepadProperties_REAL +#define SDL_GetJoystickProperties SDL_GetJoystickProperties_REAL +#define SDL_GetRendererProperties SDL_GetRendererProperties_REAL +#define SDL_GetTextureProperties SDL_GetTextureProperties_REAL +#define SDL_GetRWProperties SDL_GetRWProperties_REAL +#define SDL_GetSensorProperties SDL_GetSensorProperties_REAL +#define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL +#define SDL_GetWindowProperties SDL_GetWindowProperties_REAL +#define SDL_ClearProperty SDL_ClearProperty_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 985b13eb5d6db..4e04f0c0b234c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -427,7 +427,6 @@ SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaMod,(SDL_Texture *a, Uint8 *b),(a,b),retu SDL_DYNAPI_PROC(int,SDL_GetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetTextureColorMod,(SDL_Texture *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_GetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode *b),(a,b),return) -SDL_DYNAPI_PROC(void*,SDL_GetTextureUserData,(SDL_Texture *a),(a),return) SDL_DYNAPI_PROC(SDL_threadID,SDL_GetThreadID,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetThreadName,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetTicks,(void),(),return) @@ -439,7 +438,6 @@ SDL_DYNAPI_PROC(const char*,SDL_GetTouchName,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetVersion,(SDL_version *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetVideoDriver,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(void*,SDL_GetWindowData,(SDL_Window *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_GetWindowDisplayScale,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_GetWindowFlags,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromID,(Uint32 a),(a),return) @@ -680,11 +678,9 @@ SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaMod,(SDL_Texture *a, Uint8 b),(a,b),retur SDL_DYNAPI_PROC(int,SDL_SetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetTextureColorMod,(SDL_Texture *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_SetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureUserData,(SDL_Texture *a, void *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetThreadPriority,(SDL_ThreadPriority a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetWindowBordered,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(void*,SDL_SetWindowData,(SDL_Window *a, const char *b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetWindowFullscreen,(SDL_Window *a, SDL_bool b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetWindowFullscreenMode,(SDL_Window *a, const SDL_DisplayMode *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetWindowGrab,(SDL_Window *a, SDL_bool b),(a,b),return) @@ -985,3 +981,13 @@ SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetJoystickProperties,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRendererProperties,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetTextureProperties,(SDL_Texture *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRWProperties,(SDL_RWops *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSensorProperties,(SDL_Sensor *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index cdd5b361d121d..aa429609982f5 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -619,6 +619,7 @@ SDL_RWops *SDL_CreateRW(void) void SDL_DestroyRW(SDL_RWops *context) { + SDL_DestroyProperties(context->props); SDL_free(context); } @@ -698,6 +699,19 @@ void *SDL_LoadFile(const char *file, size_t *datasize) return SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, SDL_TRUE); } +SDL_PropertiesID SDL_GetRWProperties(SDL_RWops *context) +{ + if (!context) { + SDL_InvalidParamError("context"); + return 0; + } + + if (context->props == 0) { + context->props = SDL_CreateProperties(); + } + return context->props; +} + Sint64 SDL_RWsize(SDL_RWops *context) { if (!context) { diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 4cb4a1481da2c..6bb982c57e370 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -2925,6 +2925,21 @@ SDL_JoystickID SDL_GetGamepadInstanceID(SDL_Gamepad *gamepad) return SDL_GetJoystickInstanceID(joystick); } +SDL_PropertiesID SDL_GetGamepadProperties(SDL_Gamepad *gamepad) +{ + SDL_PropertiesID retval = 0; + + SDL_LockJoysticks(); + { + CHECK_GAMEPAD_MAGIC(gamepad, 0); + + retval = SDL_GetJoystickProperties(gamepad->joystick); + } + SDL_UnlockJoysticks(); + + return retval; +} + const char *SDL_GetGamepadName(SDL_Gamepad *gamepad) { const char *retval = NULL; diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 268ba9fc49ea2..1a58402227bb9 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1213,6 +1213,27 @@ SDL_Joystick *SDL_GetJoystickFromPlayerIndex(int player_index) return joystick; } +/* + * Get the properties associated with a joystick + */ +SDL_PropertiesID SDL_GetJoystickProperties(SDL_Joystick *joystick) +{ + SDL_PropertiesID retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); + + if (joystick->props == 0) { + joystick->props = SDL_CreateProperties(); + } + retval = joystick->props; + } + SDL_UnlockJoysticks(); + + return retval; +} + /* * Get the friendly name of this joystick */ @@ -1465,6 +1486,8 @@ void SDL_CloseJoystick(SDL_Joystick *joystick) return; } + SDL_DestroyProperties(joystick->props); + if (joystick->rumble_expiration) { SDL_RumbleJoystick(joystick, 0, 0, 0); } diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index f0f547e10d97c..8ac081026aff9 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -125,6 +125,8 @@ struct SDL_Joystick struct joystick_hwdata *hwdata _guarded; /* Driver dependent information */ + SDL_PropertiesID props _guarded; + int ref_count _guarded; /* Reference count for multiple opens */ struct SDL_Joystick *next _guarded; /* pointer to next joystick we have allocated */ diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 9e9fc1629bdf7..dfcd8a97d0f51 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -929,7 +929,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl renderer->hidden = SDL_FALSE; } - SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, renderer, NULL, NULL); SDL_SetRenderViewport(renderer, NULL); @@ -994,7 +994,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) SDL_Renderer *SDL_GetRenderer(SDL_Window *window) { - return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA); + return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA); } SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) @@ -1007,10 +1007,20 @@ int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info) { CHECK_RENDERER_MAGIC(renderer, -1); - *info = renderer->info; + SDL_copyp(info, &renderer->info); return 0; } +SDL_PropertiesID SDL_GetRendererProperties(SDL_Renderer *renderer) +{ + CHECK_RENDERER_MAGIC(renderer, 0); + + if (renderer->props == 0) { + renderer->props = SDL_CreateProperties(); + } + return renderer->props; +} + int SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) { CHECK_RENDERER_MAGIC(renderer, -1); @@ -1365,6 +1375,16 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s return texture; } +SDL_PropertiesID SDL_GetTextureProperties(SDL_Texture *texture) +{ + CHECK_TEXTURE_MAGIC(texture, 0); + + if (texture->props == 0) { + texture->props = SDL_CreateProperties(); + } + return texture->props; +} + int SDL_QueryTexture(SDL_Texture *texture, Uint32 *format, int *access, int *w, int *h) { CHECK_TEXTURE_MAGIC(texture, -1); @@ -1497,21 +1517,6 @@ int SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode) return 0; } -int SDL_SetTextureUserData(SDL_Texture *texture, void *userdata) -{ - CHECK_TEXTURE_MAGIC(texture, -1); - - texture->userdata = userdata; - return 0; -} - -void *SDL_GetTextureUserData(SDL_Texture *texture) -{ - CHECK_TEXTURE_MAGIC(texture, NULL); - - return texture->userdata; -} - #if SDL_HAVE_YUV static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch) @@ -4021,6 +4026,8 @@ static int SDL_DestroyTextureInternal(SDL_Texture *texture, SDL_bool is_destroyi CHECK_TEXTURE_MAGIC(texture, -1); + SDL_DestroyProperties(texture->props); + renderer = texture->renderer; if (is_destroying) { /* Renderer get destroyed, avoid to queue more commands */ @@ -4103,6 +4110,8 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer,); + SDL_DestroyProperties(renderer->props); + SDL_DelEventWatch(SDL_RendererEventWatch, renderer); SDL_DiscardAllCommands(renderer); @@ -4118,7 +4127,7 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer->vertex_data); if (renderer->window) { - SDL_SetWindowData(renderer->window, SDL_WINDOWRENDERDATA, NULL); + SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_WINDOWRENDERDATA); } /* It's no longer magical... */ diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index b1cb2e8e29e1d..38bc703b3cb3c 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -83,8 +83,9 @@ struct SDL_Texture Uint32 last_command_generation; /* last command queue generation this texture was in. */ + SDL_PropertiesID props; + void *driverdata; /**< Driver specific texture representation */ - void *userdata; SDL_Texture *prev; SDL_Texture *next; @@ -272,6 +273,8 @@ struct SDL_Renderer size_t vertex_data_used; size_t vertex_data_allocation; + SDL_PropertiesID props; + void *driverdata; }; diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 0a186e889dd85..85a828895efd7 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -393,6 +393,27 @@ SDL_Sensor *SDL_GetSensorFromInstanceID(SDL_SensorID instance_id) return sensor; } +/* + * Get the properties associated with a sensor. + */ +SDL_PropertiesID SDL_GetSensorProperties(SDL_Sensor *sensor) +{ + SDL_PropertiesID retval; + + SDL_LockSensors(); + { + CHECK_SENSOR_MAGIC(sensor, 0); + + if (sensor->props == 0) { + sensor->props = SDL_CreateProperties(); + } + retval = sensor->props; + } + SDL_UnlockSensors(); + + return retval; +} + /* * Get the friendly name of this sensor */ @@ -500,6 +521,8 @@ void SDL_CloseSensor(SDL_Sensor *sensor) return; } + SDL_DestroyProperties(sensor->props); + sensor->driver->Close(sensor); sensor->hwdata = NULL; diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index 9376be6b96201..2e3e3b3ca22b5 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -45,6 +45,8 @@ struct SDL_Sensor struct sensor_hwdata *hwdata _guarded; /* Driver dependent information */ + SDL_PropertiesID props _guarded; + int ref_count _guarded; /* Reference count for multiple opens */ struct SDL_Sensor *next _guarded; /* pointer to next sensor we have allocated */ diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index fe43b2f26f328..7c89a43fa1702 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -211,9 +211,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) * Create an RGB surface from an existing memory buffer using the given given * enum SDL_PIXELFORMAT_* format */ -SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, - int width, int height, int pitch, - Uint32 format) +SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitch, Uint32 format) { SDL_Surface *surface; @@ -256,10 +254,23 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, return surface; } +SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface) +{ + if (surface == NULL) { + SDL_InvalidParamError("surface"); + return 0; + } + + if (surface->props == 0) { + surface->props = SDL_CreateProperties(); + } + return surface->props; +} + int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette) { if (surface == NULL) { - return SDL_InvalidParamError("SDL_SetSurfacePalette(): surface"); + return SDL_InvalidParamError("surface"); } if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) { return -1; @@ -1550,13 +1561,14 @@ void SDL_DestroySurface(SDL_Surface *surface) if (surface->flags & SDL_DONTFREE) { return; } - SDL_InvalidateMap(surface->map); - - SDL_InvalidateAllBlitMap(surface); - if (--surface->refcount > 0) { return; } + + SDL_DestroyProperties(surface->props); + SDL_InvalidateMap(surface->map); + SDL_InvalidateAllBlitMap(surface); + while (surface->locked > 0) { SDL_UnlockSurface(surface); } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 0d55708a94f0a..20bb76912cbfa 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -58,13 +58,6 @@ struct SDL_ShapeDriver int (*SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode); }; -typedef struct SDL_WindowUserData -{ - char *name; - void *data; - struct SDL_WindowUserData *next; -} SDL_WindowUserData; - /* Define the SDL window structure, corresponding to toplevel windows */ struct SDL_Window { @@ -111,7 +104,7 @@ struct SDL_Window SDL_HitTest hit_test; void *hit_test_data; - SDL_WindowUserData *data; + SDL_PropertiesID props; SDL_WindowData *driverdata; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 4ea7a9363844e..90a2467c519bd 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -209,10 +209,25 @@ static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this) return 0; } +static void SDL_CleanupWindowTextureData(void *userdata, void *value) +{ + SDL_WindowTextureData *data = (SDL_WindowTextureData *)value; + + if (data->texture) { + SDL_DestroyTexture(data->texture); + } + if (data->renderer) { + SDL_DestroyRenderer(data->renderer); + } + SDL_free(data->pixels); + SDL_free(data); +} + static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch) { SDL_RendererInfo info; - SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA); + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA); const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; int i; int w, h; @@ -265,7 +280,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_DestroyRenderer(renderer); return SDL_OutOfMemory(); } - SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data); + SDL_SetProperty(props, SDL_WINDOWTEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); data->renderer = renderer; } else { @@ -335,7 +350,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, SDL_GetWindowSizeInPixels(window, &w, &h); - data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); if (data == NULL || !data->texture) { return SDL_SetError("No window texture data"); } @@ -360,27 +375,14 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, static void SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window *window) { - SDL_WindowTextureData *data; - - data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL); - if (data == NULL) { - return; - } - if (data->texture) { - SDL_DestroyTexture(data->texture); - } - if (data->renderer) { - SDL_DestroyRenderer(data->renderer); - } - SDL_free(data->pixels); - SDL_free(data); + SDL_ClearProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); } int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync) { SDL_WindowTextureData *data; - data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); if (data == NULL) { return -1; } @@ -2305,6 +2307,16 @@ SDL_Window *SDL_GetWindowParent(SDL_Window *window) return window->parent; } +SDL_PropertiesID SDL_GetWindowProperties(SDL_Window *window) +{ + CHECK_WINDOW_MAGIC(window, 0); + + if (window->props == 0) { + window->props = SDL_CreateProperties(); + } + return window->props; +} + Uint32 SDL_GetWindowFlags(SDL_Window *window) { CHECK_WINDOW_MAGIC(window, 0); @@ -2360,72 +2372,6 @@ int SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon) return _this->SetWindowIcon(_this, window, window->icon); } -void *SDL_SetWindowData(SDL_Window *window, const char *name, void *userdata) -{ - SDL_WindowUserData *prev, *data; - - CHECK_WINDOW_MAGIC(window, NULL); - - /* Input validation */ - if (name == NULL || name[0] == '\0') { - SDL_InvalidParamError("name"); - return NULL; - } - - /* See if the named data already exists */ - prev = NULL; - for (data = window->data; data; prev = data, data = data->next) { - if (data->name && SDL_strcmp(data->name, name) == 0) { - void *last_value = data->data; - - if (userdata) { - /* Set the new value */ - data->data = userdata; - } else { - /* Delete this value */ - if (prev) { - prev->next = data->next; - } else { - window->data = data->next; - } - SDL_free(data->name); - SDL_free(data); - } - return last_value; - } - } - - /* Add new data to the window */ - if (userdata) { - data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data)); - data->name = SDL_strdup(name); - data->data = userdata; - data->next = window->data; - window->data = data; - } - return NULL; -} - -void *SDL_GetWindowData(SDL_Window *window, const char *name) -{ - SDL_WindowUserData *data; - - CHECK_WINDOW_MAGIC(window, NULL); - - /* Input validation */ - if (name == NULL || name[0] == '\0') { - SDL_InvalidParamError("name"); - return NULL; - } - - for (data = window->data; data; data = data->next) { - if (data->name && SDL_strcmp(data->name, name) == 0) { - return data->data; - } - } - return NULL; -} - int SDL_SetWindowPosition(SDL_Window *window, int x, int y) { SDL_DisplayID original_displayID; @@ -3657,13 +3603,6 @@ void SDL_DestroyWindow(SDL_Window *window) /* Free memory associated with the window */ SDL_free(window->title); SDL_DestroySurface(window->icon); - while (window->data) { - SDL_WindowUserData *data = window->data; - - window->data = data->next; - SDL_free(data->name); - SDL_free(data); - } /* Unlink the window from the list */ if (window->next) { diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index ba7f43fcbcb57..efdd6a377ebae 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -27,16 +27,20 @@ #define DUMMY_SURFACE "_SDL_DummySurface" +static void CleanupSurface(void *userdata, void *value) +{ + SDL_Surface *surface = (SDL_Surface *)value; + + SDL_DestroySurface(surface); +} + int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch) { SDL_Surface *surface; const Uint32 surface_format = SDL_PIXELFORMAT_XRGB8888; int w, h; - /* Free the old framebuffer surface */ - SDL_DUMMY_DestroyWindowFramebuffer(_this, window); - - /* Create a new one */ + /* Create a new framebuffer */ SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); if (surface == NULL) { @@ -44,7 +48,7 @@ int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window } /* Save the info and return! */ - SDL_SetWindowData(window, DUMMY_SURFACE, surface); + SDL_SetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE, surface, CleanupSurface, NULL); *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; @@ -56,7 +60,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window static int frame_number; SDL_Surface *surface; - surface = (SDL_Surface *)SDL_GetWindowData(window, DUMMY_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE); if (surface == NULL) { return SDL_SetError("Couldn't find dummy surface for window"); } @@ -73,10 +77,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window void SDL_DUMMY_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_Surface *surface; - - surface = (SDL_Surface *)SDL_SetWindowData(window, DUMMY_SURFACE, NULL); - SDL_DestroySurface(surface); + SDL_ClearProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE); } #endif /* SDL_VIDEO_DRIVER_DUMMY */ diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 2e93c528fdf5a..57a55f5aab144 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -33,44 +33,37 @@ typedef struct int width, height; } Dimensions; -static void FreePreviousWindowFramebuffer(SDL_Window *window); -static SDL_Surface *CreateNewWindowFramebuffer(SDL_Window *window); static void CopyFramebuffertoN3DS(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim); static int GetDestOffset(int x, int y, int dest_width); static int GetSourceOffset(int x, int y, int source_width); static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen); +static void CleanupSurface(void *userdata, void *value) +{ + SDL_Surface *surface = (SDL_Surface *)value; + + SDL_DestroySurface(surface); +} + int SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch) { SDL_Surface *framebuffer; + int w, h; - FreePreviousWindowFramebuffer(window); - framebuffer = CreateNewWindowFramebuffer(window); + SDL_GetWindowSizeInPixels(window, &w, &h); + framebuffer = SDL_CreateSurface(w, h, FRAMEBUFFER_FORMAT); if (framebuffer == NULL) { return SDL_OutOfMemory(); } - SDL_SetWindowData(window, N3DS_SURFACE, framebuffer); + SDL_SetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, framebuffer, CleanupSurface, NULL); *format = FRAMEBUFFER_FORMAT; *pixels = framebuffer->pixels; *pitch = framebuffer->pitch; return 0; } -static void FreePreviousWindowFramebuffer(SDL_Window *window) -{ - SDL_Surface *surface = (SDL_Surface *)SDL_GetWindowData(window, N3DS_SURFACE); - SDL_DestroySurface(surface); -} - -static SDL_Surface *CreateNewWindowFramebuffer(SDL_Window *window) -{ - int w, h; - SDL_GetWindowSizeInPixels(window, &w, &h); - return SDL_CreateSurface(w, h, FRAMEBUFFER_FORMAT); -} - int SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects) { SDL_WindowData *drv_data = window->driverdata; @@ -79,7 +72,7 @@ int SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, u32 *framebuffer; u32 bufsize; - surface = (SDL_Surface *)SDL_GetWindowData(window, N3DS_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE); if (surface == NULL) { return SDL_SetError("%s: Unable to get the window surface.", __func__); } @@ -127,9 +120,7 @@ static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen) void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_Surface *surface; - surface = (SDL_Surface *)SDL_SetWindowData(window, N3DS_SURFACE, NULL); - SDL_DestroySurface(surface); + SDL_ClearProperty(SDL_GetWindowProperties(window), N3DS_SURFACE); } #endif /* SDL_VIDEO_DRIVER_N3DS */ diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index 2ab1b9884a8da..d51443932a504 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -27,16 +27,20 @@ #define OFFSCREEN_SURFACE "_SDL_DummySurface" +static void CleanupSurface(void *userdata, void *value) +{ + SDL_Surface *surface = (SDL_Surface *)value; + + SDL_DestroySurface(surface); +} + int SDL_OFFSCREEN_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch) { SDL_Surface *surface; const Uint32 surface_format = SDL_PIXELFORMAT_XRGB8888; int w, h; - /* Free the old framebuffer surface */ - SDL_OFFSCREEN_DestroyWindowFramebuffer(_this, window); - - /* Create a new one */ + /* Create a new framebuffer */ SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); if (surface == NULL) { @@ -44,7 +48,7 @@ int SDL_OFFSCREEN_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi } /* Save the info and return! */ - SDL_SetWindowData(window, OFFSCREEN_SURFACE, surface); + SDL_SetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE, surface, CleanupSurface, NULL); *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; @@ -57,7 +61,7 @@ int SDL_OFFSCREEN_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi static int frame_number; SDL_Surface *surface; - surface = (SDL_Surface *)SDL_GetWindowData(window, OFFSCREEN_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE); if (surface == NULL) { return SDL_SetError("Couldn't find offscreen surface for window"); } @@ -74,10 +78,7 @@ int SDL_OFFSCREEN_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi void SDL_OFFSCREEN_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_Surface *surface; - - surface = (SDL_Surface *)SDL_SetWindowData(window, OFFSCREEN_SURFACE, NULL); - SDL_DestroySurface(surface); + SDL_ClearProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE); } #endif /* SDL_VIDEO_DRIVER_OFFSCREEN */ diff --git a/test/testautomation_video.c b/test/testautomation_video.c index b57fb8213c762..5d0523f21f7a6 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1492,21 +1492,21 @@ static int video_getSetWindowData(void *arg) } /* Get non-existent data */ - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data */ - result = (char *)SDL_SetWindowData(window, name, userdata); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s)", name, userdata); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); /* Get data (twice) */ for (iteration = 1; iteration <= 2; iteration++) { - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), + name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [iteration %d]", name, iteration); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1514,130 +1514,104 @@ static int video_getSetWindowData(void *arg) /* Set data again twice */ for (iteration = 1; iteration <= 2; iteration++) { - result = (char *)SDL_SetWindowData(window, name, userdata); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [iteration %d]", name, userdata, iteration); - SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); } /* Get data again */ - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again]", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data with new data */ - result = (char *)SDL_SetWindowData(window, name, userdata2); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [new userdata]", name, userdata2); - SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Set data with new data again */ - result = (char *)SDL_SetWindowData(window, name, userdata2); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [new userdata again]", name, userdata2); - SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata2, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Get new data */ - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata2, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data with NULL to clear */ - result = (char *)SDL_SetWindowData(window, name, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,NULL)", name); - SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata2, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Set data with NULL to clear again */ - result = (char *)SDL_SetWindowData(window, name, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,NULL) [again]", name); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Get non-existent data */ - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Get non-existent data new name */ - result = (char *)SDL_GetWindowData(window, name2); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name2); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name2); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName2, name2) == 0, "Validate that name2 was not changed, expected: %s, got: %s", referenceName2, name2); /* Set data (again) */ - result = (char *)SDL_SetWindowData(window, name, userdata); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [again, after clear]", name, userdata); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); /* Get data (again) */ - result = (char *)SDL_GetWindowData(window, name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again, after clear]", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); - /* Negative test */ - SDL_ClearError(); - SDLTest_AssertPass("Call to SDL_ClearError()"); - - /* Set with invalid window */ - result = (char *)SDL_SetWindowData(NULL, name, userdata); - SDLTest_AssertPass("Call to SDL_SetWindowData(window=NULL)"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); - checkInvalidWindowError(); - /* Set data with NULL name, valid userdata */ - result = (char *)SDL_SetWindowData(window, NULL, userdata); + SDL_SetProperty(SDL_GetWindowProperties(window), NULL, userdata, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name=NULL)"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); /* Set data with empty name, valid userdata */ - result = (char *)SDL_SetWindowData(window, "", userdata); + SDL_SetProperty(SDL_GetWindowProperties(window), "", userdata, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name='')"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); /* Set data with NULL name, NULL userdata */ - result = (char *)SDL_SetWindowData(window, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), NULL, NULL, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name=NULL,userdata=NULL)"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); /* Set data with empty name, NULL userdata */ - result = (char *)SDL_SetWindowData(window, "", NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), "", NULL, NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name='',userdata=NULL)"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); - /* Get with invalid window */ - result = (char *)SDL_GetWindowData(NULL, name); - SDLTest_AssertPass("Call to SDL_GetWindowData(window=NULL)"); - SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); - checkInvalidWindowError(); - /* Get data with NULL name */ - result = (char *)SDL_GetWindowData(window, NULL); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(name=NULL)"); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); /* Get data with empty name */ - result = (char *)SDL_GetWindowData(window, ""); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), ""); SDLTest_AssertPass("Call to SDL_GetWindowData(name='')"); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); From efa9a45048e759155bf32ac5780b6ada56c482ef Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 11 Oct 2023 23:38:08 -0700 Subject: [PATCH 062/725] Clarified that testffmpeg will resize the window to the video size --- test/testffmpeg.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index ddf375996d551..090aca6b36099 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -55,10 +55,6 @@ #include "icon.h" -#define WINDOW_WIDTH 640 -#define WINDOW_HEIGHT 480 - - static SDL_Texture *sprite; static SDL_FRect *positions; static SDL_FRect *velocities; @@ -108,7 +104,8 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, window_flags, &window, &renderer) < 0) { + /* The window will be resized to the video size when it's loaded, in OpenVideoStream() */ + if (SDL_CreateWindowAndRenderer(320, 200, window_flags, &window, &renderer) < 0) { return SDL_FALSE; } From bf64fecf19f87d54af2f2e3b4430318552ac997d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Oct 2023 00:01:02 -0700 Subject: [PATCH 063/725] testffmpeg: allow resizing of the video window --- test/testffmpeg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 090aca6b36099..6142c1f562667 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -113,6 +113,9 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) SDL_Log("Created renderer %s\n", info.name); } + /* Use linear scaling in case the user resizes the window */ + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + #ifdef HAVE_EGL if (useEGL) { const char *extensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); @@ -834,7 +837,7 @@ int main(int argc, char *argv[]) goto quit; } - window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; + window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; #ifdef __APPLE__ window_flags |= SDL_WINDOW_METAL; #elif !defined(__WIN32__) From 0efa196989b66884c2d08f9b4a4713811eec83e7 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 27 Sep 2023 05:14:14 +0200 Subject: [PATCH 064/725] dynapi: implement SDL_DYNAPI_entry even when building SDL without dynapi support --- src/dynapi/SDL_dynapi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index e85437c70a7e4..9ec57e41e0111 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -523,4 +523,17 @@ static void SDL_InitDynamicAPI(void) #endif } +#else /* SDL_DYNAMIC_API */ + +#include + +Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize); +Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) +{ + (void)apiver; + (void)table; + (void)tablesize; + return -1; /* not compatible. */ +} + #endif /* SDL_DYNAMIC_API */ From 3a36433a3c78936ecc446309c701a80af1b135e3 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 20 Sep 2023 04:24:08 +0200 Subject: [PATCH 065/725] cmake: test -Wl,--version-script with minimal version script Android ndk 26 errors when a symbol in the version script is not defined. --- CMakeLists.txt | 2 +- cmake/macros.cmake | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5188e5380a8e..0baea19031b73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -423,7 +423,7 @@ if(WINDOWS_STORE) sdl_compile_options(PRIVATE "-ZW") endif() -check_linker_flag(C "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/dynapi/SDL_dynapi.sym" HAVE_WL_VERSION_SCRIPT) +check_linker_supports_version_file(HAVE_WL_VERSION_SCRIPT) if(HAVE_WL_VERSION_SCRIPT) sdl_shared_link_options("-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/dynapi/SDL_dynapi.sym") else() diff --git a/cmake/macros.cmake b/cmake/macros.cmake index 32fc9f1a1dba3..de9680047bc95 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -82,16 +82,25 @@ if(APPLE) enable_language(OBJC) endif() +function(check_linker_supports_version_file VAR) + cmake_push_check_state() + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n") + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym") + check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error)") + cmake_pop_check_state() + set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE) +endfunction() + if(CMAKE_VERSION VERSION_LESS 3.18) function(check_linker_flag LANG FLAG VAR) cmake_push_check_state() list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${FLAG} ) if(LANG STREQUAL "C") include(CheckCSourceCompiles) - check_c_source_compiles("int main(int argc,char*argv[]){(void)argc;(void)argv;return 0;}" ${VAR} FAIL_REGEX "warning") + check_c_source_compiles("int main(int argc,char*argv[]){(void)argc;(void)argv;return 0;}" ${VAR} FAIL_REGEX "(unsupported|syntax error)") elseif(LANG STREQUAL "CXX") include(CheckCXXSourceCompiles) - check_cxx_source_compiles("int main(int argc,char*argv[]){(void)argc;(void)argv;return 0;}" ${VAR} FAIL_REGEX "warning") + check_cxx_source_compiles("int main(int argc,char*argv[]){(void)argc;(void)argv;return 0;}" ${VAR} FAIL_REGEX "(unsupported|syntax error)") else() message(FATAL_ERROR "Unsupported language: ${LANG}") endif() From 25ce87979dc571e4e85090fcb747639a0db85173 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 27 Sep 2023 06:11:09 +0200 Subject: [PATCH 066/725] Always provide an implementation for all SDL3 symbols --- Android.mk | 1 + VisualC-GDK/SDL/SDL.vcxproj | 4 + VisualC-GDK/SDL/SDL.vcxproj.filters | 13 ++ VisualC-WinRT/SDL-UWP.vcxproj | 4 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 12 ++ VisualC/SDL/SDL.vcxproj | 4 + VisualC/SDL/SDL.vcxproj.filters | 14 +- src/core/SDL_core_unsupported.c | 218 +++++++++++++++++++++++ src/render/SDL_render_unsupported.c | 49 +++++ src/render/direct3d12/SDL_render_d3d12.c | 6 +- src/video/SDL_video_unsupported.c | 83 +++++++++ 11 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 src/core/SDL_core_unsupported.c create mode 100644 src/render/SDL_render_unsupported.c create mode 100644 src/video/SDL_video_unsupported.c diff --git a/Android.mk b/Android.mk index 4c26d3c9886a8..3779eb53416ba 100644 --- a/Android.mk +++ b/Android.mk @@ -24,6 +24,7 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/audio/openslES/*.c) \ $(LOCAL_PATH)/src/atomic/SDL_atomic.c.arm \ $(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \ + $(wildcard $(LOCAL_PATH)/src/core/*.c) \ $(wildcard $(LOCAL_PATH)/src/core/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \ $(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \ diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 7df28485fcaa0..bb003d0f08311 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -557,6 +557,8 @@ + + @@ -699,6 +701,7 @@ + @@ -767,6 +770,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 19b7eb904b86c..bbdc75985c4d5 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -885,6 +885,13 @@ atomic + + core + + + core + + core\windows @@ -1182,6 +1189,9 @@ video + + video + video @@ -1308,6 +1318,9 @@ render + + render + render diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index c911765b9941b..372a283396838 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -250,6 +250,8 @@ true true + + @@ -383,6 +385,7 @@ + @@ -512,6 +515,7 @@ + true diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 7b90f411fbee0..92e6f4a8d4e7b 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -498,6 +498,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -606,6 +612,9 @@ Source Files + + Source Files + Source Files @@ -786,6 +795,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index f4d4dc002cb07..5a63ba770e371 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -484,6 +484,8 @@ + + @@ -578,6 +580,7 @@ + @@ -642,6 +645,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index f72de3a0a0cfb..b2e57b4fabf5a 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -419,7 +419,7 @@ audio - + core\windows @@ -864,6 +864,12 @@ atomic + + core + + + core + core\windows @@ -1161,6 +1167,9 @@ video + + video + video @@ -1290,6 +1299,9 @@ render + + render + render diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c new file mode 100644 index 0000000000000..5e1f82834944c --- /dev/null +++ b/src/core/SDL_core_unsupported.c @@ -0,0 +1,218 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef __LINUX__ + +DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); +int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) +{ + (void)threadID; + (void)priority; + return SDL_Unsupported(); +} + +DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); +int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy) +{ + (void)threadID; + (void)sdlPriority; + (void)schedPolicy; + return SDL_Unsupported(); +} + +#endif + +#ifndef __GDK__ + +DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); +void SDL_GDKSuspendComplete(void) +{ + SDL_Unsupported(); +} + +DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(void *outUserHandle); /* XUserHandle *outUserHandle */ +int SDL_GDKGetDefaultUser(void *outUserHandle) +{ + return SDL_Unsupported(); +} + +#endif + +#if !(defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)) + +DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); +int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) +{ + (void)name; + (void)style; + (void)hInst; + return SDL_Unsupported(); +} + +DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(void *callback, void *userdata); /* SDL_WindowsMessageHook callback */ +void SDL_SetWindowsMessageHook(void *callback, void *userdata) +{ + (void)callback; + (void)userdata; + SDL_Unsupported(); +} + +DECLSPEC void SDLCALL SDL_UnregisterApp(void); +void SDL_UnregisterApp(void) +{ + SDL_Unsupported(); +} + +#endif + +#ifndef __WINRT__ + +/* Returns SDL_WinRT_DeviceFamily enum */ +DECLSPEC int SDLCALL SDL_WinRTGetDeviceFamily(void); +int SDL_WinRTGetDeviceFamily() +{ + SDL_Unsupported(); + return 0; /* SDL_WINRT_DEVICEFAMILY_UNKNOWN */ +} + +DECLSPEC const wchar_t *SDLCALL SDL_WinRTGetFSPathUNICODE(int pathType); /* SDL_WinRT_Path pathType */ +const wchar_t *SDL_WinRTGetFSPathUNICODE(int pathType) +{ + (void)pathType; + SDL_Unsupported(); + return NULL; +} + +DECLSPEC const char *SDLCALL SDL_WinRTGetFSPathUTF8(int pathType); /* SDL_WinRT_Path pathType */ +const char *SDL_WinRTGetFSPathUTF8(int pathType) +{ + (void)pathType; + SDL_Unsupported(); + return NULL; +} +#endif + +#ifndef __ANDROID__ + +DECLSPEC void SDLCALL SDL_AndroidBackButton(void); +void SDL_AndroidBackButton() +{ + SDL_Unsupported(); +} + +DECLSPEC void *SDLCALL SDL_AndroidGetActivity(void); +void *SDL_AndroidGetActivity() +{ + SDL_Unsupported(); + return NULL; +} + +DECLSPEC const char *SDLCALL SDL_AndroidGetExternalStoragePath(void); +const char* SDL_AndroidGetExternalStoragePath() +{ + SDL_Unsupported(); + return NULL; +} + +DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state); +int SDL_AndroidGetExternalStorageState(Uint32 *state) +{ + (void)state; + return SDL_Unsupported(); +} +DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void); +const char *SDL_AndroidGetInternalStoragePath() +{ + SDL_Unsupported(); + return NULL; +} + +DECLSPEC void *SDLCALL SDL_AndroidGetJNIEnv(void); +void *SDL_AndroidGetJNIEnv() +{ + SDL_Unsupported(); + return NULL; +} + +DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission); +SDL_bool SDL_AndroidRequestPermission(const char *permission) +{ + (void)permission; + SDL_Unsupported(); + return SDL_FALSE; +} + +DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); +int SDL_AndroidSendMessage(Uint32 command, int param) +{ + (void)command; + (void)param; + return SDL_Unsupported(); +} + +DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset); +int SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset) +{ + (void)message; + (void)duration; + (void)gravity; + (void)xoffset; + (void)yoffset; + return SDL_Unsupported(); +} + +DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); +int SDL_GetAndroidSDKVersion() +{ + return SDL_Unsupported(); +} + +DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void); +SDL_bool SDL_IsAndroidTV() +{ + SDL_Unsupported(); + return SDL_FALSE; +} + +DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void); +SDL_bool SDL_IsChromebook() +{ + SDL_Unsupported(); + return SDL_FALSE; +} + +DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void); +SDL_bool SDL_IsDeXMode(void) +{ + SDL_Unsupported(); + return SDL_FALSE; +} + +DECLSPEC Sint32 SDLCALL JNI_OnLoad(void *vm, void *reserved); +Sint32 JNI_OnLoad(void *vm, void *reserved) +{ + (void)vm; + (void)reserved; + SDL_Unsupported(); + return -1; /* JNI_ERR */ +} +#endif diff --git a/src/render/SDL_render_unsupported.c b/src/render/SDL_render_unsupported.c new file mode 100644 index 0000000000000..4d223895f9413 --- /dev/null +++ b/src/render/SDL_render_unsupported.c @@ -0,0 +1,49 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#if !(defined(__WIN32__) || defined(__WINGDK__)) + +DECLSPEC void *SDLCALL SDL_GetRenderD3D9Device(SDL_Renderer *renderer); /* returns IDirect3DDevice9 * */ +void *SDL_GetRenderD3D9Device(SDL_Renderer *renderer) +{ + (void)renderer; + SDL_Unsupported(); + return NULL; +} + +DECLSPEC void *SDLCALL SDL_GetRenderD3D11Device(SDL_Renderer *renderer); /* returns ID3D11Device * */ +void *SDL_GetRenderD3D11Device(SDL_Renderer *renderer) +{ + (void)renderer; + SDL_Unsupported(); + return NULL; +} + +DECLSPEC void *SDLCALL SDL_RenderGetD3D12Device(SDL_Renderer *renderer); /* return ID3D12Device * */ +void *SDL_RenderGetD3D12Device(SDL_Renderer *renderer) +{ + (void)renderer; + SDL_Unsupported(); + return NULL; +} + +#endif diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index fb18838dce0e9..0a5ddca37770d 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -3051,9 +3051,9 @@ SDL_RenderDriver D3D12_RenderDriver = { #ifdef __cplusplus extern "C" #endif - /* This function needs to always exist on Windows, for the Dynamic API. */ - ID3D12Device * - SDL_RenderGetD3D12Device(SDL_Renderer *renderer) +/* This function needs to always exist on Windows, for the Dynamic API. */ +ID3D12Device * +SDL_RenderGetD3D12Device(SDL_Renderer *renderer) { ID3D12Device *device = NULL; diff --git a/src/video/SDL_video_unsupported.c b/src/video/SDL_video_unsupported.c new file mode 100644 index 0000000000000..66be30101873d --- /dev/null +++ b/src/video/SDL_video_unsupported.c @@ -0,0 +1,83 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_VIDEO_DRIVER_WINDOWS + +DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex); +SDL_bool SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex) +{ + (void)displayID; + (void)adapterIndex; + (void)outputIndex; + SDL_Unsupported(); + return SDL_FALSE; +} + +DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID); +int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID) +{ + (void)displayID; + return SDL_Unsupported(); +} + +#endif + +#ifndef SDL_GDK_TEXTINPUT + +DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(void *outTaskQueue); +int SDL_GDKGetTaskQueue(void *outTaskQueue) +{ + (void)outTaskQueue; + return SDL_Unsupported(); +} + +#endif + +#ifndef SDL_VIDEO_DRIVER_UIKIT + +DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void); +void SDL_OnApplicationDidChangeStatusBarOrientation(void) +{ + SDL_Unsupported(); +} + +#endif + +#ifndef SDL_VIDEO_DRIVER_UIKIT + +DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window *window, int interval, void (*callback)(void *), void *callbackParam); +int SDL_iPhoneSetAnimationCallback(SDL_Window *window, int interval, void (*callback)(void *), void *callbackParam) +{ + (void)window; + (void)interval; + (void)callback; + (void)callbackParam; + return SDL_Unsupported(); +} + +DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); +void SDL_iPhoneSetEventPump(SDL_bool enabled) +{ + (void)enabled; + SDL_Unsupported(); +} +#endif From c9ccf0670c6731ea35ee8c70bfe0cb48851cec91 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 27 Sep 2023 19:54:00 +0200 Subject: [PATCH 067/725] Add unsupported functions to dynapi --- VisualC/SDL/SDL.vcxproj | 1 + VisualC/SDL/SDL.vcxproj.filters | 3 ++ src/dynapi/SDL_dynapi.c | 1 + src/dynapi/SDL_dynapi_procs.h | 18 ++--------- src/dynapi/SDL_dynapi_unsupported.h | 48 +++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 src/dynapi/SDL_dynapi_unsupported.h diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 5a63ba770e371..a40d5acb57176 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -332,6 +332,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index b2e57b4fabf5a..f72a3a0fca882 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -444,6 +444,9 @@ dynapi + + dynapi + events diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 9ec57e41e0111..8dc4b999a1f22 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -21,6 +21,7 @@ #include "build_config/SDL_build_config.h" #include "SDL_dynapi.h" +#include "SDL_dynapi_unsupported.h" #if SDL_DYNAMIC_API diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4e04f0c0b234c..b8ac62c583b07 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -65,43 +65,30 @@ SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d),(a,b,c,d),return) #endif -#if defined(__WIN32__) || defined(__GDK__) SDL_DYNAPI_PROC(int,SDL_RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(ID3D12Device*,SDL_RenderGetD3D12Device,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(void,SDL_SetWindowsMessageHook,(SDL_WindowsMessageHook a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) -#endif -#if defined(__WIN32__) || defined(__WINGDK__) SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(SDL_DisplayID a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_Direct3D9GetAdapterIndex,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(ID3D11Device*,SDL_GetRenderD3D11Device,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(IDirect3DDevice9*,SDL_GetRenderD3D9Device,(SDL_Renderer *a),(a),return) -#endif -#ifdef __GDK__ SDL_DYNAPI_PROC(int,SDL_GDKGetTaskQueue,(XTaskQueueHandle *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),) -#endif -#ifdef __WINRT__ SDL_DYNAPI_PROC(SDL_WinRT_DeviceFamily,SDL_WinRTGetDeviceFamily,(void),(),return) SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return) -#endif -#ifdef __LINUX__ SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriority,(Sint64 a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return) -#endif -#ifdef __IOS__ SDL_DYNAPI_PROC(void,SDL_OnApplicationDidChangeStatusBarOrientation,(void),(),) SDL_DYNAPI_PROC(int,SDL_iPhoneSetAnimationCallback,(SDL_Window *a, int b, void (SDLCALL *c)(void *), void *d),(a,b,c,d),return) SDL_DYNAPI_PROC(void,SDL_iPhoneSetEventPump,(SDL_bool a),(a),) -#endif -#ifdef __ANDROID__ SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),) SDL_DYNAPI_PROC(void*,SDL_AndroidGetActivity,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_AndroidGetExternalStoragePath,(void),(),return) @@ -115,7 +102,6 @@ SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return) -#endif SDL_DYNAPI_PROC(void,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return) @@ -966,9 +952,9 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32LE,(SDL_RWops *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32BE,(SDL_RWops *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64LE,(SDL_RWops *a, Sint64 b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64BE,(SDL_RWops *a, Sint64 b),(a,b),return) -#ifdef __GDK__ + SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return) -#endif + SDL_DYNAPI_PROC(int,SDL_SetWindowFocusable,(SDL_Window *a, SDL_bool b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) diff --git a/src/dynapi/SDL_dynapi_unsupported.h b/src/dynapi/SDL_dynapi_unsupported.h new file mode 100644 index 0000000000000..40c1feee166cc --- /dev/null +++ b/src/dynapi/SDL_dynapi_unsupported.h @@ -0,0 +1,48 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_dynapi_unsupported_h_ +#define SDL_dynapi_unsupported_h_ + + +#if !(defined(__WIN32__) || defined(__GDK__)) +typedef struct ID3D12Device ID3D12Device; +typedef void *SDL_WindowsMessageHook; +#endif + +#if !(defined(__WIN32__) || defined(__WINGDK__)) +typedef struct ID3D11Device ID3D11Device; +typedef struct IDirect3DDevice9 IDirect3DDevice9; +#endif + +#ifndef __GDK__ +typedef struct XTaskQueueHandle XTaskQueueHandle; +#endif + +#ifndef __WINRT__ +typedef int SDL_WinRT_DeviceFamily; +typedef int SDL_WinRT_Path; +#endif +#ifndef __GDK__ +typedef struct XUserHandle XUserHandle; +#endif + +#endif From b79db0a6eada9c64a9eb290b60af8dadc5496ffd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Oct 2023 06:22:34 -0700 Subject: [PATCH 068/725] Fixed potential wraparound issue with property IDs --- src/SDL_properties.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 29dd2391e130c..6fa46fbf32c78 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -124,7 +124,11 @@ SDL_PropertiesID SDL_CreateProperties(void) } if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) { - props = ++SDL_last_properties_id; + ++SDL_last_properties_id; + if (SDL_last_properties_id == 0) { + ++SDL_last_properties_id; + } + props = SDL_last_properties_id; if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { inserted = SDL_TRUE; } From e152129787e85902dd509766f7ffa475eb7bf71d Mon Sep 17 00:00:00 2001 From: kanjitalk755 Date: Sat, 9 Sep 2023 09:10:06 +0900 Subject: [PATCH 069/725] Fixes #8190. From #7249, reverted the hunks other than #7239. --- src/video/cocoa/SDL_cocoamouse.m | 14 +++++--------- src/video/cocoa/SDL_cocoawindow.m | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index fc29c5a59c673..2231ce7dcf393 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -219,15 +219,11 @@ static int Cocoa_ShowCursor(SDL_Cursor *cursor) SDL_VideoDevice *device = SDL_GetVideoDevice(); SDL_Window *window = (device ? device->windows : NULL); for (; window != NULL; window = window->next) { - SDL_Mouse *mouse = SDL_GetMouse(); - if(mouse->focus) { - if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) { - [(__bridge NSCursor*)mouse->cur_cursor->driverdata set]; - } else { - [[NSCursor invisibleCursor] set]; - } - } else { - [[NSCursor arrowCursor] set]; + SDL_CocoaWindowData *driverdata = (__bridge SDL_CocoaWindowData *)window->driverdata; + if (driverdata) { + [driverdata.nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:) + withObject:[driverdata.nswindow contentView] + waitUntilDone:NO]; } } return 0; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index ce110528c73b9..f86027e0e768b 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1727,6 +1727,21 @@ - (BOOL)mouseDownCanMoveWindow return YES; } +- (void)resetCursorRects +{ + SDL_Mouse *mouse; + [super resetCursorRects]; + mouse = SDL_GetMouse(); + + if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) { + [self addCursorRect:[self bounds] + cursor:(__bridge NSCursor *)mouse->cur_cursor->driverdata]; + } else { + [self addCursorRect:[self bounds] + cursor:[NSCursor invisibleCursor]]; + } +} + - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { if (SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)) { From 72034b9a07776e26cc2c83f519549c457c3452f7 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 12 Oct 2023 11:54:18 -0400 Subject: [PATCH 070/725] wayland: Fix primary selection handling when the protocol isn't supported The primary selection protocol is optional, so the function pointers to the internal Wayland functions should only be set if the protocol is supported. This allows graceful fall-back to the generic SDL implementation in other cases. Fixes the clipboard tests under Weston. --- src/video/wayland/SDL_waylandclipboard.c | 2 +- src/video/wayland/SDL_waylandvideo.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c index 0346b2cf5437a..75c358809c186 100644 --- a/src/video/wayland/SDL_waylandclipboard.c +++ b/src/video/wayland/SDL_waylandclipboard.c @@ -107,7 +107,7 @@ int Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text) { SDL_VideoData *video_data = _this->driverdata; SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL; - int status = 0; + int status = -1; if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) { primary_selection_device = video_data->input->primary_selection_device; diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 09b8368081113..92f03263d93e9 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -230,9 +230,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) device->SetClipboardData = Wayland_SetClipboardData; device->GetClipboardData = Wayland_GetClipboardData; device->HasClipboardData = Wayland_HasClipboardData; - device->SetPrimarySelectionText = Wayland_SetPrimarySelectionText; - device->GetPrimarySelectionText = Wayland_GetPrimarySelectionText; - device->HasPrimarySelectionText = Wayland_HasPrimarySelectionText; device->StartTextInput = Wayland_StartTextInput; device->StopTextInput = Wayland_StopTextInput; device->SetTextInputRect = Wayland_SetTextInputRect; @@ -912,6 +909,12 @@ int Wayland_VideoInit(SDL_VideoDevice *_this) Wayland_InitKeyboard(_this); + if (data->primary_selection_device_manager) { + _this->SetPrimarySelectionText = Wayland_SetPrimarySelectionText; + _this->GetPrimarySelectionText = Wayland_GetPrimarySelectionText; + _this->HasPrimarySelectionText = Wayland_HasPrimarySelectionText; + } + data->initializing = SDL_FALSE; return 0; From d18f910248e0d0ba430fc2d2b1fc2c53f648c12f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Oct 2023 11:38:14 -0700 Subject: [PATCH 071/725] testffmpeg: added the ability to specify audio and video codecs --- test/testffmpeg.c | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 6142c1f562667..80a1dd6d9c81a 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -406,6 +406,11 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) Uint32 texture_format = SDL_PIXELFORMAT_UNKNOWN; Uint32 frame_format = GetTextureFormat(frame->format); + if (frame_format == SDL_PIXELFORMAT_UNKNOWN) { + SDL_SetError("Unknown pixel format: %s", av_get_pix_fmt_name(frame->format)); + return SDL_FALSE; + } + if (*texture) { SDL_QueryTexture(*texture, &texture_format, NULL, &texture_width, &texture_height); } @@ -602,7 +607,10 @@ static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) static void DisplayVideoTexture(AVFrame *frame) { /* Update the video texture */ - GetTextureForFrame(frame, &video_texture); + if (!GetTextureForFrame(frame, &video_texture)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't get texture for frame: %s\n", SDL_GetError()); + return; + } if (frame->linesize[0] < 0) { SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, SDL_FLIP_VERTICAL); @@ -777,8 +785,10 @@ int main(int argc, char *argv[]) AVFormatContext *ic = NULL; int audio_stream = -1; int video_stream = -1; - const AVCodec *audio_decoder = NULL; - const AVCodec *video_decoder = NULL; + const char *audio_codec_name = NULL; + const char *video_codec_name = NULL; + const AVCodec *audio_codec = NULL; + const AVCodec *video_codec = NULL; AVCodecContext *audio_context = NULL; AVCodecContext *video_context = NULL; AVPacket *pkt = NULL; @@ -808,6 +818,12 @@ int main(int argc, char *argv[]) if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) { num_sprites = SDL_atoi(argv[i+1]); consumed = 2; + } else if (SDL_strcmp(argv[i], "--audio-codec") == 0 && argv[i+1]) { + audio_codec_name = argv[i+1]; + consumed = 2; + } else if (SDL_strcmp(argv[i], "--video-codec") == 0 && argv[i+1]) { + video_codec_name = argv[i+1]; + consumed = 2; } else if (SDL_strcmp(argv[i], "--software") == 0) { software_only = SDL_TRUE; consumed = 1; @@ -877,17 +893,33 @@ int main(int argc, char *argv[]) return_code = 4; goto quit; } - video_stream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, &video_decoder, 0); + video_stream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, &video_codec, 0); if (video_stream >= 0) { - video_context = OpenVideoStream(ic, video_stream, video_decoder); + if (video_codec_name) { + video_codec = avcodec_find_decoder_by_name(video_codec_name); + if (!video_codec) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find codec '%s'", video_codec_name); + return_code = 4; + goto quit; + } + } + video_context = OpenVideoStream(ic, video_stream, video_codec); if (!video_context) { return_code = 4; goto quit; } } - audio_stream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, video_stream, &audio_decoder, 0); + audio_stream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, video_stream, &audio_codec, 0); if (audio_stream >= 0) { - audio_context = OpenAudioStream(ic, audio_stream, audio_decoder); + if (audio_codec_name) { + audio_codec = avcodec_find_decoder_by_name(audio_codec_name); + if (!audio_codec) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find codec '%s'", audio_codec_name); + return_code = 4; + goto quit; + } + } + audio_context = OpenAudioStream(ic, audio_stream, audio_codec); if (!audio_context) { return_code = 4; goto quit; From ac71831350cd97bd4b240d6fbf5daf37c9e720a2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 12 Oct 2023 15:20:53 -0400 Subject: [PATCH 072/725] Sync wiki -> headers --- include/SDL3/SDL_audio.h | 3 ++- include/SDL3/SDL_gamepad.h | 3 ++- include/SDL3/SDL_joystick.h | 3 ++- include/SDL3/SDL_properties.h | 22 +++++++++++++--------- include/SDL3/SDL_render.h | 6 ++++-- include/SDL3/SDL_rwops.h | 3 ++- include/SDL3/SDL_sensor.h | 3 ++- include/SDL3/SDL_surface.h | 3 ++- include/SDL3/SDL_video.h | 3 ++- 9 files changed, 31 insertions(+), 18 deletions(-) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 481bfc599a385..952d958a4fdb3 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -680,7 +680,8 @@ extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(const SDL_AudioSp * Get the properties associated with an audio stream. * * \param stream the SDL_AudioStream to query - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index bb950272f37ba..5f409432d9688 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -562,7 +562,8 @@ extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromPlayerIndex(int player_in * * \param gamepad a gamepad identifier previously returned by * SDL_OpenGamepad() - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index e3c9a9f8cf94d..7b73537f6414d 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -461,7 +461,8 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, in * Get the properties associated with a joystick. * * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index efa700ee9e98f..4c1335fb737fb 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -42,7 +42,8 @@ typedef Uint32 SDL_PropertiesID; /** * Create a set of properties * - * \returns an ID for a new set of properties, or 0 on failure; call SDL_GetError() for more information. + * \returns an ID for a new set of properties, or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -53,12 +54,16 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); /** * Lock a set of properties * - * Obtain a multi-threaded lock for these properties. Other threads will wait while trying to lock these properties until they are unlocked. Properties must be unlocked before they are destroyed. + * Obtain a multi-threaded lock for these properties. Other threads will wait + * while trying to lock these properties until they are unlocked. Properties + * must be unlocked before they are destroyed. * - * The lock is automatically taken when setting individual properties, this function is only needed when you want to set several properties atomically or want to guarantee that properties being queried aren't freed in another thread. + * The lock is automatically taken when setting individual properties, this + * function is only needed when you want to set several properties atomically + * or want to guarantee that properties being queried aren't freed in another + * thread. * * \param props the properties to lock - * * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * @@ -85,9 +90,9 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); * \param props the properties to modify * \param name the name of the property to modify * \param value the new value of the property, or NULL to delete the property - * \param cleanup the function to call when this property is deleted, or NULL if no cleanup is necessary + * \param cleanup the function to call when this property is deleted, or NULL + * if no cleanup is necessary * \param userdata a pointer that is passed to the cleanup function - * * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * @@ -102,7 +107,6 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * * \param props the properties to query * \param name the name of the property to query - * * \returns the value of the property, or NULL if it is not set. * * \since This function is available since SDL 3.0.0. @@ -116,7 +120,6 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char * * \param props the properties to modify * \param name the name of the property to clear - * * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * @@ -129,7 +132,8 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char /** * Destroy a set of properties * - * All properties are deleted and their cleanup functions will be called, if any. The set of properties must be unlocked when it is destroyed. + * All properties are deleted and their cleanup functions will be called, if + * any. The set of properties must be unlocked when it is destroyed. * * \param props the properties to destroy * diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index ae08703697cf0..57f85fd3d6125 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -320,7 +320,8 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * Get the properties associated with a renderer. * * \param renderer the rendering context - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -440,7 +441,8 @@ extern DECLSPEC IDXGIResource* SDLCALL SDL_GetTextureDXGIResource(SDL_Texture *t * Get the properties associated with a texture. * * \param texture the texture to query - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 74c1ec6ec1872..26fd5299f471f 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -337,7 +337,8 @@ extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context); * Get the properties associated with an SDL_RWops. * * \param context a pointer to an SDL_RWops structure - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h index 4829bea472e9d..3c99f6825435b 100644 --- a/include/SDL3/SDL_sensor.h +++ b/include/SDL3/SDL_sensor.h @@ -194,7 +194,8 @@ extern DECLSPEC SDL_Sensor *SDLCALL SDL_GetSensorFromInstanceID(SDL_SensorID ins * Get the properties associated with a sensor. * * \param sensor The SDL_Sensor object - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 4a782175d564a..0cbf1eb9755ba 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -194,7 +194,8 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); * Get the properties associated with a surface. * * \param surface the SDL_Surface structure to query - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index c3958e37492d7..76b78ec9487ff 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -921,7 +921,8 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * Get the properties associated with a window. * * \param window the window to query - * \returns a valid property ID on success or 0 on failure; call SDL_GetError() for more information. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * From 516d6f9efc61bf38a1c79bf036954bdcb62a52f6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Oct 2023 14:08:46 -0700 Subject: [PATCH 073/725] testffmpeg: added support for YUVA formats using swscale Fixes https://github.com/libsdl-org/SDL/issues/8377 --- test/CMakeLists.txt | 1 + test/testffmpeg.c | 69 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 942400ff77ec2..4ce431e73feeb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -185,6 +185,7 @@ if(HAVE_LIBUDEV_H) add_definitions(-DHAVE_LIBUDEV_H) endif() +set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) include("${SDL3_SOURCE_DIR}/cmake/FindFFmpeg.cmake") if(FFmpeg_FOUND) cmake_push_check_state() diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 80a1dd6d9c81a..962e1c32a84c6 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef HAVE_EGL #include @@ -81,6 +82,11 @@ static ID3D11Device *d3d11_device; static ID3D11DeviceContext *d3d11_context; static const GUID SDL_IID_ID3D11Resource = { 0xdc8e63f3, 0xd12b, 0x4952, { 0xb4, 0x7b, 0x5e, 0x45, 0x02, 0x6a, 0x86, 0x2d } }; #endif +struct SwsContextContainer +{ + struct SwsContext *context; +}; +static const char *SWS_CONTEXT_CONTAINER_PROPERTY = "SWS_CONTEXT_CONTAINER"; static int done; static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) @@ -278,6 +284,13 @@ static enum AVPixelFormat GetSupportedPixelFormat(AVCodecContext *s, const enum const enum AVPixelFormat *p; for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); + + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + /* We support all memory formats using swscale */ + break; + } + if (SupportedPixelFormat(*p)) { /* We support this format */ break; @@ -341,7 +354,7 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV } #ifdef __WIN32__ - if (type == AV_HWDEVICE_TYPE_D3D11VA) { + if (d3d11_device && type == AV_HWDEVICE_TYPE_D3D11VA) { AVD3D11VADeviceContext *device_context; context->hw_device_ctx = av_hwdevice_ctx_alloc(type); @@ -400,32 +413,69 @@ static void SetYUVConversionMode(AVFrame *frame) SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */ } +static void SDLCALL FreeSwsContextContainer(void *userdata, void *value) +{ + struct SwsContextContainer *sws_container = (struct SwsContextContainer *)value; + if (sws_container->context) { + sws_freeContext(sws_container->context); + } + SDL_free(sws_container); +} + static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) { int texture_width = 0, texture_height = 0; Uint32 texture_format = SDL_PIXELFORMAT_UNKNOWN; Uint32 frame_format = GetTextureFormat(frame->format); - if (frame_format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("Unknown pixel format: %s", av_get_pix_fmt_name(frame->format)); - return SDL_FALSE; - } - if (*texture) { SDL_QueryTexture(*texture, &texture_format, NULL, &texture_width, &texture_height); } - if (!*texture || frame_format != texture_format || frame->width != texture_width || frame->height != texture_height) { + if (!*texture || texture_width != frame->width || texture_height != frame->height || + (frame_format != SDL_PIXELFORMAT_UNKNOWN && texture_format != frame_format) || + (frame_format == SDL_PIXELFORMAT_UNKNOWN && texture_format != SDL_PIXELFORMAT_ARGB8888)) { if (*texture) { SDL_DestroyTexture(*texture); } - *texture = SDL_CreateTexture(renderer, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + if (frame_format == SDL_PIXELFORMAT_UNKNOWN) { + *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + } else { + *texture = SDL_CreateTexture(renderer, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); + } if (!*texture) { return SDL_FALSE; } + SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_BLEND); } switch (frame_format) { + case SDL_PIXELFORMAT_UNKNOWN: + { + SDL_PropertiesID props = SDL_GetTextureProperties(*texture); + struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY); + if (!sws_container) { + sws_container = (struct SwsContextContainer *)SDL_calloc(1, sizeof(*sws_container)); + if (!sws_container) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + SDL_SetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL); + } + sws_container->context = sws_getCachedContext(sws_container->context, frame->width, frame->height, frame->format, frame->width, frame->height, AV_PIX_FMT_BGRA, SWS_POINT, NULL, NULL, NULL); + if (sws_container->context) { + uint8_t *pixels[4]; + int pitch[4]; + if (SDL_LockTexture(*texture, NULL, (void **)&pixels[0], &pitch[0]) == 0) { + sws_scale(sws_container->context, (const uint8_t * const *)frame->data, frame->linesize, 0, frame->height, pixels, pitch); + SDL_UnlockTexture(*texture); + } + } else { + SDL_SetError("Can't initialize the conversion context"); + return SDL_FALSE; + } + break; + } case SDL_PIXELFORMAT_IYUV: if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { SDL_UpdateYUVTexture(*texture, NULL, frame->data[0], frame->linesize[0], @@ -652,6 +702,9 @@ static void HandleVideoFrame(AVFrame *frame, double pts) now = (double)(SDL_GetTicks() - video_start) / 1000.0; } + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + DisplayVideoFrame(frame); /* Render any bouncing balls */ From f91bde64d5898f2980bd30ff1d1a62ea8e848e69 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Oct 2023 14:26:46 -0700 Subject: [PATCH 074/725] testffmpeg: Only enable blending if we're using a texture format that supports it --- test/testffmpeg.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 962e1c32a84c6..f5b3a7cc4aa27 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -119,9 +119,6 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) SDL_Log("Created renderer %s\n", info.name); } - /* Use linear scaling in case the user resizes the window */ - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - #ifdef HAVE_EGL if (useEGL) { const char *extensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); @@ -446,7 +443,13 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) if (!*texture) { return SDL_FALSE; } - SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_BLEND); + + if (frame_format == SDL_PIXELFORMAT_UNKNOWN || SDL_ISPIXELFORMAT_ALPHA(frame_format)) { + SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_BLEND); + } else { + SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE); + } + SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR); } switch (frame_format) { @@ -530,6 +533,8 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) if (!*texture) { return SDL_FALSE; } + SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE); + SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR); /* Bind the texture for importing */ SDL_GL_BindTexture(*texture, NULL, NULL); From 382751c4b5ef3fa1602ae67bd366d2982def7cba Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 13 Oct 2023 02:30:14 +0200 Subject: [PATCH 075/725] testffmpeg: print usage of options to change audio/video codec --- test/testffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index f5b3a7cc4aa27..cc75a5fa05efd 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -833,7 +833,7 @@ static void HandleAudioFrame(AVFrame *frame) } static void print_usage(SDLTest_CommonState *state, const char *argv0) { - static const char *options[] = { "[--sprites N]", "[--software]", "video_file", NULL }; + static const char *options[] = { "[--sprites N]", "[--audio-codec codec]", "[--video-codec codec]", "[--software]", "video_file", NULL }; SDLTest_CommonLogUsage(state, argv0, options); } From 9aeabb0b05e04b40cad9ccddd6b40a3de0ae3c54 Mon Sep 17 00:00:00 2001 From: kanjitalk755 Date: Fri, 13 Oct 2023 10:50:10 +0900 Subject: [PATCH 076/725] Fix macOS build error by #8269 --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index cc082179e3f58..279a74856b0ff 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -367,6 +367,10 @@ A7D8BBE923E2574800DCD162 /* SDL_uikitvulkan.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A62523E2513D00DCD162 /* SDL_uikitvulkan.m */; }; A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A62723E2513D00DCD162 /* SDL_uikitwindow.h */; }; A7D8BBEB23E2574800DCD162 /* SDL_uikitwindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A61A23E2513D00DCD162 /* SDL_uikitwindow.m */; }; + E4F7981A2AD8D84800669F54 /* SDL_core_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */; }; + E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */; }; + E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */; }; + E4F798202AD8D87F00669F54 /* SDL_video_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */; }; F31A92C828D4CB39003BFD6A /* SDL_offscreenopengles.h in Headers */ = {isa = PBXBuildFile; fileRef = F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */; }; F31A92D228D4CB39003BFD6A /* SDL_offscreenopengles.c in Sources */ = {isa = PBXBuildFile; fileRef = F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */; }; F32305FF28939F6400E66D30 /* SDL_hidapi_combined.c in Sources */ = {isa = PBXBuildFile; fileRef = F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */; }; @@ -847,6 +851,10 @@ BECDF66B0761BA81005FE872 /* Info-Framework.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = ""; }; BECDF66C0761BA81005FE872 /* SDL3.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL3.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2D187D228A5673500D2B4F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_core_unsupported.c; sourceTree = ""; }; + E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_unsupported.h; sourceTree = ""; }; + E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_unsupported.c; sourceTree = ""; }; + E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_unsupported.c; sourceTree = ""; }; F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenopengles.h; sourceTree = ""; }; F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenopengles.c; sourceTree = ""; }; F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_combined.c; sourceTree = ""; }; @@ -1321,6 +1329,7 @@ A7D8A5DB23E2513D00DCD162 /* SDL_dynapi_procs.h */, A7D8A5DA23E2513D00DCD162 /* SDL_dynapi.c */, A7D8A5D823E2513D00DCD162 /* SDL_dynapi.h */, + E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */, ); path = dynapi; sourceTree = ""; @@ -1390,6 +1399,7 @@ A7D8A61423E2513D00DCD162 /* SDL_surface.c */, A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */, A7D8A60E23E2513D00DCD162 /* SDL_video.c */, + E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */, A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */, A7D8A64023E2513D00DCD162 /* SDL_vulkan_utils.c */, A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */, @@ -1879,6 +1889,7 @@ A7D8A8FF23E2514000DCD162 /* SDL_d3dmath.c */, A7D8A8DC23E2514000DCD162 /* SDL_d3dmath.h */, A7D8A8DB23E2514000DCD162 /* SDL_render.c */, + E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */, A7D8A8EE23E2514000DCD162 /* SDL_sysrender.h */, A7D8A8EC23E2514000DCD162 /* SDL_yuv_sw_c.h */, A7D8A8ED23E2514000DCD162 /* SDL_yuv_sw.c */, @@ -2014,6 +2025,7 @@ F36C7ACF294B9F5E004D61C3 /* core */ = { isa = PBXGroup; children = ( + E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */, F36C7AD0294BA009004D61C3 /* SDL_runapp.c */, ); path = core; @@ -2162,6 +2174,7 @@ F3F7D9C92933074E00816151 /* SDL_opengl.h in Headers */, F3F7D9452933074E00816151 /* SDL_opengl_glext.h in Headers */, F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */, + E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */, F3F7D95D2933074E00816151 /* SDL_opengles.h in Headers */, F3F7D9612933074E00816151 /* SDL_opengles2.h in Headers */, F3F7D8FD2933074E00816151 /* SDL_opengles2_gl2.h in Headers */, @@ -2537,6 +2550,7 @@ A7D8B79A23E2514400DCD162 /* SDL_dummyaudio.c in Sources */, A7D8B3A423E2514200DCD162 /* SDL_fillrect.c in Sources */, A7D8ABDF23E2514100DCD162 /* SDL_nullframebuffer.c in Sources */, + E4F7981A2AD8D84800669F54 /* SDL_core_unsupported.c in Sources */, A7D8A96923E2514000DCD162 /* SDL_dummysensor.c in Sources */, A7D8B95C23E2514400DCD162 /* SDL_string.c in Sources */, A7D8BA7F23E2514400DCD162 /* SDL_render_gl.c in Sources */, @@ -2557,6 +2571,7 @@ A7D8B55123E2514300DCD162 /* SDL_hidapi_switch.c in Sources */, A7D8B96223E2514400DCD162 /* SDL_strtokr.c in Sources */, A7D8BB7523E2514500DCD162 /* SDL_clipboardevents.c in Sources */, + E4F798202AD8D87F00669F54 /* SDL_video_unsupported.c in Sources */, A1BB8B6327F6CF330057CFA8 /* SDL_list.c in Sources */, A7D8BAB523E2514400DCD162 /* k_cos.c in Sources */, A7D8B54523E2514300DCD162 /* SDL_hidapijoystick.c in Sources */, @@ -2576,6 +2591,7 @@ A7D8BBD523E2574800DCD162 /* SDL_uikitclipboard.m in Sources */, A7D8B5C923E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */, F386F6F92884663E001840AA /* SDL_utils.c in Sources */, + E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */, A7D8AC0F23E2514100DCD162 /* SDL_video.c in Sources */, A7D8BA5B23E2514400DCD162 /* SDL_shaders_gles2.c in Sources */, A7D8B14023E2514200DCD162 /* SDL_blit_1.c in Sources */, From 95a9271dbfb2d1348ba8350ba608d9e6ff915bc1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 13 Oct 2023 14:14:56 -0400 Subject: [PATCH 077/725] audio: Never lock a device while holding the device_list_lock. Fixes various not-necessarily-corner cases ending in deadlock. --- src/audio/SDL_audio.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 0608de5de3171..9eae97b56dadb 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -453,15 +453,16 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) DisconnectLogicalAudioDevice(logdev); } } - SDL_UnlockMutex(device->lock); // make sure nothing else is messing with the device before continuing. + SDL_UnlockMutex(device->lock); return; // done for now. Come back when a new default device is chosen! } SDL_bool was_live = SDL_FALSE; + SDL_LockMutex(device->lock); // make sure nothing else is messing with the device before continuing. + // take it out of the device list. SDL_LockRWLockForWriting(current_audio.device_list_lock); - SDL_LockMutex(device->lock); // make sure nothing else is messing with the device before continuing. if (device == current_audio.output_devices) { SDL_assert(device->prev == NULL); current_audio.output_devices = device->next; @@ -487,10 +488,12 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) SDL_AtomicAdd(device->iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count, -1); } + // Mark device as condemned now that it's not in the device list. + SDL_AtomicSet(&device->condemned, 1); + SDL_UnlockRWLock(current_audio.device_list_lock); // now device is not in the list, and we own it, so no one should be able to find it again, except the audio thread, which holds a pointer! - SDL_AtomicSet(&device->condemned, 1); SDL_AtomicSet(&device->shutdown, 1); // tell audio thread to terminate. // disconnect each attached logical device, so apps won't find their streams still bound if they get the REMOVED event before the device thread cleans up. @@ -1115,8 +1118,29 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid) const SDL_bool iscapture = (devid & (1<<0)) ? SDL_FALSE : SDL_TRUE; SDL_LockRWLockForReading(current_audio.device_list_lock); + SDL_bool isstack = SDL_FALSE; + const int num_devices = SDL_AtomicGet(iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count); + SDL_AudioDevice **devices = NULL; + + if (num_devices) { + devices = SDL_small_alloc(SDL_AudioDevice *, num_devices, &isstack); + if (!devices) { + SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_OutOfMemory(); + return NULL; + } else { + int i = 0; + for (SDL_AudioDevice *device = iscapture ? current_audio.capture_devices : current_audio.output_devices; device != NULL; device = device->next) { + SDL_assert(i < num_devices); + devices[i++] = device; + } + SDL_assert(i == num_devices); + } + } + SDL_UnlockRWLock(current_audio.device_list_lock); - for (SDL_AudioDevice *device = iscapture ? current_audio.capture_devices : current_audio.output_devices; device != NULL; device = device->next) { + for (int i = 0; i < num_devices; i++) { + SDL_AudioDevice *device = devices[i]; SDL_LockMutex(device->lock); // caller must unlock if we choose a logical device from this guy. SDL_assert(!SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. for (logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { @@ -1130,7 +1154,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid) SDL_UnlockMutex(device->lock); // give up this lock and try the next physical device. } - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_small_free(devices, isstack); } if (!logdev) { @@ -1167,7 +1191,6 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) for (dev = iscapture ? current_audio.capture_devices : current_audio.output_devices; dev != NULL; dev = dev->next) { if (dev->instance_id == devid) { // found it? - SDL_LockMutex(dev->lock); // caller must unlock. SDL_assert(!SDL_AtomicGet(&dev->condemned)); // shouldn't be in the list if pending deletion. break; } @@ -1177,6 +1200,8 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) if (!dev) { SDL_SetError("Invalid audio device instance ID"); + } else { + SDL_LockMutex(dev->lock); // caller must unlock. } return dev; From 0aba2c97db60e074323f7f86a73e1b1c16d32197 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 13:23:03 -0400 Subject: [PATCH 078/725] hashtable: SDL_IterateHashTable might as well provide both key and value. And SDL_IterateHashTableKey is only necessary for stackable hashtables, since non-stackable ones can either iterate each unique key/value pair with SDL_IterateHashTable, or get a specific key/value pair by using SDL_FindInHashTable. --- src/SDL_hashtable.c | 10 ++++++---- src/SDL_hashtable.h | 7 +++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index a5fc0f09e67b8..e2714d1321497 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -161,9 +161,9 @@ SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key) return SDL_FALSE; } -SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const void **_value, void **iter) +SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter) { - SDL_HashItem *item = iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)]; + SDL_HashItem *item = *iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)]; while (item != NULL) { if (table->keymatch(key, item->key, table->data)) { @@ -180,7 +180,7 @@ SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const return SDL_FALSE; } -SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, void **iter) +SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter) { SDL_HashItem *item = (SDL_HashItem *) *iter; Uint32 idx = 0; @@ -189,7 +189,7 @@ SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, const SDL_HashItem *orig = item; item = item->next; if (item == NULL) { - idx = calc_hash(table, orig->key) + 1; + idx = calc_hash(table, orig->key) + 1; // !!! FIXME: we probably shouldn't rehash each time. } } @@ -204,7 +204,9 @@ SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, } *_key = item->key; + *_value = item->value; *iter = item; + return SDL_TRUE; } diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h index eb8d7ba3ca39a..44a1788724064 100644 --- a/src/SDL_hashtable.h +++ b/src/SDL_hashtable.h @@ -42,8 +42,11 @@ SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); SDL_bool SDL_HashTableEmpty(SDL_HashTable *table); -SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void *key, const void **_value, void **iter); -SDL_bool SDL_IterateHashTableKeys(const SDL_HashTable *table, const void **_key, void **iter); +// iterate all values for a specific key. This only makes sense if the hash is stackable. If not-stackable, just use SDL_FindInHashTable(). +SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter); + +// iterate all key/value pairs in a hash (stackable hashes can have duplicate keys with multiple values). +SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter); Uint32 SDL_HashString(const void *key, void *unused); SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *unused); From 7f408e57eeb3f194bd7ffaecfc08e1560f2ddc87 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 13:26:37 -0400 Subject: [PATCH 079/725] audio: Keep all available devices in a hashtable instead of linked lists. All devices are in a single hash, whether playback or capture, or physical or logical. Lookups are keyed on device ID and map to either `SDL_AudioDevice *` for physical devices or `SDL_LogicalAudioDevice *` for logical devices (as an implementation detail, you can determine which object type you have by checking a specific bit in the device ID). This simplifies a bunch of code, makes some cases significantly more efficient, and solves the problem of having to lock each physical device while the device list rwlock is held to find logical devices by ID. Device IDs hash perfectly evenly, too, being incrementing integers. --- src/audio/SDL_audio.c | 385 ++++++++++++++++++--------------------- src/audio/SDL_sysaudio.h | 13 +- 2 files changed, 182 insertions(+), 216 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 9eae97b56dadb..3daa1b451e612 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -144,16 +144,16 @@ void OnAudioStreamCreated(SDL_AudioStream *stream) // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! // You must explicitly destroy it yourself! - if (current_audio.device_list_lock) { + if (current_audio.device_hash_lock) { // this isn't really part of the "device list" but it's a convenient lock to use here. - SDL_LockRWLockForWriting(current_audio.device_list_lock); + SDL_LockRWLockForWriting(current_audio.device_hash_lock); if (current_audio.existing_streams) { current_audio.existing_streams->prev = stream; } stream->prev = NULL; stream->next = current_audio.existing_streams; current_audio.existing_streams = stream; - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); } } @@ -164,9 +164,9 @@ void OnAudioStreamDestroy(SDL_AudioStream *stream) // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! // You must explicitly destroy it yourself! - if (current_audio.device_list_lock) { + if (current_audio.device_hash_lock) { // this isn't really part of the "device list" but it's a convenient lock to use here. - SDL_LockRWLockForWriting(current_audio.device_list_lock); + SDL_LockRWLockForWriting(current_audio.device_hash_lock); if (stream->prev) { stream->prev->next = stream->next; } @@ -176,7 +176,7 @@ void OnAudioStreamDestroy(SDL_AudioStream *stream) if (stream == current_audio.existing_streams) { current_audio.existing_streams = stream->next; } - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); } } @@ -237,28 +237,29 @@ static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) static void ClosePhysicalAudioDevice(SDL_AudioDevice *device); -// the loop in assign_audio_device_instance_id relies on this being true. SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_CAPTURE < SDL_AUDIO_DEVICE_DEFAULT_OUTPUT); -static SDL_AudioDeviceID assign_audio_device_instance_id(SDL_bool iscapture, SDL_bool islogical) +static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_bool islogical) { /* Assign an instance id! Start at 2, in case there are things from the SDL2 era that still think 1 is a special value. There's no reasonable scenario where this rolls over, but just in case, we wrap it in a loop. Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, etc. */ - // The bottom two bits of the instance id tells you if it's an output device (1<<0), and if it's a physical device (1<<1). Make sure these are right. - const SDL_AudioDeviceID required_mask = (iscapture ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); + // The bottom two bits of the instance id tells you if it's an output device (1<<0), and if it's a physical device (1<<1). + const SDL_AudioDeviceID flags = (iscapture ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); - SDL_AudioDeviceID instance_id; - do { - instance_id = (SDL_AudioDeviceID) (SDL_AtomicIncRef(¤t_audio.last_device_instance_id) + 1); - } while ( (instance_id < 2) || (instance_id >= SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) || ((instance_id & 0x3) != required_mask) ); + const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(¤t_audio.last_device_instance_id) + 1)) << 2) | flags; + SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) ); return instance_id; } // this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device! static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) { + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) logdev->instance_id); + SDL_UnlockRWLock(current_audio.device_hash_lock); + // remove ourselves from the physical device's list of logical devices. if (logdev->next) { logdev->next->prev = logdev->prev; @@ -310,13 +311,13 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) SDL_free(device); } -static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AudioDevice **devices, SDL_AtomicInt *device_count) +static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) { SDL_assert(name != NULL); - SDL_LockRWLockForReading(current_audio.device_list_lock); + SDL_LockRWLockForReading(current_audio.device_hash_lock); const int shutting_down = SDL_AtomicGet(¤t_audio.shutting_down); - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); if (shutting_down) { return NULL; // we're shutting down, don't add any devices that are hotplugged at the last possible moment. } @@ -350,20 +351,18 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq); device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); device->handle = handle; - device->prev = NULL; - - device->instance_id = assign_audio_device_instance_id(iscapture, /*islogical=*/SDL_FALSE); - SDL_LockRWLockForWriting(current_audio.device_list_lock); + device->instance_id = AssignAudioDeviceInstanceId(iscapture, /*islogical=*/SDL_FALSE); - if (*devices) { - SDL_assert((*devices)->prev == NULL); - (*devices)->prev = device; + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) { + SDL_AtomicAdd(device_count, 1); + } else { + SDL_free(device->name); + SDL_free(device); + device = NULL; } - device->next = *devices; - *devices = device; - SDL_AtomicAdd(device_count, 1); - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); return device; } @@ -371,12 +370,12 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc static SDL_AudioDevice *CreateAudioCaptureDevice(const char *name, const SDL_AudioSpec *spec, void *handle) { SDL_assert(current_audio.impl.HasCaptureSupport); - return CreatePhysicalAudioDevice(name, SDL_TRUE, spec, handle, ¤t_audio.capture_devices, ¤t_audio.capture_device_count); + return CreatePhysicalAudioDevice(name, SDL_TRUE, spec, handle, ¤t_audio.capture_device_count); } static SDL_AudioDevice *CreateAudioOutputDevice(const char *name, const SDL_AudioSpec *spec, void *handle) { - return CreatePhysicalAudioDevice(name, SDL_FALSE, spec, handle, ¤t_audio.output_devices, ¤t_audio.output_device_count); + return CreatePhysicalAudioDevice(name, SDL_FALSE, spec, handle, ¤t_audio.output_device_count); } // The audio backends call this when a new device is plugged in. @@ -462,27 +461,8 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) SDL_LockMutex(device->lock); // make sure nothing else is messing with the device before continuing. // take it out of the device list. - SDL_LockRWLockForWriting(current_audio.device_list_lock); - if (device == current_audio.output_devices) { - SDL_assert(device->prev == NULL); - current_audio.output_devices = device->next; - was_live = SDL_TRUE; - } else if (device == current_audio.capture_devices) { - SDL_assert(device->prev == NULL); - current_audio.capture_devices = device->next; - was_live = SDL_TRUE; - } - if (device->prev != NULL) { - device->prev->next = device->next; - was_live = SDL_TRUE; - } - if (device->next != NULL) { - device->next->prev = device->prev; - was_live = SDL_TRUE; - } - - device->next = NULL; - device->prev = NULL; + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + was_live = SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id); if (was_live) { SDL_AtomicAdd(device->iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count, -1); @@ -491,7 +471,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) // Mark device as condemned now that it's not in the device list. SDL_AtomicSet(&device->condemned, 1); - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); // now device is not in the list, and we own it, so no one should be able to find it again, except the audio thread, which holds a pointer! SDL_AtomicSet(&device->shutdown, 1); // tell audio thread to terminate. @@ -594,15 +574,42 @@ static void CompleteAudioEntryPoints(void) static SDL_AudioDeviceID GetFirstAddedAudioDeviceID(const SDL_bool iscapture) { - // (these are pushed to the front of the linked list as added, so the first device added is last in the list.) - SDL_LockRWLockForReading(current_audio.device_list_lock); - SDL_AudioDevice *last = NULL; - for (SDL_AudioDevice *i = iscapture ? current_audio.capture_devices : current_audio.output_devices; i != NULL; i = i->next) { - last = i; + SDL_AudioDeviceID retval = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_OUTPUT; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. + + // (Device IDs increase as new devices are added, so the first device added has the lowest SDL_AudioDeviceID value.) + SDL_LockRWLockForReading(current_audio.device_hash_lock); + + const void *key; + const void *value; + void *iter = NULL; + while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { + const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) value; + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + if (isphysical && (devid < retval)) { + retval = devid; + } } - const SDL_AudioDeviceID retval = last ? last->instance_id : 0; - SDL_UnlockRWLock(current_audio.device_list_lock); - return retval; + + SDL_UnlockRWLock(current_audio.device_hash_lock); + return (retval == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) ? 0 : retval; +} + +static Uint32 HashAudioDeviceID(const void *key, void *data) +{ + // shift right 2, to dump the first two bits, since these are flags + // (capture vs playback, logical vs physical) and the rest are unique incrementing integers. + return ((Uint32) ((uintptr_t) key)) >> 2; +} + +static SDL_bool MatchAudioDeviceID(const void *a, const void *b, void *data) +{ + return (a == b) ? SDL_TRUE : SDL_FALSE; // they're simple Uint32 values cast to pointers. +} + +static void NukeAudioDeviceHashItem(const void *key, const void *value, void *data) +{ + // no-op, keys and values in this hashtable are treated as Plain Old Data and don't get freed here. } // !!! FIXME: the video subsystem does SDL_VideoInit, not SDL_InitVideo. Make this match. @@ -615,11 +622,18 @@ int SDL_InitAudio(const char *driver_name) SDL_ChooseAudioConverters(); SDL_SetupAudioResampler(); - SDL_RWLock *device_list_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole audio subsystem. - if (!device_list_lock) { + SDL_RWLock *device_hash_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole audio subsystem. + if (!device_hash_lock) { + return -1; + } + + SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashAudioDeviceID, MatchAudioDeviceID, NukeAudioDeviceHashItem, SDL_FALSE); + if (!device_hash) { + SDL_DestroyRWLock(device_hash_lock); return -1; } + // Select the proper audio driver if (driver_name == NULL) { driver_name = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); @@ -633,7 +647,8 @@ int SDL_InitAudio(const char *driver_name) const char *driver_attempt = driver_name_copy; if (driver_name_copy == NULL) { - SDL_DestroyRWLock(device_list_lock); + SDL_DestroyRWLock(device_hash_lock); + SDL_DestroyHashTable(device_hash); return SDL_OutOfMemory(); } @@ -655,7 +670,8 @@ int SDL_InitAudio(const char *driver_name) tried_to_init = SDL_TRUE; SDL_zero(current_audio); SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. - current_audio.device_list_lock = device_list_lock; + current_audio.device_hash_lock = device_hash_lock; + current_audio.device_hash = device_hash; if (bootstrap[i]->init(¤t_audio.impl)) { current_audio.name = bootstrap[i]->name; current_audio.desc = bootstrap[i]->desc; @@ -678,7 +694,8 @@ int SDL_InitAudio(const char *driver_name) tried_to_init = SDL_TRUE; SDL_zero(current_audio); SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. - current_audio.device_list_lock = device_list_lock; + current_audio.device_hash_lock = device_hash_lock; + current_audio.device_hash = device_hash; if (bootstrap[i]->init(¤t_audio.impl)) { current_audio.name = bootstrap[i]->name; current_audio.desc = bootstrap[i]->desc; @@ -698,8 +715,10 @@ int SDL_InitAudio(const char *driver_name) } SDL_zero(current_audio); - SDL_DestroyRWLock(device_list_lock); - current_audio.device_list_lock = NULL; + SDL_DestroyRWLock(device_hash_lock); + SDL_DestroyHashTable(device_hash); + current_audio.device_hash_lock = NULL; + current_audio.device_hash = NULL; return -1; // No driver was available, so fail. } @@ -741,49 +760,29 @@ void SDL_QuitAudio(void) } // merge device lists so we don't have to duplicate work below. - SDL_LockRWLockForWriting(current_audio.device_list_lock); + SDL_LockRWLockForWriting(current_audio.device_hash_lock); SDL_AtomicSet(¤t_audio.shutting_down, 1); - SDL_AudioDevice *devices = NULL; - for (SDL_AudioDevice *i = current_audio.output_devices; i != NULL; i = i->next) { - devices = i; - } - if (!devices) { - devices = current_audio.capture_devices; - } else { - SDL_assert(devices->next == NULL); - devices->next = current_audio.capture_devices; - devices = current_audio.output_devices; - } - current_audio.output_devices = NULL; - current_audio.capture_devices = NULL; + SDL_HashTable *device_hash = current_audio.device_hash; + current_audio.device_hash = NULL; SDL_AtomicSet(¤t_audio.output_device_count, 0); SDL_AtomicSet(¤t_audio.capture_device_count, 0); - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); // mark all devices for shutdown so all threads can begin to terminate. - for (SDL_AudioDevice *i = devices; i != NULL; i = i->next) { - SDL_AtomicSet(&i->shutdown, 1); - } - - // now wait on any audio threads... - for (SDL_AudioDevice *i = devices; i != NULL; i = i->next) { - if (i->thread) { - SDL_assert(!SDL_AtomicGet(&i->condemned)); // these shouldn't have been in the device list still, and thread should have detached. - SDL_WaitThread(i->thread, NULL); - i->thread = NULL; - } - } - - while (devices) { - SDL_AudioDevice *next = devices->next; - DestroyPhysicalAudioDevice(devices); - devices = next; + const void *key; + const void *value; + void *iter = NULL; + while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { + SDL_AudioDevice *device = (SDL_AudioDevice *) value; + SDL_AtomicSet(&device->shutdown, 1); + DestroyPhysicalAudioDevice(device); } // Free the driver data current_audio.impl.Deinitialize(); - SDL_DestroyRWLock(current_audio.device_list_lock); + SDL_DestroyRWLock(current_audio.device_hash_lock); + SDL_DestroyHashTable(device_hash); SDL_zero(current_audio); } @@ -1060,31 +1059,44 @@ static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point } -static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_AudioDevice **devices, SDL_AtomicInt *device_count) +static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_bool iscapture) { if (!SDL_GetCurrentAudioDriver()) { SDL_SetError("Audio subsystem is not initialized"); return NULL; } - SDL_LockRWLockForReading(current_audio.device_list_lock); - int num_devices = SDL_AtomicGet(device_count); - SDL_AudioDeviceID *retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); - if (retval == NULL) { - num_devices = 0; - SDL_OutOfMemory(); - } else { - const SDL_AudioDevice *dev = *devices; // pointer to a pointer so we can dereference it after the lock is held. - for (int i = 0; i < num_devices; i++) { - SDL_assert(dev != NULL); - SDL_assert(!SDL_AtomicGet((SDL_AtomicInt *) &dev->condemned)); // shouldn't be in the list if pending deletion. - retval[i] = dev->instance_id; - dev = dev->next; + SDL_AudioDeviceID *retval = NULL; + + SDL_LockRWLockForReading(current_audio.device_hash_lock); + int num_devices = SDL_AtomicGet(iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count); + if (num_devices > 0) { + retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); + if (retval == NULL) { + num_devices = 0; + SDL_OutOfMemory(); + } else { + int devs_seen = 0; + const void *key; + const void *value; + void *iter = NULL; + while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { + const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; + // bit #0 of devid is set for output devices and unset for capture. + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_bool devid_iscapture = (devid & (1<<0)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + if (isphysical && (devid_iscapture == iscapture)) { + SDL_assert(devs_seen < num_devices); + retval[devs_seen++] = devid; + } + } + + SDL_assert(devs_seen == num_devices); + retval[devs_seen] = 0; // null-terminated. } - SDL_assert(dev == NULL); // did the whole list? - retval[num_devices] = 0; // null-terminated. } - SDL_UnlockRWLock(current_audio.device_list_lock); + SDL_UnlockRWLock(current_audio.device_hash_lock); if (reqcount != NULL) { *reqcount = num_devices; @@ -1095,12 +1107,12 @@ static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_AudioDevice **devic SDL_AudioDeviceID *SDL_GetAudioOutputDevices(int *count) { - return GetAudioDevices(count, ¤t_audio.output_devices, ¤t_audio.output_device_count); + return GetAudioDevices(count, SDL_FALSE); } SDL_AudioDeviceID *SDL_GetAudioCaptureDevices(int *count) { - return GetAudioDevices(count, ¤t_audio.capture_devices, ¤t_audio.capture_device_count); + return GetAudioDevices(count, SDL_TRUE); } // If found, this locks _the physical device_ this logical device is associated with, before returning. @@ -1113,52 +1125,18 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid) SDL_LogicalAudioDevice *logdev = NULL; + // bit #1 of devid is set for physical devices and unset for logical. const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; if (islogical) { // don't bother looking if it's not a logical device id value. - const SDL_bool iscapture = (devid & (1<<0)) ? SDL_FALSE : SDL_TRUE; - - SDL_LockRWLockForReading(current_audio.device_list_lock); - SDL_bool isstack = SDL_FALSE; - const int num_devices = SDL_AtomicGet(iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count); - SDL_AudioDevice **devices = NULL; - - if (num_devices) { - devices = SDL_small_alloc(SDL_AudioDevice *, num_devices, &isstack); - if (!devices) { - SDL_UnlockRWLock(current_audio.device_list_lock); - SDL_OutOfMemory(); - return NULL; - } else { - int i = 0; - for (SDL_AudioDevice *device = iscapture ? current_audio.capture_devices : current_audio.output_devices; device != NULL; device = device->next) { - SDL_assert(i < num_devices); - devices[i++] = device; - } - SDL_assert(i == num_devices); - } - } - SDL_UnlockRWLock(current_audio.device_list_lock); - - for (int i = 0; i < num_devices; i++) { - SDL_AudioDevice *device = devices[i]; - SDL_LockMutex(device->lock); // caller must unlock if we choose a logical device from this guy. - SDL_assert(!SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. - for (logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - if (logdev->instance_id == devid) { - break; // found it! - } - } - if (logdev != NULL) { - break; - } - SDL_UnlockMutex(device->lock); // give up this lock and try the next physical device. - } - - SDL_small_free(devices, isstack); + SDL_LockRWLockForReading(current_audio.device_hash_lock); + SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); + SDL_UnlockRWLock(current_audio.device_hash_lock); } if (!logdev) { SDL_SetError("Invalid audio device instance ID"); + } else { + SDL_LockMutex(logdev->physical_device->lock); } return logdev; @@ -1168,43 +1146,31 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid) Note that a logical device instance id will return its associated physical device! */ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) { + SDL_AudioDevice *device = NULL; + // bit #1 of devid is set for physical devices and unset for logical. const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; if (islogical) { SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); if (logdev) { - return logdev->physical_device; + device = logdev->physical_device; } - return NULL; - } - - if (!SDL_GetCurrentAudioDriver()) { + } else if (!SDL_GetCurrentAudioDriver()) { // (the `islogical` path, above, checks this in ObtainLogicalAudioDevice.) SDL_SetError("Audio subsystem is not initialized"); - return NULL; - } - - // bit #0 of devid is set for output devices and unset for capture. - const SDL_bool iscapture = (devid & (1<<0)) ? SDL_FALSE : SDL_TRUE; - SDL_AudioDevice *dev = NULL; - - SDL_LockRWLockForReading(current_audio.device_list_lock); + } else { + SDL_LockRWLockForReading(current_audio.device_hash_lock); + SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device); + SDL_assert(!device || !SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. + SDL_UnlockRWLock(current_audio.device_hash_lock); - for (dev = iscapture ? current_audio.capture_devices : current_audio.output_devices; dev != NULL; dev = dev->next) { - if (dev->instance_id == devid) { // found it? - SDL_assert(!SDL_AtomicGet(&dev->condemned)); // shouldn't be in the list if pending deletion. - break; + if (!device) { + SDL_SetError("Invalid audio device instance ID"); + } else { + SDL_LockMutex(device->lock); // caller must unlock. } } - SDL_UnlockRWLock(current_audio.device_list_lock); - - if (!dev) { - SDL_SetError("Invalid audio device instance ID"); - } else { - SDL_LockMutex(dev->lock); // caller must unlock. - } - - return dev; + return device; } SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata) @@ -1214,33 +1180,28 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_ return NULL; } - SDL_LockRWLockForReading(current_audio.device_list_lock); - - SDL_AudioDevice *dev = NULL; - for (dev = current_audio.output_devices; dev != NULL; dev = dev->next) { - if (callback(dev, userdata)) { // found it? - break; - } - } + const void *key; + const void *value; + void *iter = NULL; - if (!dev) { - // !!! FIXME: code duplication, from above. - for (dev = current_audio.capture_devices; dev != NULL; dev = dev->next) { - if (callback(dev, userdata)) { // found it? - break; + SDL_LockRWLockForReading(current_audio.device_hash_lock); + while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { + const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + if (isphysical) { + SDL_AudioDevice *device = (SDL_AudioDevice *) value; + SDL_assert(!SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. + if (callback(device, userdata)) { // found it? + SDL_UnlockRWLock(current_audio.device_hash_lock); + return device; } } } + SDL_UnlockRWLock(current_audio.device_hash_lock); - SDL_UnlockRWLock(current_audio.device_list_lock); - - if (!dev) { - SDL_SetError("Device not found"); - } - - SDL_assert(!dev || !SDL_AtomicGet(&dev->condemned)); // shouldn't be in the list if pending deletion. - - return dev; + SDL_SetError("Device not found"); + return NULL; } static SDL_bool TestDeviceHandleCallback(SDL_AudioDevice *device, void *handle) @@ -1535,7 +1496,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp SDL_free(logdev); } else { SDL_AtomicSet(&logdev->paused, 0); - retval = logdev->instance_id = assign_audio_device_instance_id(device->iscapture, /*islogical=*/SDL_TRUE); + retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->iscapture, /*islogical=*/SDL_TRUE); logdev->physical_device = device; logdev->opened_as_default = wants_default; logdev->next = device->logical_devices; @@ -1546,6 +1507,14 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp UpdateAudioStreamFormatsPhysical(device); } SDL_UnlockMutex(device->lock); + + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + const SDL_bool inserted = SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) retval, logdev); + SDL_UnlockRWLock(current_audio.device_hash_lock); + if (!inserted) { + SDL_CloseAudioDevice(retval); + retval = 0; + } } return retval; diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 043b562af3a12..334aed82e9a05 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -24,6 +24,8 @@ #ifndef SDL_sysaudio_h_ #define SDL_sysaudio_h_ +#include "../SDL_hashtable.h" + #define DEBUG_AUDIOSTREAM 0 #define DEBUG_AUDIO_CONVERT 0 @@ -142,7 +144,7 @@ typedef struct SDL_AudioDriverImpl SDL_bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore. SDL_bool HasCaptureSupport; SDL_bool OnlyHasDefaultOutputDevice; - SDL_bool OnlyHasDefaultCaptureDevice; + SDL_bool OnlyHasDefaultCaptureDevice; // !!! FIXME: is there ever a time where you'd have a default output and not a default capture (or vice versa)? } SDL_AudioDriverImpl; typedef struct SDL_AudioDriver @@ -150,9 +152,8 @@ typedef struct SDL_AudioDriver const char *name; // The name of this audio driver const char *desc; // The description of this audio driver SDL_AudioDriverImpl impl; // the backend's interface - SDL_RWLock *device_list_lock; // A mutex for device detection - SDL_AudioDevice *output_devices; // the list of currently-available audio output devices. - SDL_AudioDevice *capture_devices; // the list of currently-available audio capture devices. + SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash` + SDL_HashTable *device_hash; // the collection of currently-available audio devices (capture, playback, logical and physical!) SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams. SDL_AudioDeviceID default_output_device_id; SDL_AudioDeviceID default_capture_device_id; @@ -302,10 +303,6 @@ struct SDL_AudioDevice // All logical devices associated with this physical device. SDL_LogicalAudioDevice *logical_devices; - - // double-linked list of all physical devices. - struct SDL_AudioDevice *prev; - struct SDL_AudioDevice *next; }; typedef struct AudioBootStrap From b17151eb16e18354adc2412afb9c451f903188f5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 13:43:22 -0400 Subject: [PATCH 080/725] testaudio: Don't crash if renderer is NULL (happens during shutdown). --- test/testaudio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index 3cb71a764273f..1508098f2191c 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -416,11 +416,13 @@ static void DrawThings(SDL_Renderer *renderer) static void Draw(void) { SDL_Renderer *renderer = state->renderers[0]; - SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(renderer, 64, 0, 64, 255); - SDL_RenderClear(renderer); - DrawThings(renderer); - SDL_RenderPresent(renderer); + if (renderer) { /* might be NULL if we're shutting down. */ + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, 64, 0, 64, 255); + SDL_RenderClear(renderer); + DrawThings(renderer); + SDL_RenderPresent(renderer); + } } static void RepositionRowOfThings(const ThingType what, const float y) From 8ac5c84ad18205bd4708e54ea642629a96f37531 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 13:49:08 -0400 Subject: [PATCH 081/725] audio: device thread shouldn't touch `thread_alive` after object is free'd. Reference Issue #8386. --- src/audio/SDL_audio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 3daa1b451e612..a14bef9cc2e9d 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -790,15 +790,20 @@ void SDL_QuitAudio(void) void SDL_AudioThreadFinalize(SDL_AudioDevice *device) { - if (SDL_AtomicGet(&device->condemned)) { + const SDL_bool condemned = SDL_AtomicGet(&device->condemned) ? SDL_TRUE : SDL_FALSE; + if (condemned) { if (device->thread) { SDL_DetachThread(device->thread); // no one is waiting for us, just detach ourselves. device->thread = NULL; - SDL_AtomicSet(&device->thread_alive, 0); } - DestroyPhysicalAudioDevice(device); } + + // tell the world we're done touching this object (except if condemned, when we're the only thing that _can_ touch it). SDL_AtomicSet(&device->thread_alive, 0); + + if (condemned) { // nothing is coming to destroy this object, we have to do it as we exit. + DestroyPhysicalAudioDevice(device); + } } static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) From 66644377480887eeacafbccdba3b8a458fa696c9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 13:52:50 -0400 Subject: [PATCH 082/725] hashtable: Don't rearrange bucket elements during SDL_FindInHashTable. This is a race condition if the hashtable isn't protected by a mutex, and it makes a read/write operation out of something what appears to be read-only, which is dangerously surprising from an interface viewpoint. The downside is that if you have an item that is frequently accessed that isn't in the first slot of a bucket, each find operation will take longer instead of common items bubbling to the front of the bucket. Then again, if you have several common things being looked up in rotation, they'll just be doing unnecessary shuffling here. In this case, it might be better to just use a larger hashtable or a better hashing function (or just look up the thing you need once instead of multiple times). Fixes #8391. --- src/SDL_hashtable.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index e2714d1321497..5646a3717f305 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -116,16 +116,6 @@ SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const if (_value != NULL) { *_value = i->value; } - - /* Matched! Move to the front of list for faster lookup next time. - (stackable tables have to remain in the same order, though!) */ - if ((!table->stackable) && (prev != NULL)) { - SDL_assert(prev->next == i); - prev->next = i->next; - i->next = table->table[hash]; - table->table[hash] = i; - } - return SDL_TRUE; } From e526dc64bdd6fded52bd46afe503b827e062ea48 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 15 Oct 2023 01:36:49 +0200 Subject: [PATCH 083/725] Don't set unused variable --- src/SDL_hashtable.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 5646a3717f305..2bb36a5394757 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -108,7 +108,6 @@ SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const { const Uint32 hash = calc_hash(table, key); void *data = table->data; - SDL_HashItem *prev = NULL; SDL_HashItem *i; for (i = table->table[hash]; i != NULL; i = i->next) { @@ -118,8 +117,6 @@ SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const } return SDL_TRUE; } - - prev = i; } return SDL_FALSE; From b22ffb979725fe3b502e5e8eddbe71955c5adf74 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 23:10:50 -0400 Subject: [PATCH 084/725] audio: Fix some logic errors in the new device hashtable code. Fixes #8395. --- src/audio/SDL_audio.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index a14bef9cc2e9d..3321050d1d94a 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -256,9 +256,12 @@ static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_boo // this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device! static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) { - SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) logdev->instance_id); - SDL_UnlockRWLock(current_audio.device_hash_lock); + // Remove ourselves from the device_hash hashtable. + if (current_audio.device_hash) { // will be NULL while shutting down. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) logdev->instance_id); + SDL_UnlockRWLock(current_audio.device_hash_lock); + } // remove ourselves from the physical device's list of logical devices. if (logdev->next) { @@ -773,9 +776,14 @@ void SDL_QuitAudio(void) const void *value; void *iter = NULL; while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { - SDL_AudioDevice *device = (SDL_AudioDevice *) value; - SDL_AtomicSet(&device->shutdown, 1); - DestroyPhysicalAudioDevice(device); + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; + const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + if (isphysical) { + SDL_AudioDevice *device = (SDL_AudioDevice *) value; + SDL_AtomicSet(&device->shutdown, 1); + DestroyPhysicalAudioDevice(device); + } } // Free the driver data @@ -1513,12 +1521,14 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp } SDL_UnlockMutex(device->lock); - SDL_LockRWLockForWriting(current_audio.device_hash_lock); - const SDL_bool inserted = SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) retval, logdev); - SDL_UnlockRWLock(current_audio.device_hash_lock); - if (!inserted) { - SDL_CloseAudioDevice(retval); - retval = 0; + if (retval) { + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + const SDL_bool inserted = SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) retval, logdev); + SDL_UnlockRWLock(current_audio.device_hash_lock); + if (!inserted) { + SDL_CloseAudioDevice(retval); + retval = 0; + } } } From 1c6d996108997fc53109673948d2e2f4e80ff5d6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 14 Oct 2023 23:17:59 -0400 Subject: [PATCH 085/725] testaudio: if the SDL_Renderer is already gone, don't destroy SDL_Textures. --- test/testaudio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/testaudio.c b/test/testaudio.c index 1508098f2191c..83bdd4163e59f 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -732,7 +732,9 @@ static void LoadStockWavThings(void) static void DestroyTexture(Texture *tex) { if (tex) { - SDL_DestroyTexture(tex->texture); + if (state->renderers[0] != NULL) { /* if the renderer went away, this pointer is already bogus. */ + SDL_DestroyTexture(tex->texture); + } SDL_free(tex); } } From 8df68b4120488ade44e07330f0ea8ca19b195d7b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 15 Oct 2023 15:41:04 -0400 Subject: [PATCH 086/725] hashtable: Moved over to single-line comments. --- src/SDL_hashtable.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 2bb36a5394757..e3133fe8623cf 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -46,7 +46,7 @@ SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const S { SDL_HashTable *table; - /* num_buckets must be a power of two so we get a solid block of bits to mask hash values against. */ + // num_buckets must be a power of two so we get a solid block of bits to mask hash values against. if ((num_buckets == 0) || ((num_buckets & (num_buckets - 1)) != 0)) { SDL_SetError("num_buckets must be a power of two"); return NULL; @@ -89,7 +89,7 @@ SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const vo return SDL_FALSE; } - /* !!! FIXME: grow and rehash table if it gets too saturated. */ + // !!! FIXME: grow and rehash table if it gets too saturated. item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem)); if (item == NULL) { SDL_OutOfMemory(); @@ -161,7 +161,7 @@ SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, co item = item->next; } - /* no more matches. */ + // no more matches. *_value = NULL; *iter = NULL; return SDL_FALSE; @@ -181,10 +181,10 @@ SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, con } while (!item && (idx < table->table_len)) { - item = table->table[idx++]; /* skip empty buckets... */ + item = table->table[idx++]; // skip empty buckets... } - if (item == NULL) { /* no more matches? */ + if (item == NULL) { // no more matches? *_key = NULL; *iter = NULL; return SDL_FALSE; @@ -233,7 +233,7 @@ void SDL_DestroyHashTable(SDL_HashTable *table) } } -/* this is djb's xor hashing function. */ +// this is djb's xor hashing function. static SDL_INLINE Uint32 hash_string_djbxor(const char *str, size_t len) { Uint32 hash = 5381; @@ -252,14 +252,14 @@ Uint32 SDL_HashString(const void *key, void *data) SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) { if (a == b) { - return SDL_TRUE; /* same pointer, must match. */ + return SDL_TRUE; // same pointer, must match. } else if (!a || !b) { - return SDL_FALSE; /* one pointer is NULL (and first test shows they aren't the same pointer), must not match. */ + return SDL_FALSE; // one pointer is NULL (and first test shows they aren't the same pointer), must not match. } - return (SDL_strcmp((const char *)a, (const char *)b) == 0) ? SDL_TRUE : SDL_FALSE; /* Check against actual string contents. */ + return (SDL_strcmp((const char *)a, (const char *)b) == 0) ? SDL_TRUE : SDL_FALSE; // Check against actual string contents. } -/* We assume we can fit the ID in the key directly */ +// We assume we can fit the ID in the key directly SDL_COMPILE_TIME_ASSERT(SDL_HashID_KeySize, sizeof(Uint32) <= sizeof(const void *)); Uint32 SDL_HashID(const void *key, void *unused) From 6ddd96a4d07c2dd019626ab6365b0709978d496a Mon Sep 17 00:00:00 2001 From: Zhile Zhu <52572293+zhuzhile08@users.noreply.github.com> Date: Sun, 15 Oct 2023 17:09:11 +0200 Subject: [PATCH 087/725] Fix some wrong gamepad/controller event enums --- include/SDL3/SDL_oldnames.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index e5b5c9b567c4a..68f33080eabf6 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -524,16 +524,16 @@ #define SDL_AUDIODEVICEADDED SDL_AUDIODEVICEADDED_renamed_SDL_EVENT_AUDIO_DEVICE_ADDED #define SDL_AUDIODEVICEREMOVED SDL_AUDIODEVICEREMOVED_renamed_SDL_EVENT_AUDIO_DEVICE_REMOVED #define SDL_CLIPBOARDUPDATE SDL_CLIPBOARDUPDATE_renamed_SDL_EVENT_CLIPBOARD_UPDATE -#define SDL_CONTROLLERAXISMOTION SDL_CONTROLLERAXISMOTION_renamed_SDL_GAMEPADAXISMOTION -#define SDL_CONTROLLERBUTTONDOWN SDL_CONTROLLERBUTTONDOWN_renamed_SDL_GAMEPADBUTTONDOWN -#define SDL_CONTROLLERBUTTONUP SDL_CONTROLLERBUTTONUP_renamed_SDL_GAMEPADBUTTONUP +#define SDL_CONTROLLERAXISMOTION SDL_CONTROLLERAXISMOTION_renamed_SDL_EVENT_GAMEPAD_AXIS_MOTION +#define SDL_CONTROLLERBUTTONDOWN SDL_CONTROLLERBUTTONDOWN_renamed_SDL_EVENT_GAMEPAD_BUTTON_DOWN +#define SDL_CONTROLLERBUTTONUP SDL_CONTROLLERBUTTONUP_renamed_SDL_EVENT_GAMEPAD_BUTTON_UP #define SDL_CONTROLLERDEVICEADDED SDL_CONTROLLERDEVICEADDED_renamed_SDL_EVENT_GAMEPAD_ADDED #define SDL_CONTROLLERDEVICEREMAPPED SDL_CONTROLLERDEVICEREMAPPED_renamed_SDL_EVENT_GAMEPAD_REMAPPED #define SDL_CONTROLLERDEVICEREMOVED SDL_CONTROLLERDEVICEREMOVED_renamed_SDL_EVENT_GAMEPAD_REMOVED -#define SDL_CONTROLLERSENSORUPDATE SDL_CONTROLLERSENSORUPDATE_renamed_SDL_GAMEPADSENSORUPDATE -#define SDL_CONTROLLERTOUCHPADDOWN SDL_CONTROLLERTOUCHPADDOWN_renamed_SDL_GAMEPADTOUCHPADDOWN -#define SDL_CONTROLLERTOUCHPADMOTION SDL_CONTROLLERTOUCHPADMOTION_renamed_SDL_GAMEPADTOUCHPADMOTION -#define SDL_CONTROLLERTOUCHPADUP SDL_CONTROLLERTOUCHPADUP_renamed_SDL_GAMEPADTOUCHPADUP +#define SDL_CONTROLLERSENSORUPDATE SDL_CONTROLLERSENSORUPDATE_renamed_SDL_EVENT_GAMEPAD_SENSOR_UPDATE +#define SDL_CONTROLLERTOUCHPADDOWN SDL_CONTROLLERTOUCHPADDOWN_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN +#define SDL_CONTROLLERTOUCHPADMOTION SDL_CONTROLLERTOUCHPADMOTION_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION +#define SDL_CONTROLLERTOUCHPADUP SDL_CONTROLLERTOUCHPADUP_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_UP #define SDL_ControllerAxisEvent SDL_ControllerAxisEvent_renamed_SDL_GamepadAxisEvent #define SDL_ControllerButtonEvent SDL_ControllerButtonEvent_renamed_SDL_GamepadButtonEvent #define SDL_ControllerDeviceEvent SDL_ControllerDeviceEvent_renamed_SDL_GamepadDeviceEvent From a17f3ba916849ae926cd597d861f3d001f26f03c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 09:46:34 -0400 Subject: [PATCH 088/725] audio: Reworked audio device disconnect management. - No more tapdance to either join the audio device thread or have it detach itself. Significant simplication of and fixes to the locking code to prevent deadlocks. - Physical devices now keep a refcount. Each logical device increments it, as does the existence of a device thread, etc. Last unref destroys the device and takes it out of the device_hash. Since there's a lot of moving parts that might be holding a reference to a physical device, this seemed like a safer way to protect the object. - Disconnected devices now continue to function as zombie devices. Playback devices will still consume data (and just throw it away), and capture devices will continue to produce data (which always be silence). This helps apps that don't handle disconnect events; the device still stops playing/capturing, but bound audio streams will still consume data so they don't allocate more data infinitely, and apps that depend on an audio callback firing regularly to make progress won't hang. Please note that disconnected audio devices must now be explicitly closed! They always _should_ have been, but before this commit, SDL3 would destroy the disconnected device for you (and manually closing afterwards was a safe no-op). Reference Issue #8331. Fixes #8386. (and probably others). --- src/audio/SDL_audio.c | 333 ++++++++++++++++++++++----------------- src/audio/SDL_sysaudio.h | 17 +- 2 files changed, 199 insertions(+), 151 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 3321050d1d94a..7374f9d9bf059 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -220,6 +220,42 @@ static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) } +// Zombie device implementation... + +// These get used when a device is disconnected or fails, so audiostreams don't overflow with data that isn't being +// consumed and apps relying on audio callbacks don't stop making progress. +static int ZombieWaitDevice(SDL_AudioDevice *device) +{ + if (!SDL_AtomicGet(&device->shutdown)) { + const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); + SDL_Delay((frames * 1000) / device->spec.freq); + } + return 0; +} + +static int ZombiePlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +{ + return 0; // no-op, just throw the audio away. +} + +static Uint8 *ZombieGetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) +{ + return device->work_buffer; +} + +static int ZombieCaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +{ + // return a full buffer of silence every time. + SDL_memset(buffer, device->silence_value, buflen); + return buflen; +} + +static void ZombieFlushCapture(SDL_AudioDevice *device) +{ + // no-op, this is all imaginary. +} + + // device management and hotplug... @@ -254,6 +290,7 @@ static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_boo } // this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device! +// It also will not unref the physical device, since we might be shutting down; SDL_CloseAudioDevice handles the unref. static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) { // Remove ourselves from the device_hash hashtable. @@ -289,7 +326,7 @@ static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) SDL_free(logdev); } -// this must not be called while `device` is still in a device list, or while a device's audio thread is still running (except if the thread calls this while shutting down). */ +// this must not be called while `device` is still in a device list, or while a device's audio thread is still running. static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) { if (!device) { @@ -314,6 +351,25 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) SDL_free(device); } +// Don't hold the device lock when calling this, as we may destroy the device! +static void UnrefPhysicalAudioDevice(SDL_AudioDevice *device) +{ + if (SDL_AtomicDecRef(&device->refcount)) { + // take it out of the device list. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + if (SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id)) { + SDL_AtomicAdd(device->iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count, -1); + } + SDL_UnlockRWLock(current_audio.device_hash_lock); + DestroyPhysicalAudioDevice(device); // ...and nuke it. + } +} + +static void RefPhysicalAudioDevice(SDL_AudioDevice *device) +{ + SDL_AtomicIncRef(&device->refcount); +} + static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) { SDL_assert(name != NULL); @@ -346,7 +402,6 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc } SDL_AtomicSet(&device->shutdown, 0); - SDL_AtomicSet(&device->condemned, 0); SDL_AtomicSet(&device->zombie, 0); device->iscapture = iscapture; SDL_copyp(&device->spec, spec); @@ -367,6 +422,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc } SDL_UnlockRWLock(current_audio.device_hash_lock); + RefPhysicalAudioDevice(device); // deref'd on device disconnect. return device; } @@ -415,25 +471,6 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, return device; } -// this _also_ destroys the logical device! -static void DisconnectLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) -{ - SDL_assert(logdev != NULL); // currently, this is always true. - - const SDL_AudioDeviceID instance_id = logdev->instance_id; - const SDL_bool iscapture = logdev->physical_device->iscapture; - DestroyLogicalAudioDevice(logdev); - - if (SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED)) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_REMOVED; - event.adevice.which = instance_id; - event.adevice.iscapture = iscapture ? 1 : 0; - SDL_PushEvent(&event); - } -} - // Called when a device is removed from the system, or it fails unexpectedly, from any thread, possibly even the audio device's thread. void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) { @@ -441,72 +478,86 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) return; } - // if the current default device is going down, mark it as dead but keep it around until a replacement is decided upon, so we can migrate logical devices to it. - if ((device->instance_id == current_audio.default_output_device_id) || (device->instance_id == current_audio.default_capture_device_id)) { - SDL_LockMutex(device->lock); // make sure nothing else is messing with the device before continuing. - SDL_AtomicSet(&device->zombie, 1); - SDL_AtomicSet(&device->shutdown, 1); // tell audio thread to terminate, but don't mark it condemned, so the thread won't destroy the device. We'll join on the audio thread later. + SDL_LockMutex(device->lock); - // dump any logical devices that explicitly opened this device. Things that opened the system default can stay. - SDL_LogicalAudioDevice *next = NULL; - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = next) { - next = logdev->next; - if (!logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. - DisconnectLogicalAudioDevice(logdev); - } - } + if (!SDL_AtomicCAS(&device->zombie, 0, 1)) { SDL_UnlockMutex(device->lock); - return; // done for now. Come back when a new default device is chosen! - } - - SDL_bool was_live = SDL_FALSE; - - SDL_LockMutex(device->lock); // make sure nothing else is messing with the device before continuing. - - // take it out of the device list. - SDL_LockRWLockForWriting(current_audio.device_hash_lock); - was_live = SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id); - - if (was_live) { - SDL_AtomicAdd(device->iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count, -1); - } - - // Mark device as condemned now that it's not in the device list. - SDL_AtomicSet(&device->condemned, 1); + return; // already disconnected this device, don't do it twice. + } + + // Swap in "Zombie" versions of the usual platform interfaces, so the device will keep + // making progress until the app closes it. Otherwise, streams might continue to + // accumulate waste data that never drains, apps that depend on audio callbacks to + // progress will freeze, etc. + device->WaitDevice = ZombieWaitDevice; + device->GetDeviceBuf = ZombieGetDeviceBuf; + device->PlayDevice = ZombiePlayDevice; + device->WaitCaptureDevice = ZombieWaitDevice; + device->CaptureFromDevice = ZombieCaptureFromDevice; + device->FlushCapture = ZombieFlushCapture; + + const SDL_AudioDeviceID devid = device->instance_id; + const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)) ? SDL_TRUE : SDL_FALSE; + + // get a count of all devices currently attached. Save these off in an array so we can + // send events for each after we're done with the device lock, in case something tries + // to close a device from an event filter, as this would deadlock waiting on the device + // thread to join, which will be waiting for the device lock, too. + int total_devices = 0; + SDL_bool isstack = SDL_FALSE; + SDL_AudioDeviceID *devices = NULL; + if (SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED)) { + total_devices++; // count the physical device. + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + total_devices++; + } - SDL_UnlockRWLock(current_audio.device_hash_lock); + devices = SDL_small_alloc(SDL_AudioDeviceID, total_devices, &isstack); + int deviceidx = 0; - // now device is not in the list, and we own it, so no one should be able to find it again, except the audio thread, which holds a pointer! - SDL_AtomicSet(&device->shutdown, 1); // tell audio thread to terminate. + if (devices) { // if we ran out of memory, we won't send disconnect events, but you probably have deeper problems anyhow. + if (is_default_device) { + // dump any logical devices that explicitly opened this device. Things that opened the system default can stay. + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + if (!logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. + SDL_assert(deviceidx < total_devices); + devices[deviceidx++] = logdev->instance_id; + } + } + } else { + // report _all_ logical devices as disconnected. + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + SDL_assert(deviceidx < total_devices); + devices[deviceidx++] = logdev->instance_id; + } + } - // disconnect each attached logical device, so apps won't find their streams still bound if they get the REMOVED event before the device thread cleans up. - SDL_LogicalAudioDevice *next; - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = next) { - next = logdev->next; - DisconnectLogicalAudioDevice(logdev); + SDL_assert(deviceidx < total_devices); + devices[deviceidx++] = device->instance_id; + total_devices = deviceidx; + } } - // if there's an audio thread, don't free until thread is terminating, otherwise free stuff now. - const SDL_bool should_destroy = SDL_AtomicGet(&device->thread_alive) ? SDL_FALSE : SDL_TRUE; - - const SDL_AudioDeviceID instance_id = device->instance_id; - const SDL_bool iscapture = device->iscapture; - + // Let go of the lock before sending events, so an event filter trying to close a device won't deadlock with the device thread. SDL_UnlockMutex(device->lock); - if (should_destroy) { - DestroyPhysicalAudioDevice(device); + if (devices) { // NULL if event is disabled or disaster struck. + const Uint8 iscapture = device->iscapture ? 1 : 0; + for (int i = 0; i < total_devices; i++) { + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_AUDIO_DEVICE_REMOVED; + event.adevice.which = devices[i]; + event.adevice.iscapture = iscapture; + SDL_PushEvent(&event); + } + SDL_small_free(devices, isstack); } - // Post the event, if we haven't tried to before and if it's desired - if (was_live && SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED)) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_REMOVED; - event.common.timestamp = 0; - event.adevice.which = instance_id; - event.adevice.iscapture = iscapture ? 1 : 0; - SDL_PushEvent(&event); + // Is this a non-default device? We can unref it now. + // Otherwise, we'll unref it when a new default device is chosen. + if (!is_default_device) { + UnrefPhysicalAudioDevice(device); } } @@ -762,7 +813,6 @@ void SDL_QuitAudio(void) SDL_DestroyAudioStream(current_audio.existing_streams); } - // merge device lists so we don't have to duplicate work below. SDL_LockRWLockForWriting(current_audio.device_hash_lock); SDL_AtomicSet(¤t_audio.shutting_down, 1); SDL_HashTable *device_hash = current_audio.device_hash; @@ -771,7 +821,6 @@ void SDL_QuitAudio(void) SDL_AtomicSet(¤t_audio.capture_device_count, 0); SDL_UnlockRWLock(current_audio.device_hash_lock); - // mark all devices for shutdown so all threads can begin to terminate. const void *key; const void *value; void *iter = NULL; @@ -780,9 +829,7 @@ void SDL_QuitAudio(void) const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; if (isphysical) { - SDL_AudioDevice *device = (SDL_AudioDevice *) value; - SDL_AtomicSet(&device->shutdown, 1); - DestroyPhysicalAudioDevice(device); + DestroyPhysicalAudioDevice((SDL_AudioDevice *) value); } } @@ -798,20 +845,7 @@ void SDL_QuitAudio(void) void SDL_AudioThreadFinalize(SDL_AudioDevice *device) { - const SDL_bool condemned = SDL_AtomicGet(&device->condemned) ? SDL_TRUE : SDL_FALSE; - if (condemned) { - if (device->thread) { - SDL_DetachThread(device->thread); // no one is waiting for us, just detach ourselves. - device->thread = NULL; - } - } - - // tell the world we're done touching this object (except if condemned, when we're the only thing that _can_ touch it). - SDL_AtomicSet(&device->thread_alive, 0); - - if (condemned) { // nothing is coming to destroy this object, we have to do it as we exit. - DestroyPhysicalAudioDevice(device); - } + UnrefPhysicalAudioDevice(device); } static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) @@ -841,13 +875,13 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) return SDL_FALSE; // we're done, shut it down. } - SDL_bool retval = SDL_TRUE; + SDL_bool failed = SDL_FALSE; int buffer_size = device->buffer_size; - Uint8 *device_buffer = current_audio.impl.GetDeviceBuf(device, &buffer_size); + Uint8 *device_buffer = device->GetDeviceBuf(device, &buffer_size); if (buffer_size == 0) { // WASAPI (maybe others, later) does this to say "just abandon this iteration and try again next time." } else if (!device_buffer) { - retval = SDL_FALSE; + failed = SDL_TRUE; } else { SDL_assert(buffer_size <= device->buffer_size); // you can ask for less, but not more. SDL_assert(AudioDeviceCanUseSimpleCopy(device) == device->simple_copy); // make sure this hasn't gotten out of sync. @@ -862,7 +896,7 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) const int br = SDL_AtomicGet(&logdev->paused) ? 0 : SDL_GetAudioStreamData(stream, device_buffer, buffer_size); if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow. - retval = SDL_FALSE; + failed = SDL_TRUE; SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die. } else if (br < buffer_size) { SDL_memset(device_buffer + br, device->silence_value, buffer_size - br); // silence whatever we didn't write to. @@ -903,7 +937,7 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) the same stream to different devices at the same time, though.) */ const int br = SDL_GetAudioStreamData(stream, device->work_buffer, work_buffer_size); if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow. - retval = SDL_FALSE; + failed = SDL_TRUE; break; } else if (br > 0) { // it's okay if we get less than requested, we mix what we have. MixFloat32Audio(mix_buffer, (float *) device->work_buffer, br); @@ -926,26 +960,28 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) } // PlayDevice SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitDevice instead! - if (current_audio.impl.PlayDevice(device, device_buffer, buffer_size) < 0) { - retval = SDL_FALSE; + if (device->PlayDevice(device, device_buffer, buffer_size) < 0) { + failed = SDL_TRUE; } } SDL_UnlockMutex(device->lock); - if (!retval) { + if (failed) { SDL_AudioDeviceDisconnected(device); // doh. } - return retval; + return SDL_TRUE; // always go on if not shutting down, even if device failed. } void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device) { SDL_assert(!device->iscapture); const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); - // Wait for the audio to drain. !!! FIXME: don't bother waiting if device is lost. - SDL_Delay(((frames * 1000) / device->spec.freq) * 2); + // Wait for the audio to drain if device didn't die. + if (!SDL_AtomicGet(&device->zombie)) { + SDL_Delay(((frames * 1000) / device->spec.freq) * 2); + } current_audio.impl.ThreadDeinit(device); SDL_AudioThreadFinalize(device); } @@ -956,10 +992,10 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point SDL_assert(device != NULL); SDL_assert(!device->iscapture); SDL_OutputAudioThreadSetup(device); + do { - if (current_audio.impl.WaitDevice(device) < 0) { - SDL_AudioDeviceDisconnected(device); // doh. - break; + if (device->WaitDevice(device) < 0) { + SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) } } while (SDL_OutputAudioThreadIterate(device)); @@ -983,17 +1019,20 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) SDL_LockMutex(device->lock); - SDL_bool retval = SDL_TRUE; - if (SDL_AtomicGet(&device->shutdown)) { - retval = SDL_FALSE; // we're done, shut it down. - } else if (device->logical_devices == NULL) { - current_audio.impl.FlushCapture(device); // nothing wants data, dump anything pending. + SDL_UnlockMutex(device->lock); + return SDL_FALSE; // we're done, shut it down. + } + + SDL_bool failed = SDL_FALSE; + + if (device->logical_devices == NULL) { + device->FlushCapture(device); // nothing wants data, dump anything pending. } else { // this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitCaptureDevice! - int br = current_audio.impl.CaptureFromDevice(device, device->work_buffer, device->buffer_size); + int br = device->CaptureFromDevice(device, device->work_buffer, device->buffer_size); if (br < 0) { // uhoh, device failed for some reason! - retval = SDL_FALSE; + failed = SDL_TRUE; } else if (br > 0) { // queue the new data to each bound stream. for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { if (SDL_AtomicGet(&logdev->paused)) { @@ -1028,7 +1067,7 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) the same stream to different devices at the same time, though.) */ if (SDL_PutAudioStreamData(stream, output_buffer, br) < 0) { // oh crud, we probably ran out of memory. This is possibly an overreaction to kill the audio device, but it's likely the whole thing is going down in a moment anyhow. - retval = SDL_FALSE; + failed = SDL_TRUE; break; } } @@ -1038,17 +1077,17 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) SDL_UnlockMutex(device->lock); - if (!retval) { + if (failed) { SDL_AudioDeviceDisconnected(device); // doh. } - return retval; + return SDL_TRUE; // always go on if not shutting down, even if device failed. } void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device) { SDL_assert(device->iscapture); - current_audio.impl.FlushCapture(device); + device->FlushCapture(device); current_audio.impl.ThreadDeinit(device); SDL_AudioThreadFinalize(device); } @@ -1061,9 +1100,8 @@ static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point SDL_CaptureAudioThreadSetup(device); do { - if (current_audio.impl.WaitCaptureDevice(device) < 0) { - SDL_AudioDeviceDisconnected(device); // doh. - break; + if (device->WaitCaptureDevice(device) < 0) { + SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) } } while (SDL_CaptureAudioThreadIterate(device)); @@ -1173,7 +1211,6 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) } else { SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device); - SDL_assert(!device || !SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. SDL_UnlockRWLock(current_audio.device_hash_lock); if (!device) { @@ -1204,7 +1241,6 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_ const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; if (isphysical) { SDL_AudioDevice *device = (SDL_AudioDevice *) value; - SDL_assert(!SDL_AtomicGet(&device->condemned)); // shouldn't be in the list if pending deletion. if (callback(device, userdata)) { // found it? SDL_UnlockRWLock(current_audio.device_hash_lock); return device; @@ -1280,15 +1316,10 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * // this expects the device lock to be held. !!! FIXME: no it doesn't...? static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { - //SDL_assert(current_audio.impl.ProvidesOwnCallbackThread || ((device->thread == NULL) == (SDL_AtomicGet(&device->thread_alive) == 0))); - - if (SDL_AtomicGet(&device->thread_alive)) { - SDL_AtomicSet(&device->shutdown, 1); - if (device->thread != NULL) { - SDL_WaitThread(device->thread, NULL); - device->thread = NULL; - } - SDL_AtomicSet(&device->thread_alive, 0); + SDL_AtomicSet(&device->shutdown, 1); + if (device->thread != NULL) { + SDL_WaitThread(device->thread, NULL); + device->thread = NULL; } if (device->currently_opened) { @@ -1315,16 +1346,15 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) { SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); - if (logdev) { // if NULL, maybe it was already lost? + if (logdev) { SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); + UnrefPhysicalAudioDevice(device); // one reference for each logical device. + // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. + SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. - // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. - SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. ClosePhysicalAudioDevice(device); - } else { - SDL_UnlockMutex(device->lock); // we're set, let everything go again. } } } @@ -1402,11 +1432,19 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec SDL_assert(!device->currently_opened); SDL_assert(device->logical_devices == NULL); - // Just pretend to open a zombie device. It can still collect logical devices on the assumption they will all migrate when the default device is officially changed. + // Just pretend to open a zombie device. It can still collect logical devices on a default device under the assumption they will all migrate when the default device is officially changed. if (SDL_AtomicGet(&device->zombie)) { return 0; // Braaaaaaaaains. } + // These start with the backend's implementation, but we might swap them out with zombie versions later. + device->WaitDevice = current_audio.impl.WaitDevice; + device->PlayDevice = current_audio.impl.PlayDevice; + device->GetDeviceBuf = current_audio.impl.GetDeviceBuf; + device->WaitCaptureDevice = current_audio.impl.WaitCaptureDevice; + device->CaptureFromDevice = current_audio.impl.CaptureFromDevice; + device->FlushCapture = current_audio.impl.FlushCapture; + SDL_AudioSpec spec; SDL_copyp(&spec, inspec ? inspec : &device->default_spec); PrepareAudioFormat(device->iscapture, &spec); @@ -1445,7 +1483,6 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec } // Start the audio thread if necessary - SDL_AtomicSet(&device->thread_alive, 1); if (!current_audio.impl.ProvidesOwnCallbackThread) { const size_t stacksize = 0; // just take the system default, since audio streams might have callbacks. char threadname[64]; @@ -1453,12 +1490,13 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec device->thread = SDL_CreateThreadInternal(device->iscapture ? CaptureAudioThread : OutputAudioThread, threadname, stacksize, device); if (device->thread == NULL) { - SDL_AtomicSet(&device->thread_alive, 0); ClosePhysicalAudioDevice(device); return SDL_SetError("Couldn't create audio thread"); } } + RefPhysicalAudioDevice(device); // deref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). + return 0; } @@ -1501,13 +1539,14 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp if (device) { SDL_LogicalAudioDevice *logdev = NULL; if (!wants_default && SDL_AtomicGet(&device->zombie)) { - // uhoh, this device is undead, and just waiting for a new default device to be declared so it can hand off to it. Refuse explicit opens. + // uhoh, this device is undead, and just waiting to be cleaned up. Refuse explicit opens. SDL_SetError("Device was already lost and can't accept new opens"); } else if ((logdev = (SDL_LogicalAudioDevice *) SDL_calloc(1, sizeof (SDL_LogicalAudioDevice))) == NULL) { SDL_OutOfMemory(); } else if (!device->currently_opened && OpenPhysicalAudioDevice(device, spec) == -1) { // first thing using this physical device? Open at the OS level... SDL_free(logdev); } else { + RefPhysicalAudioDevice(device); // deref'd on successful SDL_CloseAudioDevice SDL_AtomicSet(&logdev->paused, 0); retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->iscapture, /*islogical=*/SDL_TRUE); logdev->physical_device = device; @@ -1909,7 +1948,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) } if (needs_migration) { - if (new_default_device->logical_devices == NULL) { // New default physical device not been opened yet? Open at the OS level... + if (!new_default_device->currently_opened) { // New default physical device not been opened yet? Open at the OS level... if (OpenPhysicalAudioDevice(new_default_device, &spec) == -1) { needs_migration = SDL_FALSE; // uhoh, just leave everything on the old default, nothing to be done. } @@ -1943,6 +1982,10 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) logdev->next = new_default_device->logical_devices; new_default_device->logical_devices = logdev; + SDL_assert(SDL_AtomicGet(¤t_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase... + RefPhysicalAudioDevice(new_default_device); + UnrefPhysicalAudioDevice(current_default_device); + // Post an event for each logical device we moved. if (post_fmt_event) { SDL_Event event; @@ -1973,7 +2016,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) // was current device already dead and just kept around to migrate to a new default device? Now we can kill it. Aim for the brain. if (current_default_device && SDL_AtomicGet(¤t_default_device->zombie)) { - SDL_AudioDeviceDisconnected(current_default_device); // Call again, now that we're not the default; this will remove from device list, send removal events, and destroy the SDL_AudioDevice. + UnrefPhysicalAudioDevice(current_default_device); } } diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 334aed82e9a05..6dd7a9f2b72f8 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -244,6 +244,17 @@ struct SDL_AudioDevice // A mutex for locking access to this struct SDL_Mutex *lock; + // Reference count of the device; logical devices, device threads, etc, add to this. + SDL_AtomicInt refcount; + + // These are, initially, set from current_audio, but we might swap them out with Zombie versions on disconnect/failure. + int (*WaitDevice)(SDL_AudioDevice *device); + int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); + Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); + int (*WaitCaptureDevice)(SDL_AudioDevice *device); + int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); + void (*FlushCapture)(SDL_AudioDevice *device); + // human-readable name of the device. ("SoundBlaster Pro 16") char *name; @@ -269,15 +280,9 @@ struct SDL_AudioDevice // non-zero if we are signaling the audio thread to end. SDL_AtomicInt shutdown; - // non-zero if we want the device to be destroyed (so audio thread knows to do it on termination). - SDL_AtomicInt condemned; - // non-zero if this was a disconnected default device and we're waiting for its replacement. SDL_AtomicInt zombie; - // non-zero if this has a thread running (which might be `thread` or something provided by the backend!) - SDL_AtomicInt thread_alive; - // SDL_TRUE if this is a capture device instead of an output device SDL_bool iscapture; From 354611a0c64aab27d538e6dfbf79f49bc8cc21c8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 10:03:42 -0400 Subject: [PATCH 089/725] testaudio: Fixed some bugs Valgrind pointed out. --- test/testaudio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/testaudio.c b/test/testaudio.c index 83bdd4163e59f..60eb79f51c739 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -316,7 +316,9 @@ static void DestroyThing(Thing *thing) case THING_LOGDEV: case THING_LOGDEV_CAPTURE: SDL_CloseAudioDevice(thing->data.logdev.devid); - SDL_DestroyTexture(thing->data.logdev.visualizer); + if (state->renderers[0] != NULL) { + SDL_DestroyTexture(thing->data.logdev.visualizer); + } SDL_DestroyMutex(thing->data.logdev.postmix_lock); SDL_free(thing->data.logdev.postmix_buffer); break; @@ -557,6 +559,7 @@ static void StreamThing_ontick(Thing *thing, Uint64 now) SDL_AudioSpec spec; if (!available || (SDL_GetAudioStreamFormat(thing->data.stream.stream, NULL, &spec) < 0)) { DestroyThingInPoof(thing); + return; } else { const int ticksleft = (int) ((((Uint64) (available / SDL_AUDIO_FRAMESIZE(spec))) * 1000) / spec.freq); const float pct = thing->data.stream.total_ticks ? (((float) (ticksleft)) / ((float) thing->data.stream.total_ticks)) : 0.0f; From 063cb0df6b6640862314f1535f74c8892c7a8627 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 13:09:55 -0400 Subject: [PATCH 090/725] audio: Fixed comment typo. "deref" should be "unref" --- src/audio/SDL_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 7374f9d9bf059..c34aee5b98c48 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -422,7 +422,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc } SDL_UnlockRWLock(current_audio.device_hash_lock); - RefPhysicalAudioDevice(device); // deref'd on device disconnect. + RefPhysicalAudioDevice(device); // unref'd on device disconnect. return device; } @@ -1495,7 +1495,7 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec } } - RefPhysicalAudioDevice(device); // deref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). + RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). return 0; } @@ -1546,7 +1546,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp } else if (!device->currently_opened && OpenPhysicalAudioDevice(device, spec) == -1) { // first thing using this physical device? Open at the OS level... SDL_free(logdev); } else { - RefPhysicalAudioDevice(device); // deref'd on successful SDL_CloseAudioDevice + RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice SDL_AtomicSet(&logdev->paused, 0); retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->iscapture, /*islogical=*/SDL_TRUE); logdev->physical_device = device; From f26b838a3ecb91034eb862102850e54249fd7661 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 13:10:27 -0400 Subject: [PATCH 091/725] jack: Check for sample rate and buffer size changes from the server. Reference Issue #8344. --- src/audio/jack/SDL_jackaudio.c | 39 ++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index ce2fde14c7f94..ba19621ef586f 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -43,6 +43,8 @@ static const char *(*JACK_jack_port_name)(const jack_port_t *); static const char *(*JACK_jack_port_type)(const jack_port_t *); static int (*JACK_jack_connect)(jack_client_t *, const char *, const char *); static int (*JACK_jack_set_process_callback)(jack_client_t *, JackProcessCallback, void *); +static int (*JACK_jack_set_sample_rate_callback)(jack_client_t *, JackSampleRateCallback, void *); +static int (*JACK_jack_set_buffer_size_callback)(jack_client_t *, JackBufferSizeCallback, void *); static int load_jack_syms(void); @@ -129,6 +131,8 @@ static int load_jack_syms(void) SDL_JACK_SYM(jack_port_type); SDL_JACK_SYM(jack_connect); SDL_JACK_SYM(jack_set_process_callback); + SDL_JACK_SYM(jack_set_sample_rate_callback); + SDL_JACK_SYM(jack_set_buffer_size_callback); return 0; } @@ -138,9 +142,30 @@ static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. * SDL_AudioDeviceDisconnected((SDL_AudioDevice *)arg); } -// !!! FIXME: implement and register these! -// typedef int(* JackSampleRateCallback)(jack_nframes_t nframes, void *arg) -// typedef int(* JackBufferSizeCallback)(jack_nframes_t nframes, void *arg) +static int jackSampleRateCallback(jack_nframes_t nframes, void *arg) +{ + //SDL_Log("JACK Sample Rate Callback! %d", (int) nframes); + SDL_AudioDevice *device = (SDL_AudioDevice *) arg; + SDL_AudioSpec newspec; + SDL_copyp(&newspec, &device->spec); + newspec.freq = (int) nframes; + if (SDL_AudioDeviceFormatChanged(device, &newspec, device->sample_frames) < 0) { + SDL_AudioDeviceDisconnected(device); + } + return 0; +} + +static int jackBufferSizeCallback(jack_nframes_t nframes, void *arg) +{ + //SDL_Log("JACK Buffer Size Callback! %d", (int) nframes); + SDL_AudioDevice *device = (SDL_AudioDevice *) arg; + SDL_AudioSpec newspec; + SDL_copyp(&newspec, &device->spec); + if (SDL_AudioDeviceFormatChanged(device, &newspec, (int) nframes) < 0) { + SDL_AudioDeviceDisconnected(device); + } + return 0; +} static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg) { @@ -341,7 +366,13 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) } } - if (JACK_jack_set_process_callback(client, callback, device) != 0) { + if (JACK_jack_set_buffer_size_callback(client, jackBufferSizeCallback, device) != 0) { + SDL_free(audio_ports); + return SDL_SetError("JACK: Couldn't set buffer size callback"); + } else if (JACK_jack_set_sample_rate_callback(client, jackSampleRateCallback, device) != 0) { + SDL_free(audio_ports); + return SDL_SetError("JACK: Couldn't set sample rate callback"); + } else if (JACK_jack_set_process_callback(client, callback, device) != 0) { SDL_free(audio_ports); return SDL_SetError("JACK: Couldn't set process callback"); } From 8c392692796cfad839c7cf57afa538dcac8fdbe0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 13:34:15 -0400 Subject: [PATCH 092/725] audio: Fix audio stream format when binding to a capture device. Fixes #8402. --- src/audio/SDL_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index c34aee5b98c48..18b5f533f283d 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1708,7 +1708,10 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int logdev->bound_streams = stream; if (iscapture) { - stream->src_spec.format = logdev->postmix ? SDL_AUDIO_F32 : device->spec.format; + SDL_copyp(&stream->src_spec, &device->spec); + if (logdev->postmix) { + stream->src_spec.format = SDL_AUDIO_F32; + } } SDL_UnlockMutex(stream->lock); From b19e68c8ec5b156ff8e389c353739e5f06c32360 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 13:56:43 -0400 Subject: [PATCH 093/725] testaudio: Properly display playback progress, regardless of data source. --- test/testaudio.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index 60eb79f51c739..9813237da56d9 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -75,7 +75,7 @@ struct Thing } poof; struct { SDL_AudioStream *stream; - int total_ticks; + int total_bytes; Uint64 next_level_update; Uint8 levels[5]; } stream; @@ -556,14 +556,11 @@ static void StreamThing_ontick(Thing *thing, Uint64 now) /* are we playing? See if we're done, or update state. */ if (thing->line_connected_to->what == THING_LOGDEV) { const int available = SDL_GetAudioStreamAvailable(thing->data.stream.stream); - SDL_AudioSpec spec; - if (!available || (SDL_GetAudioStreamFormat(thing->data.stream.stream, NULL, &spec) < 0)) { + if (!available) { DestroyThingInPoof(thing); return; } else { - const int ticksleft = (int) ((((Uint64) (available / SDL_AUDIO_FRAMESIZE(spec))) * 1000) / spec.freq); - const float pct = thing->data.stream.total_ticks ? (((float) (ticksleft)) / ((float) thing->data.stream.total_ticks)) : 0.0f; - thing->progress = 1.0f - pct; + thing->progress = 1.0f - (thing->data.stream.total_bytes ? (((float) (available)) / ((float) thing->data.stream.total_bytes)) : 0.0f); } } @@ -583,6 +580,9 @@ static void StreamThing_ondrag(Thing *thing, int button, float x, float y) if (button == SDL_BUTTON_RIGHT) { /* this is kinda hacky, but use this to disconnect from a playing source. */ if (thing->line_connected_to) { SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */ + if (thing->line_connected_to->what == THING_LOGDEV_CAPTURE) { + SDL_FlushAudioStream(thing->data.stream.stream); + } thing->line_connected_to = NULL; } } @@ -597,16 +597,14 @@ static void StreamThing_ondrop(Thing *thing, int button, float x, float y) /* connect to a logical device! */ SDL_Log("Binding audio stream ('%s') to logical device %u", thing->titlebar, (unsigned int) droppable_highlighted_thing->data.logdev.devid); if (thing->line_connected_to) { - const SDL_AudioSpec *spec = &droppable_highlighted_thing->data.logdev.spec; SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */ if (thing->line_connected_to->what == THING_LOGDEV_CAPTURE) { SDL_FlushAudioStream(thing->data.stream.stream); - thing->data.stream.total_ticks = (int) ((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / SDL_AUDIO_FRAMESIZE(*spec))) * 1000) / spec->freq); } } SDL_BindAudioStream(droppable_highlighted_thing->data.logdev.devid, thing->data.stream.stream); /* bind to new device! */ - + thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream); thing->progress = 0.0f; /* ontick will adjust this if we're on an output device.*/ thing->data.stream.next_level_update = SDL_GetTicks() + 100; thing->line_connected_to = droppable_highlighted_thing; @@ -644,7 +642,7 @@ static Thing *CreateStreamThing(const SDL_AudioSpec *spec, const Uint8 *buf, con if (buf && buflen) { SDL_PutAudioStreamData(thing->data.stream.stream, buf, (int) buflen); SDL_FlushAudioStream(thing->data.stream.stream); - thing->data.stream.total_ticks = (int) ((((Uint64) (SDL_GetAudioStreamAvailable(thing->data.stream.stream) / SDL_AUDIO_FRAMESIZE(*spec))) * 1000) / spec->freq); + thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream); } thing->ontick = StreamThing_ontick; thing->ondrag = StreamThing_ondrag; From d5dac0ad27dae1ee040f8a64f03c3aab4d0437ac Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 14:03:58 -0400 Subject: [PATCH 094/725] testaudio: Deal with a texture being unexpectedly NULL when scaling. This happens to work because our current textures are all 128x128, but in theory one shouldn't hit this case anyhow...right?! Reference Issue #8344. --- test/testaudio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index 9813237da56d9..ab70d2934954b 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -359,9 +359,10 @@ static void DrawOneThing(SDL_Renderer *renderer, Thing *thing) if (thing->scale != 1.0f) { const float centerx = thing->rect.x + (thing->rect.w / 2); const float centery = thing->rect.y + (thing->rect.h / 2); - SDL_assert(thing->texture != NULL); - dst.w = thing->texture->w * thing->scale; - dst.h = thing->texture->h * thing->scale; + const int w = 0 && thing->texture ? thing->texture->w : 128; + const int h = 0 && thing->texture ? thing->texture->h : 128; + dst.w = w * thing->scale; + dst.h = h * thing->scale; dst.x = centerx - (dst.w / 2); dst.y = centery - (dst.h / 2); } From c6f08c2553ee8be4292600ceaf787c207dd02df4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 15:25:34 -0400 Subject: [PATCH 095/725] testaudio: Removed debugging code. --- test/testaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index ab70d2934954b..a1bafa04e37cf 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -359,8 +359,8 @@ static void DrawOneThing(SDL_Renderer *renderer, Thing *thing) if (thing->scale != 1.0f) { const float centerx = thing->rect.x + (thing->rect.w / 2); const float centery = thing->rect.y + (thing->rect.h / 2); - const int w = 0 && thing->texture ? thing->texture->w : 128; - const int h = 0 && thing->texture ? thing->texture->h : 128; + const int w = thing->texture ? thing->texture->w : 128; + const int h = thing->texture ? thing->texture->h : 128; dst.w = w * thing->scale; dst.h = h * thing->scale; dst.x = centerx - (dst.w / 2); From b733adb503407efffe249bfad86624fb7bdb25be Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Oct 2023 20:17:04 -0400 Subject: [PATCH 096/725] audio: Fix device refcounting vs ProvidesOwnCallbackThread backends. --- src/audio/SDL_audio.c | 8 ++++---- src/audio/SDL_sysaudio.h | 3 +++ src/audio/emscripten/SDL_emscriptenaudio.c | 2 ++ src/audio/haiku/SDL_haikuaudio.cc | 2 ++ src/audio/jack/SDL_jackaudio.c | 2 ++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 18b5f533f283d..331e57c7ee8b1 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -352,7 +352,7 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) } // Don't hold the device lock when calling this, as we may destroy the device! -static void UnrefPhysicalAudioDevice(SDL_AudioDevice *device) +void UnrefPhysicalAudioDevice(SDL_AudioDevice *device) { if (SDL_AtomicDecRef(&device->refcount)) { // take it out of the device list. @@ -365,7 +365,7 @@ static void UnrefPhysicalAudioDevice(SDL_AudioDevice *device) } } -static void RefPhysicalAudioDevice(SDL_AudioDevice *device) +void RefPhysicalAudioDevice(SDL_AudioDevice *device) { SDL_AtomicIncRef(&device->refcount); } @@ -861,6 +861,7 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(!device->iscapture); + RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1010,6 +1011,7 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(device->iscapture); + RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1495,8 +1497,6 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec } } - RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). - return 0; } diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 6dd7a9f2b72f8..c33ac9ce08dc4 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -106,6 +106,9 @@ extern void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device); // Backends can call this to get a standardized name for a thread to power a specific audio device. extern char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen); +// Backends can call these to change a device's refcount. +extern void RefPhysicalAudioDevice(SDL_AudioDevice *device); +extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device); // These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread. extern void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device); diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index b8740a887529a..d2ee78b9dd9fe 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -181,6 +181,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + // limit to native freq device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; }); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 15204362d6be2..5d74462672b26 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -112,6 +112,8 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) } SDL_zerop(device->hidden); + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + // Parse the audio format and fill the Be raw audio format media_raw_audio_format format; SDL_zero(format); diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index ba19621ef586f..4f0691bc3dde3 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -300,6 +300,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); device->hidden->client = client; if (client == NULL) { From 435e7ce663b7e568086c5dc0fb1bb889e41a3ed1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 17 Oct 2023 21:41:30 -0500 Subject: [PATCH 097/725] Check for device disconnection in HIDAPI_JoystickOpen() HIDAPI joystick drivers may call HIDAPI_JoystickDisconnected() in their UpdateDevice() function during HIDAPI_JoystickOpen(). If they do this today, the opened joystick will end up partially initialized (no name, path, mapping GUID, etc.) because HIDAPI_GetDeviceByIndex() will no longer be able to find the SDL_HIDAPI_Device for the removed joystick. Worse still, joystick->hwdata->device becomes a dangling freed pointer the next time HIDAPI_UpdateDeviceList() is called. This leads to a UAF when the application or SDL calls SDL_JoystickClose() on this joystick. Fix all this by checking if the device no longer has any associated joysticks after calling UpdateDevice() and failing the open call if so. --- src/joystick/hidapi/SDL_hidapijoystick.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 06e6d2607a0c5..7fa7da96a7dd2 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1440,6 +1440,12 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) device->updating = SDL_FALSE; SDL_UnlockMutex(device->dev_lock); + /* UpdateDevice() may have called HIDAPI_JoystickDisconnected() if the device went away */ + if (device->num_joysticks == 0) { + SDL_free(hwdata); + return SDL_SetError("HIDAPI device disconnected while opening"); + } + if (!device->driver->OpenJoystick(device, joystick)) { /* The open failed, mark this device as disconnected and update devices */ HIDAPI_JoystickDisconnected(device, joystickID); From b45a0d901625cb1ab66b64bc57a9df0ca51ca7b2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 17 Oct 2023 14:06:40 -0700 Subject: [PATCH 098/725] Updated the documentation for SDL_LoadWAV_RW() --- include/SDL3/SDL_audio.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 952d958a4fdb3..007905d3e14c3 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -1281,8 +1281,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, * audio data allocated by the function is written to `audio_buf` and its * length in bytes to `audio_len`. The SDL_AudioSpec members `freq`, * `channels`, and `format` are set to the values of the audio data in the - * buffer. The `samples` member is set to a sane default and all others are - * set to zero. + * buffer. * * It's necessary to use SDL_free() to free the audio data returned in * `audio_buf` when it is no longer used. From e55e556f327f2a4cd40be2c76012570be2922985 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 Oct 2023 23:27:07 -0400 Subject: [PATCH 099/725] alsa: Fixed minor memory leak. The default device handles aren't free'd anywhere, so don't strdup them; everything else is managed by the hotplug thread, which does its own freeing. --- src/audio/alsa/SDL_alsa_audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 0826c551b6ece..c6f86d8460201 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -910,10 +910,10 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE; ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. if (has_default_output) { - *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, SDL_strdup("default")); + *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, "default"); } if (has_default_capture) { - *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, SDL_strdup("default")); + *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, "default"); } #if SDL_ALSA_HOTPLUG_THREAD From 7a52f7b3fdbd6f26e68015ee8248f19d855b2df1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 10:41:20 -0400 Subject: [PATCH 100/725] audio: Split Deinitialize into two stages. First stage happens before we destroy objects, and is generally used to shut down hotplug. The second stage is the usual deinit, which cleans up the lowlevel API, unloads shared libraries, etc. --- src/audio/SDL_audio.c | 4 ++++ src/audio/SDL_sysaudio.h | 1 + src/audio/alsa/SDL_alsa_audio.c | 6 +++++- src/audio/android/SDL_androidaudio.c | 2 +- src/audio/coreaudio/SDL_coreaudio.m | 4 ++-- src/audio/directsound/SDL_directsound.c | 11 ++++++++-- src/audio/pipewire/SDL_pipewire.c | 9 ++++++++- src/audio/pulseaudio/SDL_pulseaudio.c | 6 +++++- src/audio/wasapi/SDL_wasapi.c | 13 ++++++++++++ src/audio/wasapi/SDL_wasapi.h | 1 + src/audio/wasapi/SDL_wasapi_win32.c | 27 ++++++++++++++++++++++--- src/audio/wasapi/SDL_wasapi_winrt.cpp | 13 +++++++++++- 12 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 331e57c7ee8b1..a5dac4b673aed 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -570,6 +570,7 @@ static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buf static int SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } +static void SDL_AudioDeinitializeStart_Default(void) { /* no-op. */ } static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } static void SDL_AudioFreeDeviceHandle_Default(SDL_AudioDevice *device) { /* no-op. */ } @@ -622,6 +623,7 @@ static void CompleteAudioEntryPoints(void) FILL_STUB(FlushCapture); FILL_STUB(CloseDevice); FILL_STUB(FreeDeviceHandle); + FILL_STUB(DeinitializeStart); FILL_STUB(Deinitialize); #undef FILL_STUB } @@ -808,6 +810,8 @@ void SDL_QuitAudio(void) return; } + current_audio.impl.DeinitializeStart(); + // Destroy any audio streams that still exist... while (current_audio.existing_streams != NULL) { SDL_DestroyAudioStream(current_audio.existing_streams); diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index c33ac9ce08dc4..0d3ec6305a5b3 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -141,6 +141,7 @@ typedef struct SDL_AudioDriverImpl void (*FlushCapture)(SDL_AudioDevice *device); void (*CloseDevice)(SDL_AudioDevice *device); void (*FreeDeviceHandle)(SDL_AudioDevice *device); // SDL is done with this device; free the handle from SDL_AddAudioDevice() + void (*DeinitializeStart)(void); // SDL calls this, then starts destroying objects, then calls Deinitialize. This is a good place to stop hotplug detection. void (*Deinitialize)(void); // Some flags to push duplicate code into the core and reduce #ifdefs. diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index c6f86d8460201..ebc2b604c58ce 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -923,7 +923,7 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice #endif } -static void ALSA_Deinitialize(void) +static void ALSA_DeinitializeStart(void) { ALSA_Device *dev; ALSA_Device *next; @@ -944,7 +944,10 @@ static void ALSA_Deinitialize(void) SDL_free(dev); } hotplug_devices = NULL; +} +static void ALSA_Deinitialize(void) +{ UnloadALSALibrary(); } @@ -960,6 +963,7 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl) impl->GetDeviceBuf = ALSA_GetDeviceBuf; impl->PlayDevice = ALSA_PlayDevice; impl->CloseDevice = ALSA_CloseDevice; + impl->DeinitializeStart = ALSA_DeinitializeStart; impl->Deinitialize = ALSA_Deinitialize; impl->WaitCaptureDevice = ALSA_WaitDevice; impl->CaptureFromDevice = ALSA_CaptureFromDevice; diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index c0dade8acb6e9..9d49ce9b8cb7e 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -172,7 +172,7 @@ static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl) // !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultOutputDevice and OnlyHasDefaultCaptureDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+. impl->ThreadInit = Android_AudioThreadInit; impl->DetectDevices = Android_StartAudioHotplug; - impl->Deinitialize = Android_StopAudioHotplug; + impl->DeinitializeStart = Android_StopAudioHotplug; impl->OpenDevice = ANDROIDAUDIO_OpenDevice; impl->PlayDevice = ANDROIDAUDIO_PlayDevice; impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf; diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index bbe37161bf133..998bda154f03a 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -940,7 +940,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) return (device->hidden->thread != NULL) ? 0 : -1; } -static void COREAUDIO_Deinitialize(void) +static void COREAUDIO_DeinitializeStart(void) { #ifdef MACOSX_COREAUDIO AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL); @@ -958,7 +958,7 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) impl->CaptureFromDevice = COREAUDIO_CaptureFromDevice; impl->FlushCapture = COREAUDIO_FlushCapture; impl->CloseDevice = COREAUDIO_CloseDevice; - impl->Deinitialize = COREAUDIO_Deinitialize; + impl->DeinitializeStart = COREAUDIO_DeinitializeStart; #ifdef MACOSX_COREAUDIO impl->DetectDevices = COREAUDIO_DetectDevices; diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index ad0d9db375bb2..2a6bb47e7ceb8 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -623,15 +623,21 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) return 0; // good to go. } -static void DSOUND_Deinitialize(void) +static void DSOUND_DeinitializeStart(void) { #ifdef HAVE_MMDEVICEAPI_H if (SupportsIMMDevice) { SDL_IMMDevice_Quit(); - SupportsIMMDevice = SDL_FALSE; } #endif +} + +static void DSOUND_Deinitialize(void) +{ DSOUND_Unload(); +#ifdef HAVE_MMDEVICEAPI_H + SupportsIMMDevice = SDL_FALSE; +#endif } static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl) @@ -654,6 +660,7 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl) impl->FlushCapture = DSOUND_FlushCapture; impl->CloseDevice = DSOUND_CloseDevice; impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle; + impl->DeinitializeStart = DSOUND_DeinitializeStart; impl->Deinitialize = DSOUND_Deinitialize; impl->HasCaptureSupport = SDL_TRUE; diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 0dda0d8caec9f..b5cbbe74c1afc 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -1234,10 +1234,16 @@ static void PIPEWIRE_CloseDevice(SDL_AudioDevice *device) SDL_AudioThreadFinalize(device); } -static void PIPEWIRE_Deinitialize(void) +static void PIPEWIRE_DeinitializeStart(void) { if (pipewire_initialized) { hotplug_loop_destroy(); + } +} + +static void PIPEWIRE_Deinitialize(void) +{ + if (pipewire_initialized) { deinit_pipewire_library(); pipewire_initialized = SDL_FALSE; } @@ -1261,6 +1267,7 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) /* Set the function pointers */ impl->DetectDevices = PIPEWIRE_DetectDevices; impl->OpenDevice = PIPEWIRE_OpenDevice; + impl->DeinitializeStart = PIPEWIRE_DeinitializeStart; impl->Deinitialize = PIPEWIRE_Deinitialize; impl->PlayDevice = PIPEWIRE_PlayDevice; impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf; diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 1ab099baa0203..0703fc7401e69 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -968,7 +968,7 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio SDL_DestroySemaphore(ready_sem); } -static void PULSEAUDIO_Deinitialize(void) +static void PULSEAUDIO_DeinitializeStart(void) { if (pulseaudio_hotplug_thread) { PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); @@ -978,7 +978,10 @@ static void PULSEAUDIO_Deinitialize(void) SDL_WaitThread(pulseaudio_hotplug_thread, NULL); pulseaudio_hotplug_thread = NULL; } +} +static void PULSEAUDIO_Deinitialize(void) +{ DisconnectFromPulseServer(); SDL_free(default_sink_path); @@ -1010,6 +1013,7 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) impl->WaitDevice = PULSEAUDIO_WaitDevice; impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf; impl->CloseDevice = PULSEAUDIO_CloseDevice; + impl->DeinitializeStart = PULSEAUDIO_DeinitializeStart; impl->Deinitialize = PULSEAUDIO_Deinitialize; impl->WaitCaptureDevice = PULSEAUDIO_WaitCaptureDevice; impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice; diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 42aa8ef57716f..86f504387bccd 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -714,6 +714,18 @@ static void WASAPI_FreeDeviceHandle(SDL_AudioDevice *device) WASAPI_ProxyToManagementThread(mgmtthrtask_FreeDeviceHandle, device, &rc); } +static int mgmtthrtask_DeinitializeStart(void *userdata) +{ + WASAPI_PlatformDeinitializeStart(void); + return 0; +} + +static void WASAPI_DeinitializeStart(void) +{ + int rc; + WASAPI_ProxyToManagementThread(mgmtthrtask_DeinitializeStart, NULL, &rc); +} + static void WASAPI_Deinitialize(void) { DeinitManagementThread(); @@ -736,6 +748,7 @@ static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl) impl->CaptureFromDevice = WASAPI_CaptureFromDevice; impl->FlushCapture = WASAPI_FlushCapture; impl->CloseDevice = WASAPI_CloseDevice; + impl->DeinitializeStart = WASAPI_DeinitializeStart; impl->Deinitialize = WASAPI_Deinitialize; impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle; diff --git a/src/audio/wasapi/SDL_wasapi.h b/src/audio/wasapi/SDL_wasapi.h index ba2870801b2ba..00f80a08a3022 100644 --- a/src/audio/wasapi/SDL_wasapi.h +++ b/src/audio/wasapi/SDL_wasapi.h @@ -58,6 +58,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in // UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD. int WASAPI_PlatformInit(void); void WASAPI_PlatformDeinit(void); +void WASAPI_PlatformDeinitializeStart(void); void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); int WASAPI_ActivateDevice(SDL_AudioDevice *device); void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread. diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 719ac94a3bec6..b43e07941ca12 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -44,15 +44,21 @@ typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE); static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL; static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL; +static SDL_bool immdevice_initialized = SDL_FALSE; + /* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */ static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } }; int WASAPI_PlatformInit(void) { - if (SDL_IMMDevice_Init() < 0) { // this will call WIN_CoInitialize for us! - return -1; /* This is set by SDL_IMMDevice_Init */ + if (FAILED(WIN_CoInitialize())) { + return SDL_SetError("CoInitialize() failed"); + } else if (SDL_IMMDevice_Init() < 0) { + return -1; // Error string is set by SDL_IMMDevice_Init } + immdevice_initialized = SDL_TRUE; + libavrt = LoadLibrary(TEXT("avrt.dll")); /* this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! */ if (libavrt) { pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW)GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW"); @@ -62,6 +68,14 @@ int WASAPI_PlatformInit(void) return 0; } +static void StopWasapiHotplug(void) +{ + if (immdevice_initialized) { + SDL_IMMDevice_Quit(); + immdevice_initialized = SDL_FALSE; + } +} + void WASAPI_PlatformDeinit(void) { if (libavrt) { @@ -72,7 +86,14 @@ void WASAPI_PlatformDeinit(void) pAvSetMmThreadCharacteristicsW = NULL; pAvRevertMmThreadCharacteristics = NULL; - SDL_IMMDevice_Quit(); // This will call WIN_CoUninitialize for us! + StopWasapiHotplug(); + + WIN_CoUninitialize(); +} + +void WASAPI_PlatformDeinitializeStart(void) +{ + StopWasapiHotplug(); } void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) diff --git a/src/audio/wasapi/SDL_wasapi_winrt.cpp b/src/audio/wasapi/SDL_wasapi_winrt.cpp index a4030f39c2dc4..c3701a8a5f149 100644 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp @@ -220,7 +220,7 @@ int WASAPI_PlatformInit(void) return 0; } -void WASAPI_PlatformDeinit(void) +static void StopWasapiHotplug(void) { delete playback_device_event_handler; playback_device_event_handler = nullptr; @@ -228,6 +228,17 @@ void WASAPI_PlatformDeinit(void) capture_device_event_handler = nullptr; } +void WASAPI_PlatformDeinit(void) +{ + StopWasapiHotplug(); +} + +void WASAPI_PlatformDeinitializeStart(void) +{ + StopWasapiHotplug(); +} + + void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) { Platform::String ^ defdevid; From dd9833007692a6cb51f05c1d7f0c0206ec0ab6ba Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 18 Oct 2023 18:20:00 +0300 Subject: [PATCH 101/725] audio: fix windows wasapi build. --- src/audio/wasapi/SDL_wasapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 86f504387bccd..04295cceac1bc 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -716,7 +716,7 @@ static void WASAPI_FreeDeviceHandle(SDL_AudioDevice *device) static int mgmtthrtask_DeinitializeStart(void *userdata) { - WASAPI_PlatformDeinitializeStart(void); + WASAPI_PlatformDeinitializeStart(); return 0; } From f7dc63bcc3e7af853934d4c96618616087a56412 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 18 Oct 2023 18:32:00 +0300 Subject: [PATCH 102/725] audio: another windows wasapi build fix. --- src/audio/wasapi/SDL_wasapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 04295cceac1bc..620c15fbe191a 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -368,7 +368,7 @@ static int ActivateWasapiDevice(SDL_AudioDevice *device) { // this blocks because we're either being notified from a background thread or we're running during device open, // both of which won't deadlock vs the device thread. - int rc; + int rc = -1; return ((WASAPI_ProxyToManagementThread(mgmtthrtask_ActivateDevice, device, &rc) < 0) || (rc < 0)) ? -1 : 0; } From 48d80efb516bc9185cef71391cd586fa8d43c55e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 09:04:05 -0700 Subject: [PATCH 103/725] Fixed warning C4701: potentially uninitialized local variable 'props' used --- src/SDL_properties.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 6fa46fbf32c78..22613752d3d97 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -98,7 +98,7 @@ void SDL_QuitProperties(void) SDL_PropertiesID SDL_CreateProperties(void) { - SDL_PropertiesID props; + SDL_PropertiesID props = 0; SDL_Properties *properties = NULL; SDL_bool inserted = SDL_FALSE; From 34914bfb494cca86b9f08b2bd23fba42b358e877 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 13:53:42 -0400 Subject: [PATCH 104/725] alsa: Clean up device handles, now that hotplug thread cleanup is in place. --- src/audio/alsa/SDL_alsa_audio.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index ebc2b604c58ce..9d11cdc180300 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -875,7 +875,6 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name)); - SDL_free(dev->name); SDL_free(dev); } } @@ -910,10 +909,10 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE; ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. if (has_default_output) { - *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, "default"); + *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, SDL_strdup("default")); } if (has_default_capture) { - *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, "default"); + *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, SDL_strdup("default")); } #if SDL_ALSA_HOTPLUG_THREAD @@ -940,12 +939,16 @@ static void ALSA_DeinitializeStart(void) for (dev = hotplug_devices; dev; dev = next) { //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; - SDL_free(dev->name); SDL_free(dev); } hotplug_devices = NULL; } +static void ALSA_FreeDeviceHandle(SDL_AudioDevice *device) +{ + SDL_free(device->handle); +} + static void ALSA_Deinitialize(void) { UnloadALSALibrary(); @@ -968,6 +971,7 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl) impl->WaitCaptureDevice = ALSA_WaitDevice; impl->CaptureFromDevice = ALSA_CaptureFromDevice; impl->FlushCapture = ALSA_FlushCapture; + impl->FreeDeviceHandle = ALSA_FreeDeviceHandle; impl->HasCaptureSupport = SDL_TRUE; From 442e84916a2b7b0b820e7fe93e6c58afcdd5c0fc Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 13:57:32 -0400 Subject: [PATCH 105/725] opensles: Fixed capitalization to match other SDL backends. --- src/audio/SDL_audio.c | 2 +- src/audio/SDL_sysaudio.h | 2 +- src/audio/openslES/SDL_openslES.c | 96 +++++++++++++++---------------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index a5dac4b673aed..b74795649df36 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -55,7 +55,7 @@ static const AudioBootStrap *const bootstrap[] = { &AAUDIO_bootstrap, #endif #ifdef SDL_AUDIO_DRIVER_OPENSLES - &openslES_bootstrap, + &OPENSLES_bootstrap, #endif #ifdef SDL_AUDIO_DRIVER_ANDROID &ANDROIDAUDIO_bootstrap, diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 0d3ec6305a5b3..9d607bf8886a1 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -338,7 +338,7 @@ extern AudioBootStrap COREAUDIO_bootstrap; extern AudioBootStrap DISKAUDIO_bootstrap; extern AudioBootStrap DUMMYAUDIO_bootstrap; extern AudioBootStrap AAUDIO_bootstrap; -extern AudioBootStrap openslES_bootstrap; // !!! FIXME: capitalize this to match the others +extern AudioBootStrap OPENSLES_bootstrap; extern AudioBootStrap ANDROIDAUDIO_bootstrap; extern AudioBootStrap PS2AUDIO_bootstrap; extern AudioBootStrap PSPAUDIO_bootstrap; diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index de041e6b4895c..9a3dc33ba7664 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -108,7 +108,7 @@ static const char *sldevaudioplayerstr = "SLES Audio Player"; #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr -static void openslES_DetectDevices( int iscapture ) +static void OPENSLES_DetectDevices( int iscapture ) { LOGI( "openSLES_DetectDevices()" ); if ( iscapture ) @@ -118,9 +118,9 @@ static void openslES_DetectDevices( int iscapture ) } #endif -static void openslES_DestroyEngine(void) +static void OPENSLES_DestroyEngine(void) { - LOGI("openslES_DestroyEngine()"); + LOGI("OPENSLES_DestroyEngine()"); // destroy output mix object, and invalidate all associated interfaces if (outputMixObject != NULL) { @@ -136,7 +136,7 @@ static void openslES_DestroyEngine(void) } } -static int openslES_CreateEngine(void) +static int OPENSLES_CreateEngine(void) { const SLInterfaceID ids[1] = { SL_IID_VOLUME }; const SLboolean req[1] = { SL_BOOLEAN_FALSE }; @@ -185,7 +185,7 @@ static int openslES_CreateEngine(void) return 1; error: - openslES_DestroyEngine(); + OPENSLES_DestroyEngine(); return 0; } @@ -198,7 +198,7 @@ static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) SDL_PostSemaphore(audiodata->playsem); } -static void openslES_DestroyPCMRecorder(SDL_AudioDevice *device) +static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; SLresult result; @@ -229,7 +229,7 @@ static void openslES_DestroyPCMRecorder(SDL_AudioDevice *device) } } -static int openslES_CreatePCMRecorder(SDL_AudioDevice *device) +static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; SLDataFormat_PCM format_pcm; @@ -375,7 +375,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) SDL_PostSemaphore(audiodata->playsem); } -static void openslES_DestroyPCMPlayer(SDL_AudioDevice *device) +static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; @@ -406,7 +406,7 @@ static void openslES_DestroyPCMPlayer(SDL_AudioDevice *device) } } -static int openslES_CreatePCMPlayer(SDL_AudioDevice *device) +static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) { /* If we want to add floating point audio support (requires API level 21) it can be done as described here: @@ -597,7 +597,7 @@ static int openslES_CreatePCMPlayer(SDL_AudioDevice *device) return -1; } -static int openslES_OpenDevice(SDL_AudioDevice *device) +static int OPENSLES_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { @@ -605,18 +605,18 @@ static int openslES_OpenDevice(SDL_AudioDevice *device) } if (device->iscapture) { - LOGI("openslES_OpenDevice() for capture"); - return openslES_CreatePCMRecorder(device); + LOGI("OPENSLES_OpenDevice() for capture"); + return OPENSLES_CreatePCMRecorder(device); } else { int ret; - LOGI("openslES_OpenDevice() for playing"); - ret = openslES_CreatePCMPlayer(device); + LOGI("OPENSLES_OpenDevice() for playing"); + ret = OPENSLES_CreatePCMPlayer(device); if (ret < 0) { // Another attempt to open the device with a lower frequency if (device->spec.freq > 48000) { - openslES_DestroyPCMPlayer(device); + OPENSLES_DestroyPCMPlayer(device); device->spec.freq = 48000; - ret = openslES_CreatePCMPlayer(device); + ret = OPENSLES_CreatePCMPlayer(device); } } @@ -628,21 +628,21 @@ static int openslES_OpenDevice(SDL_AudioDevice *device) return 0; } -static int openslES_WaitDevice(SDL_AudioDevice *device) +static int OPENSLES_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; - LOGV("openslES_WaitDevice()"); + LOGV("OPENSLES_WaitDevice()"); // Wait for an audio chunk to finish return SDL_WaitSemaphore(audiodata->playsem); } -static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static int OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { struct SDL_PrivateAudioData *audiodata = device->hidden; - LOGV("======openslES_PlayDevice()======"); + LOGV("======OPENSLES_PlayDevice()======"); // Queue it up const SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer, buflen); @@ -673,15 +673,15 @@ static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int // // okay.. -static Uint8 *openslES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) +static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) { struct SDL_PrivateAudioData *audiodata = device->hidden; - LOGV("openslES_GetDeviceBuf()"); + LOGV("OPENSLES_GetDeviceBuf()"); return audiodata->pmixbuff[audiodata->next_buffer]; } -static int openslES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int OPENSLES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *audiodata = device->hidden; @@ -704,16 +704,16 @@ static int openslES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int return device->buffer_size; } -static void openslES_CloseDevice(SDL_AudioDevice *device) +static void OPENSLES_CloseDevice(SDL_AudioDevice *device) { // struct SDL_PrivateAudioData *audiodata = device->hidden; if (device->hidden) { if (device->iscapture) { - LOGI("openslES_CloseDevice() for capture"); - openslES_DestroyPCMRecorder(device); + LOGI("OPENSLES_CloseDevice() for capture"); + OPENSLES_DestroyPCMRecorder(device); } else { - LOGI("openslES_CloseDevice() for playing"); - openslES_DestroyPCMPlayer(device); + LOGI("OPENSLES_CloseDevice() for playing"); + OPENSLES_DestroyPCMPlayer(device); } SDL_free(device->hidden); @@ -721,61 +721,61 @@ static void openslES_CloseDevice(SDL_AudioDevice *device) } } -static SDL_bool openslES_Init(SDL_AudioDriverImpl *impl) +static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl) { - LOGI("openslES_Init() called"); + LOGI("OPENSLES_Init() called"); - if (!openslES_CreateEngine()) { + if (!OPENSLES_CreateEngine()) { return SDL_FALSE; } - LOGI("openslES_Init() - set pointers"); + LOGI("OPENSLES_Init() - set pointers"); // Set the function pointers - // impl->DetectDevices = openslES_DetectDevices; + // impl->DetectDevices = OPENSLES_DetectDevices; impl->ThreadInit = Android_AudioThreadInit; - impl->OpenDevice = openslES_OpenDevice; - impl->WaitDevice = openslES_WaitDevice; - impl->PlayDevice = openslES_PlayDevice; - impl->GetDeviceBuf = openslES_GetDeviceBuf; - impl->WaitCaptureDevice = openslES_WaitDevice; - impl->CaptureFromDevice = openslES_CaptureFromDevice; - impl->CloseDevice = openslES_CloseDevice; - impl->Deinitialize = openslES_DestroyEngine; + impl->OpenDevice = OPENSLES_OpenDevice; + impl->WaitDevice = OPENSLES_WaitDevice; + impl->PlayDevice = OPENSLES_PlayDevice; + impl->GetDeviceBuf = OPENSLES_GetDeviceBuf; + impl->WaitCaptureDevice = OPENSLES_WaitDevice; + impl->CaptureFromDevice = OPENSLES_CaptureFromDevice; + impl->CloseDevice = OPENSLES_CloseDevice; + impl->Deinitialize = OPENSLES_DestroyEngine; // and the capabilities impl->HasCaptureSupport = SDL_TRUE; impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; - LOGI("openslES_Init() - success"); + LOGI("OPENSLES_Init() - success"); // this audio target is available. return SDL_TRUE; } -AudioBootStrap openslES_bootstrap = { - "openslES", "opensl ES audio driver", openslES_Init, SDL_FALSE +AudioBootStrap OPENSLES_bootstrap = { + "openslES", "opensl ES audio driver", OPENSLES_Init, SDL_FALSE }; -void openslES_ResumeDevices(void) +void OPENSLES_ResumeDevices(void) { if (bqPlayerPlay != NULL) { // set the player's state to 'playing' SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); if (SL_RESULT_SUCCESS != result) { - LOGE("openslES_ResumeDevices failed: %d", result); + LOGE("OPENSLES_ResumeDevices failed: %d", result); } } } -void openslES_PauseDevices(void) +void OPENSLES_PauseDevices(void) { if (bqPlayerPlay != NULL) { // set the player's state to 'paused' SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED); if (SL_RESULT_SUCCESS != result) { - LOGE("openslES_PauseDevices failed: %d", result); + LOGE("OPENSLES_PauseDevices failed: %d", result); } } } From 81c77396af2681b5feb38ce1f3beb90d59bd9fa8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 14:56:32 -0400 Subject: [PATCH 106/725] opensles: Patched to compile. --- src/audio/openslES/SDL_openslES.c | 2 +- src/audio/openslES/SDL_openslES.h | 8 ++++---- src/video/android/SDL_androidevents.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index 9a3dc33ba7664..b40e702ba6c4b 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -755,7 +755,7 @@ static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl) } AudioBootStrap OPENSLES_bootstrap = { - "openslES", "opensl ES audio driver", OPENSLES_Init, SDL_FALSE + "openslES", "OpenSL ES audio driver", OPENSLES_Init, SDL_FALSE }; void OPENSLES_ResumeDevices(void) diff --git a/src/audio/openslES/SDL_openslES.h b/src/audio/openslES/SDL_openslES.h index d7abc19e34afa..74d0da445d1ab 100644 --- a/src/audio/openslES/SDL_openslES.h +++ b/src/audio/openslES/SDL_openslES.h @@ -25,13 +25,13 @@ #ifdef SDL_AUDIO_DRIVER_OPENSLES -void openslES_ResumeDevices(void); -void openslES_PauseDevices(void); +void OPENSLES_ResumeDevices(void); +void OPENSLES_PauseDevices(void); #else -static void openslES_ResumeDevices(void) {} -static void openslES_PauseDevices(void) {} +static void OPENSLES_ResumeDevices(void) {} +static void OPENSLES_PauseDevices(void) {} #endif diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index ff39d801c776c..31704c68bfb28 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -107,7 +107,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this) #endif ANDROIDAUDIO_PauseDevices(); - openslES_PauseDevices(); + OPENSLES_PauseDevices(); AAUDIO_PauseDevices(); if (SDL_WaitSemaphore(Android_ResumeSem) == 0) { @@ -118,7 +118,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this) SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); ANDROIDAUDIO_ResumeDevices(); - openslES_ResumeDevices(); + OPENSLES_ResumeDevices(); AAUDIO_ResumeDevices(); /* Restore the GL Context from here, as this operation is thread dependent */ @@ -181,7 +181,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this) if (videodata->pauseAudio) { ANDROIDAUDIO_PauseDevices(); - openslES_PauseDevices(); + OPENSLES_PauseDevices(); AAUDIO_PauseDevices(); } @@ -197,7 +197,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this) if (videodata->pauseAudio) { ANDROIDAUDIO_ResumeDevices(); - openslES_ResumeDevices(); + OPENSLES_ResumeDevices(); AAUDIO_ResumeDevices(); } From 0ff67dc21b4f3c5efa49f333872c7d12bed76233 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 15:02:01 -0400 Subject: [PATCH 107/725] video: Fix compiler warning about SDL_ReadSurfacePixel not being declared. (this was legal before, but the Android NDK wants to make sure we didn't mean for this function to be marked `static` since it didn't have a formal declaration before its definition and might only be used in the one source file.) --- src/video/SDL_surface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 7c89a43fa1702..ac0d97e410f93 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -21,6 +21,7 @@ #include "SDL_internal.h" #include "SDL_sysvideo.h" +#include "SDL_video_c.h" #include "SDL_blit.h" #include "SDL_RLEaccel_c.h" #include "SDL_surface_pixel_impl.h" @@ -35,8 +36,7 @@ SDL_COMPILE_TIME_ASSERT(surface_size_assumptions, SDL_COMPILE_TIME_ASSERT(can_indicate_overflow, SDL_SIZE_MAX > SDL_MAX_SINT32); -int -SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { return SDL_ReadSurfacePixel_impl(surface, x, y, r, g, b, a); } From 9d7c57234a2e518ea96c969370bbb8b8b6bc5ac1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 15:35:09 -0400 Subject: [PATCH 108/725] audio: Cleaned out most remaining `/* */` comments for `//` style. Fully committing to it...! This left SDL_wave.* alone for now, since there's a ton of comments in there and this code hasn't changed much from SDL2 so far. But as SDL2 ages out a little more, I'll likely switch this over, too. --- build-scripts/gen_audio_channel_conversion.c | 4 +- build-scripts/gen_audio_resampler_filter.c | 4 +- src/audio/SDL_audio_channel_converters.h | 58 +++--- src/audio/SDL_audio_resampler_filter.h | 2 +- src/audio/SDL_audiodev.c | 10 +- src/audio/SDL_audiodev_c.h | 6 +- src/audio/SDL_audioresample.c | 8 +- src/audio/SDL_audiotypecvt.c | 177 +++++++++---------- src/audio/SDL_mixer.c | 12 +- src/audio/aaudio/SDL_aaudio.h | 2 +- src/audio/aaudio/SDL_aaudiofuncs.h | 26 +-- src/audio/alsa/SDL_alsa_audio.h | 8 +- src/audio/android/SDL_androidaudio.h | 2 +- src/audio/coreaudio/SDL_coreaudio.h | 4 +- src/audio/coreaudio/SDL_coreaudio.m | 45 +++-- src/audio/disk/SDL_diskaudio.h | 4 +- src/audio/dsp/SDL_dspaudio.c | 25 ++- src/audio/dsp/SDL_dspaudio.h | 6 +- src/audio/emscripten/SDL_emscriptenaudio.h | 2 +- src/audio/haiku/SDL_haikuaudio.h | 2 +- src/audio/jack/SDL_jackaudio.c | 37 ++-- src/audio/jack/SDL_jackaudio.h | 2 +- src/audio/n3ds/SDL_n3dsaudio.h | 6 +- src/audio/netbsd/SDL_netbsdaudio.c | 2 +- src/audio/netbsd/SDL_netbsdaudio.h | 10 +- src/audio/openslES/SDL_openslES.h | 2 +- src/audio/pipewire/SDL_pipewire.c | 108 +++++------ src/audio/pipewire/SDL_pipewire.h | 4 +- src/audio/ps2/SDL_ps2audio.h | 10 +- src/audio/psp/SDL_pspaudio.h | 10 +- src/audio/pulseaudio/SDL_pulseaudio.c | 109 ++++++------ src/audio/pulseaudio/SDL_pulseaudio.h | 8 +- src/audio/qnx/SDL_qsa_audio.h | 3 +- src/audio/sndio/SDL_sndioaudio.h | 2 +- src/audio/vita/SDL_vitaaudio.h | 10 +- src/audio/wasapi/SDL_wasapi.h | 6 +- src/audio/wasapi/SDL_wasapi_win32.c | 26 +-- 37 files changed, 378 insertions(+), 384 deletions(-) diff --git a/build-scripts/gen_audio_channel_conversion.c b/build-scripts/gen_audio_channel_conversion.c index 6c98fa3494f00..720a9e5997cee 100644 --- a/build-scripts/gen_audio_channel_conversion.c +++ b/build-scripts/gen_audio_channel_conversion.c @@ -269,7 +269,7 @@ static void write_converter(const int fromchans, const int tochans) "\n", lowercase(fromstr), lowercase(tostr)); if (convert_backwards) { /* must convert backwards when growing the output in-place. */ - printf(" /* convert backwards, since output is growing in-place. */\n"); + printf(" // convert backwards, since output is growing in-place.\n"); printf(" src += (num_frames-1)"); if (fromchans != 1) { printf(" * %d", fromchans); @@ -425,7 +425,7 @@ int main(void) " 3. This notice may not be removed or altered from any source distribution.\n" "*/\n" "\n" - "/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c */\n" + "// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c\n" "\n" "\n" "typedef void (*SDL_AudioChannelConverter)(float *dst, const float *src, int num_frames);\n" diff --git a/build-scripts/gen_audio_resampler_filter.c b/build-scripts/gen_audio_resampler_filter.c index 19991bd964b1d..732b873d2347d 100644 --- a/build-scripts/gen_audio_resampler_filter.c +++ b/build-scripts/gen_audio_resampler_filter.c @@ -25,7 +25,7 @@ Built with: gcc -o genfilter build-scripts/gen_audio_resampler_filter.c -lm && ./genfilter > src/audio/SDL_audio_resampler_filter.h - */ +*/ /* SDL's resampler uses a "bandlimited interpolation" algorithm: @@ -128,7 +128,7 @@ int main(void) " 3. This notice may not be removed or altered from any source distribution.\n" "*/\n" "\n" - "/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c */\n" + "// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c\n" "\n" "#define RESAMPLER_ZERO_CROSSINGS %d\n" "#define RESAMPLER_BITS_PER_SAMPLE %d\n" diff --git a/src/audio/SDL_audio_channel_converters.h b/src/audio/SDL_audio_channel_converters.h index b29046bd1788d..5fe6df52fb4a1 100644 --- a/src/audio/SDL_audio_channel_converters.h +++ b/src/audio/SDL_audio_channel_converters.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c */ +// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c typedef void (*SDL_AudioChannelConverter)(float *dst, const float *src, int num_frames); @@ -30,7 +30,7 @@ static void SDL_ConvertMonoToStereo(float *dst, const float *src, int num_frames LOG_DEBUG_AUDIO_CONVERT("mono", "stereo"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 2; for (i = num_frames; i; i--, src--, dst -= 2) { @@ -47,7 +47,7 @@ static void SDL_ConvertMonoTo21(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "2.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 3; for (i = num_frames; i; i--, src--, dst -= 3) { @@ -65,7 +65,7 @@ static void SDL_ConvertMonoToQuad(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "quad"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 4; for (i = num_frames; i; i--, src--, dst -= 4) { @@ -84,7 +84,7 @@ static void SDL_ConvertMonoTo41(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "4.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 5; for (i = num_frames; i; i--, src--, dst -= 5) { @@ -104,7 +104,7 @@ static void SDL_ConvertMonoTo51(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "5.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 6; for (i = num_frames; i; i--, src--, dst -= 6) { @@ -125,7 +125,7 @@ static void SDL_ConvertMonoTo61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src--, dst -= 7) { @@ -147,7 +147,7 @@ static void SDL_ConvertMonoTo71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("mono", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1); dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src--, dst -= 8) { @@ -182,7 +182,7 @@ static void SDL_ConvertStereoTo21(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("stereo", "2.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 3; for (i = num_frames; i; i--, src -= 2, dst -= 3) { @@ -199,7 +199,7 @@ static void SDL_ConvertStereoToQuad(float *dst, const float *src, int num_frames LOG_DEBUG_AUDIO_CONVERT("stereo", "quad"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 4; for (i = num_frames; i; i--, src -= 2, dst -= 4) { @@ -217,7 +217,7 @@ static void SDL_ConvertStereoTo41(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("stereo", "4.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 5; for (i = num_frames; i; i--, src -= 2, dst -= 5) { @@ -236,7 +236,7 @@ static void SDL_ConvertStereoTo51(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("stereo", "5.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 6; for (i = num_frames; i; i--, src -= 2, dst -= 6) { @@ -256,7 +256,7 @@ static void SDL_ConvertStereoTo61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("stereo", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src -= 2, dst -= 7) { @@ -277,7 +277,7 @@ static void SDL_ConvertStereoTo71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("stereo", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 2; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 2, dst -= 8) { @@ -325,7 +325,7 @@ static void SDL_Convert21ToQuad(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("2.1", "quad"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 3; dst += (num_frames-1) * 4; for (i = num_frames; i; i--, src -= 3, dst -= 4) { @@ -344,7 +344,7 @@ static void SDL_Convert21To41(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("2.1", "4.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 3; dst += (num_frames-1) * 5; for (i = num_frames; i; i--, src -= 3, dst -= 5) { @@ -363,7 +363,7 @@ static void SDL_Convert21To51(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("2.1", "5.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 3; dst += (num_frames-1) * 6; for (i = num_frames; i; i--, src -= 3, dst -= 6) { @@ -383,7 +383,7 @@ static void SDL_Convert21To61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("2.1", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 3; dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src -= 3, dst -= 7) { @@ -404,7 +404,7 @@ static void SDL_Convert21To71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("2.1", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 3; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 3, dst -= 8) { @@ -469,7 +469,7 @@ static void SDL_ConvertQuadTo41(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("quad", "4.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 4; dst += (num_frames-1) * 5; for (i = num_frames; i; i--, src -= 4, dst -= 5) { @@ -488,7 +488,7 @@ static void SDL_ConvertQuadTo51(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("quad", "5.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 4; dst += (num_frames-1) * 6; for (i = num_frames; i; i--, src -= 4, dst -= 6) { @@ -508,7 +508,7 @@ static void SDL_ConvertQuadTo61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("quad", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 4; dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src -= 4, dst -= 7) { @@ -531,7 +531,7 @@ static void SDL_ConvertQuadTo71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("quad", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 4; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 4, dst -= 8) { @@ -613,7 +613,7 @@ static void SDL_Convert41To51(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("4.1", "5.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 5; dst += (num_frames-1) * 6; for (i = num_frames; i; i--, src -= 5, dst -= 6) { @@ -633,7 +633,7 @@ static void SDL_Convert41To61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("4.1", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 5; dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src -= 5, dst -= 7) { @@ -656,7 +656,7 @@ static void SDL_Convert41To71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("4.1", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 5; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 5, dst -= 8) { @@ -758,7 +758,7 @@ static void SDL_Convert51To61(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("5.1", "6.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 6; dst += (num_frames-1) * 7; for (i = num_frames; i; i--, src -= 6, dst -= 7) { @@ -781,7 +781,7 @@ static void SDL_Convert51To71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("5.1", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 6; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 6, dst -= 8) { @@ -911,7 +911,7 @@ static void SDL_Convert61To71(float *dst, const float *src, int num_frames) LOG_DEBUG_AUDIO_CONVERT("6.1", "7.1"); - /* convert backwards, since output is growing in-place. */ + // convert backwards, since output is growing in-place. src += (num_frames-1) * 7; dst += (num_frames-1) * 8; for (i = num_frames; i; i--, src -= 7, dst -= 8) { diff --git a/src/audio/SDL_audio_resampler_filter.h b/src/audio/SDL_audio_resampler_filter.h index 1ea9c33ddec22..42e4666506c52 100644 --- a/src/audio/SDL_audio_resampler_filter.h +++ b/src/audio/SDL_audio_resampler_filter.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c */ +// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c #define RESAMPLER_ZERO_CROSSINGS 5 #define RESAMPLER_BITS_PER_SAMPLE 16 diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index 9d73fbb55cec1..f00b8590dd5ee 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -20,14 +20,14 @@ */ #include "SDL_internal.h" -/* Get the name of the audio device we use for output */ +// Get the name of the audio device we use for output #if defined(SDL_AUDIO_DRIVER_NETBSD) || defined(SDL_AUDIO_DRIVER_OSS) #include #include #include -#include /* For close() */ +#include // For close() #include "SDL_audiodev_c.h" @@ -84,7 +84,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD test = test_stub; } - /* Figure out what our audio device is */ + // Figure out what our audio device is audiodev = SDL_getenv("SDL_PATH_DSP"); if (audiodev == NULL) { audiodev = SDL_getenv("AUDIODEV"); @@ -95,7 +95,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD } else { struct stat sb; - /* Added support for /dev/sound/\* in Linux 2.4 */ + // Added support for /dev/sound/\* in Linux 2.4 if (((stat("/dev/sound", &sb) == 0) && S_ISDIR(sb.st_mode)) && ((stat(SDL_PATH_DEV_DSP24, &sb) == 0) && S_ISCHR(sb.st_mode))) { audiodev = SDL_PATH_DEV_DSP24; } else { @@ -122,4 +122,4 @@ void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int)) SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test); } -#endif /* Audio driver selection */ +#endif // Audio device selection diff --git a/src/audio/SDL_audiodev_c.h b/src/audio/SDL_audiodev_c.h index 6301d07c54bae..53d451fc10bd7 100644 --- a/src/audio/SDL_audiodev_c.h +++ b/src/audio/SDL_audiodev_c.h @@ -25,8 +25,8 @@ #include "SDL_internal.h" #include "SDL_sysaudio.h" -/* Open the audio device for playback, and don't block if busy */ -/* #define USE_BLOCKING_WRITES */ +// Open the audio device for playback, and don't block if busy +//#define USE_BLOCKING_WRITES #ifdef USE_BLOCKING_WRITES #define OPEN_FLAGS_OUTPUT O_WRONLY @@ -38,4 +38,4 @@ extern void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int)); -#endif /* SDL_audiodev_c_h_ */ +#endif // SDL_audiodev_c_h_ diff --git a/src/audio/SDL_audioresample.c b/src/audio/SDL_audioresample.c index 6e3f40327232f..a357fab9e306d 100644 --- a/src/audio/SDL_audioresample.c +++ b/src/audio/SDL_audioresample.c @@ -23,13 +23,13 @@ #include "SDL_sysaudio.h" #include "SDL_audioresample.h" -/* SDL's resampler uses a "bandlimited interpolation" algorithm: - https://ccrma.stanford.edu/~jos/resample/ */ +// SDL's resampler uses a "bandlimited interpolation" algorithm: +// https://ccrma.stanford.edu/~jos/resample/ #include "SDL_audio_resampler_filter.h" -/* For a given srcpos, `srcpos + frame` are sampled, where `-RESAMPLER_ZERO_CROSSINGS < frame <= RESAMPLER_ZERO_CROSSINGS`. - * Note, when upsampling, it is also possible to start sampling from `srcpos = -1`. */ +// For a given srcpos, `srcpos + frame` are sampled, where `-RESAMPLER_ZERO_CROSSINGS < frame <= RESAMPLER_ZERO_CROSSINGS`. +// Note, when upsampling, it is also possible to start sampling from `srcpos = -1`. #define RESAMPLER_MAX_PADDING_FRAMES (RESAMPLER_ZERO_CROSSINGS + 1) #define RESAMPLER_FILTER_INTERP_BITS (32 - RESAMPLER_BITS_PER_ZERO_CROSSING) diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index a8fb65427f5e8..deabeee474b94 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -22,32 +22,31 @@ #include "SDL_audio_c.h" -/* TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 - * can be fixed */ +// TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 can be fixed #undef SDL_NEON_INTRINSICS #ifndef SDL_CPUINFO_DISABLED #if defined(__x86_64__) && defined(SDL_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // x86_64 guarantees SSE2. #elif defined(__MACOS__) && defined(SDL_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* macOS/Intel guarantees SSE2. */ +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // macOS/Intel guarantees SSE2. #elif defined(__ARM_ARCH) && (__ARM_ARCH >= 8) && defined(SDL_NEON_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* ARMv8+ promise NEON. */ +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // ARMv8+ promise NEON. #elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) && defined(SDL_NEON_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* All Apple ARMv7 chips promise NEON support. */ +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // All Apple ARMv7 chips promise NEON support. #endif #endif -/* Set to zero if platform is guaranteed to use a SIMD codepath here. */ +// Set to zero if platform is guaranteed to use a SIMD codepath here. #if !defined(NEED_SCALAR_CONVERTER_FALLBACKS) || defined(SDL_CPUINFO_DISABLED) #define NEED_SCALAR_CONVERTER_FALLBACKS 1 #endif -#define DIVBY2147483648 0.0000000004656612873077392578125f /* 0x1p-31f */ +#define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f #if NEED_SCALAR_CONVERTER_FALLBACKS -/* This code requires that floats are in the IEEE-754 binary32 format */ +// This code requires that floats are in the IEEE-754 binary32 format SDL_COMPILE_TIME_ASSERT(float_bits, sizeof(float) == sizeof(Uint32)); union float_bits { @@ -111,7 +110,7 @@ static void SDL_Convert_S32_to_F32_Scalar(float *dst, const Sint32 *src, int num } } -/* Create a bit-mask based on the sign-bit. Should optimize to a single arithmetic-shift-right */ +// Create a bit-mask based on the sign-bit. Should optimize to a single arithmetic-shift-right #define SIGNMASK(x) (Uint32)(0u - ((Uint32)(x) >> 31)) static void SDL_Convert_F32_to_S8_Scalar(Sint8 *dst, const float *src, int num_samples) @@ -202,7 +201,7 @@ static void SDL_Convert_F32_to_S32_Scalar(Sint32 *dst, const float *src, int num #undef SIGNMASK -#endif /* NEED_SCALAR_CONVERTER_FALLBACKS */ +#endif // NEED_SCALAR_CONVERTER_FALLBACKS #ifdef SDL_SSE2_INTRINSICS static void SDL_TARGETING("sse2") SDL_Convert_S8_to_F32_SSE2(float *dst, const Sint8 *src, int num_samples) @@ -324,7 +323,7 @@ static void SDL_TARGETING("sse2") SDL_Convert_S32_to_F32_SSE2(float *dst, const { int i = num_samples; - /* dst[i] = f32(src[i]) / f32(0x80000000) */ + // dst[i] = f32(src[i]) / f32(0x80000000) const __m128 scaler = _mm_set1_ps(DIVBY2147483648); LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using SSE2)"); @@ -543,9 +542,9 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S32_SSE2(Sint32 *dst, const #endif #ifdef SDL_NEON_INTRINSICS -#define DIVBY128 0.0078125f /* 0x1p-7f */ -#define DIVBY32768 0.000030517578125f /* 0x1p-15f */ -#define DIVBY8388607 0.00000011920930376163766f /* 0x1.000002p-23f */ +#define DIVBY128 0.0078125f // 0x1p-7f +#define DIVBY32768 0.000030517578125f // 0x1p-15f +#define DIVBY8388607 0.00000011920930376163766f // 0x1.000002p-23f static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples) { @@ -556,25 +555,25 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam src += num_samples - 1; dst += num_samples - 1; - /* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */ + // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) { *dst = ((float)*src) * DIVBY128; } src -= 15; - dst -= 15; /* adjust to read NEON blocks from the start. */ + dst -= 15; // adjust to read NEON blocks from the start. SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const int8_t *mmsrc = (const int8_t *)src; const float32x4_t divby128 = vdupq_n_f32(DIVBY128); - while (i >= 16) { /* 16 * 8-bit */ - const int8x16_t bytes = vld1q_s8(mmsrc); /* get 16 sint8 into a NEON register. */ - const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); /* convert top 8 bytes to 8 int16 */ - const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); /* convert bottom 8 bytes to 8 int16 */ - /* split int16 to two int32, then convert to float, then multiply to normalize, store. */ + while (i >= 16) { // 16 * 8-bit + const int8x16_t bytes = vld1q_s8(mmsrc); // get 16 sint8 into a NEON register. + const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); // convert top 8 bytes to 8 int16 + const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); // convert bottom 8 bytes to 8 int16 + // split int16 to two int32, then convert to float, then multiply to normalize, store. vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128)); vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128)); vst1q_f32(dst + 8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128)); @@ -588,9 +587,9 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam } src += 15; - dst += 15; /* adjust for any scalar finishing. */ + dst += 15; // adjust for any scalar finishing. - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { *dst = ((float)*src) * DIVBY128; i--; @@ -608,26 +607,26 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam src += num_samples - 1; dst += num_samples - 1; - /* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */ + // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) { *dst = (((float)*src) * DIVBY128) - 1.0f; } src -= 15; - dst -= 15; /* adjust to read NEON blocks from the start. */ + dst -= 15; // adjust to read NEON blocks from the start. SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const uint8_t *mmsrc = (const uint8_t *)src; const float32x4_t divby128 = vdupq_n_f32(DIVBY128); const float32x4_t negone = vdupq_n_f32(-1.0f); - while (i >= 16) { /* 16 * 8-bit */ - const uint8x16_t bytes = vld1q_u8(mmsrc); /* get 16 uint8 into a NEON register. */ - const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); /* convert top 8 bytes to 8 uint16 */ - const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); /* convert bottom 8 bytes to 8 uint16 */ - /* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */ + while (i >= 16) { // 16 * 8-bit + const uint8x16_t bytes = vld1q_u8(mmsrc); // get 16 uint8 into a NEON register. + const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); // convert top 8 bytes to 8 uint16 + const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); // convert bottom 8 bytes to 8 uint16 + // split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128)); vst1q_f32(dst + 4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128)); vst1q_f32(dst + 8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128)); @@ -641,9 +640,9 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam } src += 15; - dst += 15; /* adjust for any scalar finishing. */ + dst += 15; // adjust for any scalar finishing. - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { *dst = (((float)*src) * DIVBY128) - 1.0f; i--; @@ -661,22 +660,22 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s src += num_samples - 1; dst += num_samples - 1; - /* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */ + // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) for (i = num_samples; i && (((size_t)(dst - 7)) & 15); --i, --src, --dst) { *dst = ((float)*src) * DIVBY32768; } src -= 7; - dst -= 7; /* adjust to read NEON blocks from the start. */ + dst -= 7; // adjust to read NEON blocks from the start. SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768); - while (i >= 8) { /* 8 * 16-bit */ - const int16x8_t ints = vld1q_s16((int16_t const *)src); /* get 8 sint16 into a NEON register. */ - /* split int16 to two int32, then convert to float, then multiply to normalize, store. */ + while (i >= 8) { // 8 * 16-bit + const int16x8_t ints = vld1q_s16((int16_t const *)src); // get 8 sint16 into a NEON register. + // split int16 to two int32, then convert to float, then multiply to normalize, store. vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(ints))), divby32768)); vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(ints))), divby32768)); i -= 8; @@ -686,9 +685,9 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s } src += 7; - dst += 7; /* adjust for any scalar finishing. */ + dst += 7; // adjust for any scalar finishing. - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { *dst = ((float)*src) * DIVBY32768; i--; @@ -703,20 +702,20 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)"); - /* Get dst aligned to 16 bytes */ + // Get dst aligned to 16 bytes for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { *dst = ((float)(*src >> 8)) * DIVBY8388607; } SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607); const int32_t *mmsrc = (const int32_t *)src; - while (i >= 4) { /* 4 * sint32 */ - /* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */ + while (i >= 4) { // 4 * sint32 + // shift out lowest bits so int fits in a float32. Small precision loss, but much faster. vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vshrq_n_s32(vld1q_s32(mmsrc), 8)), divby8388607)); i -= 4; mmsrc += 4; @@ -725,7 +724,7 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s src = (const Sint32 *)mmsrc; } - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { *dst = ((float)(*src >> 8)) * DIVBY8388607; i--; @@ -740,7 +739,7 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)"); - /* Get dst aligned to 16 bytes */ + // Get dst aligned to 16 bytes for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { const float sample = *src; if (sample >= 1.0f) { @@ -754,21 +753,21 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t one = vdupq_n_f32(1.0f); const float32x4_t negone = vdupq_n_f32(-1.0f); const float32x4_t mulby127 = vdupq_n_f32(127.0f); int8_t *mmdst = (int8_t *)dst; - while (i >= 16) { /* 16 * float32 */ - const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */ - const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */ - const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */ - const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */ - const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, narrow to sint8 */ - const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); /* narrow to sint16, combine, narrow to sint8 */ - vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); /* combine to int8x16_t, store out */ + while (i >= 16) { // 16 * float32 + const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); // load 4 floats, clamp, convert to sint32 + const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby127)); // load 4 floats, clamp, convert to sint32 + const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), mulby127)); // load 4 floats, clamp, convert to sint32 + const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), mulby127)); // load 4 floats, clamp, convert to sint32 + const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, narrow to sint8 + const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); // narrow to sint16, combine, narrow to sint8 + vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); // combine to int8x16_t, store out i -= 16; src += 16; mmdst += 16; @@ -776,7 +775,7 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam dst = (Sint8 *)mmdst; } - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { const float sample = *src; if (sample >= 1.0f) { @@ -798,7 +797,7 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)"); - /* Get dst aligned to 16 bytes */ + // Get dst aligned to 16 bytes for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { const float sample = *src; if (sample >= 1.0f) { @@ -812,21 +811,21 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t one = vdupq_n_f32(1.0f); const float32x4_t negone = vdupq_n_f32(-1.0f); const float32x4_t mulby127 = vdupq_n_f32(127.0f); uint8_t *mmdst = (uint8_t *)dst; - while (i >= 16) { /* 16 * float32 */ - const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */ - const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */ - const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */ - const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */ - const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, narrow to uint8 */ - const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); /* narrow to uint16, combine, narrow to uint8 */ - vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); /* combine to uint8x16_t, store out */ + while (i >= 16) { // 16 * float32 + const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 + const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 + const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 + const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 + const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); // narrow to uint16, combine, narrow to uint8 + const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); // narrow to uint16, combine, narrow to uint8 + vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); // combine to uint8x16_t, store out i -= 16; src += 16; mmdst += 16; @@ -835,7 +834,7 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam dst = (Uint8 *)mmdst; } - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { const float sample = *src; if (sample >= 1.0f) { @@ -857,7 +856,7 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)"); - /* Get dst aligned to 16 bytes */ + // Get dst aligned to 16 bytes for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { const float sample = *src; if (sample >= 1.0f) { @@ -871,17 +870,17 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s SDL_assert(!i || !(((size_t)dst) & 15)); - /* Make sure src is aligned too. */ + // Make sure src is aligned too. if (!(((size_t)src) & 15)) { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t one = vdupq_n_f32(1.0f); const float32x4_t negone = vdupq_n_f32(-1.0f); const float32x4_t mulby32767 = vdupq_n_f32(32767.0f); int16_t *mmdst = (int16_t *)dst; - while (i >= 8) { /* 8 * float32 */ - const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */ - const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */ - vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, store out. */ + while (i >= 8) { // 8 * float32 + const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); // load 4 floats, clamp, convert to sint32 + const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby32767)); // load 4 floats, clamp, convert to sint32 + vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, store out. i -= 8; src += 8; mmdst += 8; @@ -889,7 +888,7 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s dst = (Sint16 *)mmdst; } - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { const float sample = *src; if (sample >= 1.0f) { @@ -911,7 +910,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)"); - /* Get dst aligned to 16 bytes */ + // Get dst aligned to 16 bytes for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { const float sample = *src; if (sample >= 1.0f) { @@ -927,12 +926,12 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s SDL_assert(!i || !(((size_t)src) & 15)); { - /* Aligned! Do NEON blocks as long as we have 16 bytes available. */ + // Aligned! Do NEON blocks as long as we have 16 bytes available. const float32x4_t one = vdupq_n_f32(1.0f); const float32x4_t negone = vdupq_n_f32(-1.0f); const float32x4_t mulby8388607 = vdupq_n_f32(8388607.0f); int32_t *mmdst = (int32_t *)dst; - while (i >= 4) { /* 4 * float32 */ + while (i >= 4) { // 4 * float32 vst1q_s32(mmdst, vshlq_n_s32(vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby8388607)), 8)); i -= 4; src += 4; @@ -941,7 +940,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s dst = (Sint32 *)mmdst; } - /* Finish off any leftovers with scalar operations. */ + // Finish off any leftovers with scalar operations. while (i) { const float sample = *src; if (sample >= 1.0f) { @@ -958,7 +957,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s } #endif -/* Function pointers set to a CPU-specific implementation. */ +// Function pointers set to a CPU-specific implementation. void (*SDL_Convert_S8_to_F32)(float *dst, const Sint8 *src, int num_samples) = NULL; void (*SDL_Convert_U8_to_F32)(float *dst, const Uint8 *src, int num_samples) = NULL; void (*SDL_Convert_S16_to_F32)(float *dst, const Sint16 *src, int num_samples) = NULL; diff --git a/src/audio/SDL_mixer.c b/src/audio/SDL_mixer.c index 0a4992d8295bb..30b099346f488 100644 --- a/src/audio/SDL_mixer.c +++ b/src/audio/SDL_mixer.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* This provides the default mixing callback for the SDL audio routines */ +// This provides the default mixing callback for the SDL audio routines #include "SDL_sysaudio.h" @@ -77,12 +77,12 @@ static const Uint8 mix8[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -/* The volume ranges from 0 - 128 */ +// The volume ranges from 0 - 128 #define ADJUST_VOLUME(type, s, v) ((s) = (type)(((s) * (v)) / SDL_MIX_MAXVOLUME)) #define ADJUST_VOLUME_U8(s, v) ((s) = (Uint8)(((((s) - 128) * (v)) / SDL_MIX_MAXVOLUME) + 128)) -/* !!! FIXME: this needs some SIMD magic. */ +// !!! FIXME: this needs some SIMD magic. int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, Uint32 len, int volume) @@ -237,7 +237,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, float *dst32 = (float *)dst; float src1, src2; double dst_sample; - /* !!! FIXME: are these right? */ + // !!! FIXME: are these right? const double max_audioval = 3.402823466e+38F; const double min_audioval = -3.402823466e+38F; @@ -265,7 +265,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, float *dst32 = (float *)dst; float src1, src2; double dst_sample; - /* !!! FIXME: are these right? */ + // !!! FIXME: are these right? const double max_audioval = 3.402823466e+38F; const double min_audioval = -3.402823466e+38F; @@ -285,7 +285,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, } } break; - default: /* If this happens... FIXME! */ + default: // If this happens... FIXME! return SDL_SetError("SDL_MixAudioFormat(): unknown audio format"); } diff --git a/src/audio/aaudio/SDL_aaudio.h b/src/audio/aaudio/SDL_aaudio.h index b866f2ede525d..61cce54cf7113 100644 --- a/src/audio/aaudio/SDL_aaudio.h +++ b/src/audio/aaudio/SDL_aaudio.h @@ -35,4 +35,4 @@ void AAUDIO_PauseDevices(void); #endif -#endif /* SDL_aaudio_h_ */ +#endif // SDL_aaudio_h_ diff --git a/src/audio/aaudio/SDL_aaudiofuncs.h b/src/audio/aaudio/SDL_aaudiofuncs.h index febbb89da8123..0fba87d1ed7be 100644 --- a/src/audio/aaudio/SDL_aaudiofuncs.h +++ b/src/audio/aaudio/SDL_aaudiofuncs.h @@ -33,18 +33,18 @@ SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder * SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction)) SDL_PROC_UNUSED(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames)) SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode)) -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) /* API 28 */ -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) /* API 28 */ -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setInputPreset, (AAudioStreamBuilder * builder, aaudio_input_preset_t inputPreset)) /* API 28 */ -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setAllowedCapturePolicy, (AAudioStreamBuilder * builder, aaudio_allowed_capture_policy_t capturePolicy)) /* API 29 */ -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSessionId, (AAudioStreamBuilder * builder, aaudio_session_id_t sessionId)) /* API 28 */ -SDL_PROC_UNUSED(void, AAudioStreamBuilder_setPrivacySensitive, (AAudioStreamBuilder * builder, bool privacySensitive)) /* API 30 */ +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28 +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28 +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setInputPreset, (AAudioStreamBuilder * builder, aaudio_input_preset_t inputPreset)) // API 28 +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setAllowedCapturePolicy, (AAudioStreamBuilder * builder, aaudio_allowed_capture_policy_t capturePolicy)) // API 29 +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSessionId, (AAudioStreamBuilder * builder, aaudio_session_id_t sessionId)) // API 28 +SDL_PROC_UNUSED(void, AAudioStreamBuilder_setPrivacySensitive, (AAudioStreamBuilder * builder, bool privacySensitive)) // API 30 SDL_PROC(void, AAudioStreamBuilder_setDataCallback, (AAudioStreamBuilder * builder, AAudioStream_dataCallback callback, void *userData)) SDL_PROC(void, AAudioStreamBuilder_setFramesPerDataCallback, (AAudioStreamBuilder * builder, int32_t numFrames)) SDL_PROC(void, AAudioStreamBuilder_setErrorCallback, (AAudioStreamBuilder * builder, AAudioStream_errorCallback callback, void *userData)) SDL_PROC(aaudio_result_t, AAudioStreamBuilder_openStream, (AAudioStreamBuilder * builder, AAudioStream **stream)) SDL_PROC(aaudio_result_t, AAudioStreamBuilder_delete, (AAudioStreamBuilder * builder)) -SDL_PROC_UNUSED(aaudio_result_t, AAudioStream_release, (AAudioStream * stream)) /* API 30 */ +SDL_PROC_UNUSED(aaudio_result_t, AAudioStream_release, (AAudioStream * stream)) // API 30 SDL_PROC(aaudio_result_t, AAudioStream_close, (AAudioStream * stream)) SDL_PROC(aaudio_result_t, AAudioStream_requestStart, (AAudioStream * stream)) SDL_PROC(aaudio_result_t, AAudioStream_requestPause, (AAudioStream * stream)) @@ -70,13 +70,13 @@ SDL_PROC_UNUSED(aaudio_performance_mode_t, AAudioStream_getPerformanceMode, (AAu SDL_PROC_UNUSED(aaudio_direction_t, AAudioStream_getDirection, (AAudioStream * stream)) SDL_PROC_UNUSED(int64_t, AAudioStream_getFramesWritten, (AAudioStream * stream)) SDL_PROC_UNUSED(int64_t, AAudioStream_getFramesRead, (AAudioStream * stream)) -SDL_PROC_UNUSED(aaudio_session_id_t, AAudioStream_getSessionId, (AAudioStream * stream)) /* API 28 */ +SDL_PROC_UNUSED(aaudio_session_id_t, AAudioStream_getSessionId, (AAudioStream * stream)) // API 28 SDL_PROC(aaudio_result_t, AAudioStream_getTimestamp, (AAudioStream * stream, clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds)) -SDL_PROC_UNUSED(aaudio_usage_t, AAudioStream_getUsage, (AAudioStream * stream)) /* API 28 */ -SDL_PROC_UNUSED(aaudio_content_type_t, AAudioStream_getContentType, (AAudioStream * stream)) /* API 28 */ -SDL_PROC_UNUSED(aaudio_input_preset_t, AAudioStream_getInputPreset, (AAudioStream * stream)) /* API 28 */ -SDL_PROC_UNUSED(aaudio_allowed_capture_policy_t, AAudioStream_getAllowedCapturePolicy, (AAudioStream * stream)) /* API 29 */ -SDL_PROC_UNUSED(bool, AAudioStream_isPrivacySensitive, (AAudioStream * stream)) /* API 30 */ +SDL_PROC_UNUSED(aaudio_usage_t, AAudioStream_getUsage, (AAudioStream * stream)) // API 28 +SDL_PROC_UNUSED(aaudio_content_type_t, AAudioStream_getContentType, (AAudioStream * stream)) // API 28 +SDL_PROC_UNUSED(aaudio_input_preset_t, AAudioStream_getInputPreset, (AAudioStream * stream)) // API 28 +SDL_PROC_UNUSED(aaudio_allowed_capture_policy_t, AAudioStream_getAllowedCapturePolicy, (AAudioStream * stream)) // API 29 +SDL_PROC_UNUSED(bool, AAudioStream_isPrivacySensitive, (AAudioStream * stream)) // API 30 #undef SDL_PROC #undef SDL_PROC_UNUSED diff --git a/src/audio/alsa/SDL_alsa_audio.h b/src/audio/alsa/SDL_alsa_audio.h index ef7ce1bb5c3e9..2d41b3f1cc4b7 100644 --- a/src/audio/alsa/SDL_alsa_audio.h +++ b/src/audio/alsa/SDL_alsa_audio.h @@ -29,14 +29,14 @@ struct SDL_PrivateAudioData { - /* The audio device handle */ + // The audio device handle snd_pcm_t *pcm_handle; - /* Raw mixing buffer */ + // Raw mixing buffer Uint8 *mixbuf; - /* swizzle function */ + // swizzle function void (*swizzle_func)(SDL_AudioDevice *_this, void *buffer, Uint32 bufferlen); }; -#endif /* SDL_ALSA_audio_h_ */ +#endif // SDL_ALSA_audio_h_ diff --git a/src/audio/android/SDL_androidaudio.h b/src/audio/android/SDL_androidaudio.h index 759951129e4cc..5efdc419d0da0 100644 --- a/src/audio/android/SDL_androidaudio.h +++ b/src/audio/android/SDL_androidaudio.h @@ -35,4 +35,4 @@ static void ANDROIDAUDIO_PauseDevices(void) {} #endif -#endif /* SDL_androidaudio_h_ */ +#endif // SDL_androidaudio_h_ diff --git a/src/audio/coreaudio/SDL_coreaudio.h b/src/audio/coreaudio/SDL_coreaudio.h index 4b7f81bf06717..6c4891da2a0d5 100644 --- a/src/audio/coreaudio/SDL_coreaudio.h +++ b/src/audio/coreaudio/SDL_coreaudio.h @@ -39,7 +39,7 @@ #include #include -/* Things named "Master" were renamed to "Main" in macOS 12.0's SDK. */ +// Things named "Master" were renamed to "Main" in macOS 12.0's SDK. #ifdef MACOSX_COREAUDIO #include #ifndef MAC_OS_VERSION_12_0 @@ -65,4 +65,4 @@ struct SDL_PrivateAudioData #endif }; -#endif /* SDL_coreaudio_h_ */ +#endif // SDL_coreaudio_h_ diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 998bda154f03a..923eb8fe60d71 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -79,9 +79,9 @@ static OSStatus DeviceAliveNotification(AudioObjectID devid, UInt32 num_addr, co SDL_bool dead = SDL_FALSE; if (error == kAudioHardwareBadDeviceError) { - dead = SDL_TRUE; /* device was unplugged. */ + dead = SDL_TRUE; // device was unplugged. } else if ((error == kAudioHardwareNoError) && (!alive)) { - dead = SDL_TRUE; /* device died in some other way. */ + dead = SDL_TRUE; // device died in some other way. } if (dead) { @@ -263,7 +263,7 @@ static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioD AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL); - /* Get the Device ID */ + // Get the Device ID UInt32 size; AudioDeviceID devid; @@ -428,7 +428,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b /* AVAudioSessionCategoryOptionAllowBluetooth isn't available in the SDK for Apple TV but is still needed in order to output to Bluetooth devices. */ - options |= 0x4; /* AVAudioSessionCategoryOptionAllowBluetooth; */ + options |= 0x4; // AVAudioSessionCategoryOptionAllowBluetooth; } if (category == AVAudioSessionCategoryPlayAndRecord) { options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP | @@ -441,7 +441,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) { if (![session.category isEqualToString:category] || session.categoryOptions != options) { - /* Stop the current session so we don't interrupt other application audio */ + // Stop the current session so we don't interrupt other application audio PauseAudioDevices(); [session setActive:NO error:nil]; session_active = SDL_FALSE; @@ -454,7 +454,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b } } else { if (![session.category isEqualToString:category]) { - /* Stop the current session so we don't interrupt other application audio */ + // Stop the current session so we don't interrupt other application audio PauseAudioDevices(); [session setActive:NO error:nil]; session_active = SDL_FALSE; @@ -498,7 +498,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b /* An interruption end notification is not guaranteed to be sent if we were previously interrupted... resuming if needed when the app becomes active seems to be the way to go. */ - // Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications. johna + // Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications. [center addObserver:listener selector:@selector(applicationBecameActive:) name:UIApplicationDidBecomeActiveNotification @@ -717,7 +717,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); // make sure this is correct. - /* Set the channel layout for the audio queue */ + // Set the channel layout for the audio queue AudioChannelLayout layout; SDL_zero(layout); switch (device->spec.channels) { @@ -740,7 +740,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A; break; case 7: - /* FIXME: Need to move channel[4] (BC) to channel[6] */ + // FIXME: Need to move channel[4] (BC) to channel[6] layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A; break; case 8: @@ -763,7 +763,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) int numAudioBuffers = 2; const double msecs = (device->sample_frames / ((double)device->spec.freq)) * 1000.0; - if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { /* use more buffers if we have a VERY small sample set. */ + if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { // use more buffers if we have a VERY small sample set. numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2); } @@ -782,7 +782,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) CHECK_RESULT("AudioQueueAllocateBuffer"); SDL_memset(device->hidden->audioBuffer[i]->mAudioData, device->silence_value, device->hidden->audioBuffer[i]->mAudioDataBytesCapacity); device->hidden->audioBuffer[i]->mAudioDataByteSize = device->hidden->audioBuffer[i]->mAudioDataBytesCapacity; - /* !!! FIXME: should we use AudioQueueEnqueueBufferWithParameters and specify all frames be "trimmed" so these are immediately ready to refill with SDL callback data? */ + // !!! FIXME: should we use AudioQueueEnqueueBufferWithParameters and specify all frames be "trimmed" so these are immediately ready to refill with SDL callback data? result = AudioQueueEnqueueBuffer(device->hidden->audioQueue, device->hidden->audioBuffer[i], 0, NULL); CHECK_RESULT("AudioQueueEnqueueBuffer"); } @@ -831,7 +831,7 @@ static int AudioQueueThreadEntry(void *arg) static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) { - /* Initialize all variables that we clean on shutdown */ + // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { return SDL_OutOfMemory(); @@ -842,7 +842,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) return -1; } - /* Stop CoreAudio from doing expensive audio rate conversion */ + // Stop CoreAudio from doing expensive audio rate conversion @autoreleasepool { AVAudioSession *session = [AVAudioSession sharedInstance]; [session setPreferredSampleRate:device->spec.freq error:nil]; @@ -856,12 +856,12 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) device->spec.channels = session.preferredOutputNumberOfChannels; } #else - /* Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS */ - #endif /* TARGET_OS_TV */ + // Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS + #endif // TARGET_OS_TV } #endif - /* Setup a AudioStreamBasicDescription with the requested format */ + // Setup a AudioStreamBasicDescription with the requested format AudioStreamBasicDescription *strdesc = &device->hidden->strdesc; strdesc->mFormatID = kAudioFormatLinearPCM; strdesc->mFormatFlags = kLinearPCMFormatFlagIsPacked; @@ -872,7 +872,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); SDL_AudioFormat test_format; while ((test_format = *(closefmts++)) != 0) { - /* CoreAudio handles most of SDL's formats natively. */ + // CoreAudio handles most of SDL's formats natively. switch (test_format) { case SDL_AUDIO_U8: case SDL_AUDIO_S8: @@ -890,7 +890,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) break; } - if (!test_format) { /* shouldn't happen, but just in case... */ + if (!test_format) { // shouldn't happen, but just in case... return SDL_SetError("%s: Unsupported audio format", "coreaudio"); } device->spec.format = test_format; @@ -914,10 +914,10 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) } #endif - /* This has to init in a new thread so it can get its own CFRunLoop. :/ */ + // This has to init in a new thread so it can get its own CFRunLoop. :/ device->hidden->ready_semaphore = SDL_CreateSemaphore(0); if (!device->hidden->ready_semaphore) { - return -1; /* oh well. */ + return -1; // oh well. } char threadname[64]; @@ -951,7 +951,6 @@ static void COREAUDIO_DeinitializeStart(void) static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) { - /* Set the function pointers */ impl->OpenDevice = COREAUDIO_OpenDevice; impl->PlayDevice = COREAUDIO_PlayDevice; impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf; @@ -971,11 +970,11 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->HasCaptureSupport = SDL_TRUE; - return SDL_TRUE; /* this audio target is available. */ + return SDL_TRUE; } AudioBootStrap COREAUDIO_bootstrap = { "coreaudio", "CoreAudio", COREAUDIO_Init, SDL_FALSE }; -#endif /* SDL_AUDIO_DRIVER_COREAUDIO */ +#endif // SDL_AUDIO_DRIVER_COREAUDIO diff --git a/src/audio/disk/SDL_diskaudio.h b/src/audio/disk/SDL_diskaudio.h index bdc734bdf8dd3..97930b0b141e5 100644 --- a/src/audio/disk/SDL_diskaudio.h +++ b/src/audio/disk/SDL_diskaudio.h @@ -27,10 +27,10 @@ struct SDL_PrivateAudioData { - /* The file descriptor for the audio device */ + // The file descriptor for the audio device SDL_RWops *io; Uint32 io_delay; Uint8 *mixbuf; }; -#endif /* SDL_diskaudio_h_ */ +#endif // SDL_diskaudio_h_ diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index b75b6d9f20d58..22d3923d792a7 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -24,8 +24,8 @@ #ifdef SDL_AUDIO_DRIVER_OSS -#include /* For perror() */ -#include /* For strerror() */ +#include // For perror() +#include // For strerror() #include #include #include @@ -97,7 +97,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Couldn't get audio format list"); } - /* Try for a closest match on audio format */ + // Try for a closest match on audio format int format = 0; SDL_AudioFormat test_format; const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); @@ -156,7 +156,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) } device->spec.freq = value; - /* Calculate the final parameters for this audio specification */ + // Calculate the final parameters for this audio specification SDL_UpdatedAudioDeviceFormat(device); /* Determine the power of two of the fragment size @@ -168,9 +168,9 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) while ((0x01U << frag_spec) < device->buffer_size) { frag_spec++; } - frag_spec |= 0x00020000; /* two fragments, for low latency */ + frag_spec |= 0x00020000; // two fragments, for low latency - /* Set the audio buffering parameters */ + // Set the audio buffering parameters #ifdef DEBUG_AUDIO fprintf(stderr, "Requesting %d fragments of size %d\n", (frag_spec >> 16), 1 << (frag_spec & 0xFFFF)); @@ -189,7 +189,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) } #endif - /* Allocate mixing buffer */ + // Allocate mixing buffer if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (device->hidden->mixbuf == NULL) { @@ -269,8 +269,8 @@ static void DSP_FlushCapture(SDL_AudioDevice *device) static SDL_bool InitTimeDevicesExist = SDL_FALSE; static SDL_bool look_for_devices_test(int fd) { - InitTimeDevicesExist = SDL_TRUE; /* note that _something_ exists. */ - /* Don't add to the device list, we're just seeing if any devices exist. */ + InitTimeDevicesExist = SDL_TRUE; // note that _something_ exists. + // Don't add to the device list, we're just seeing if any devices exist. return SDL_FALSE; } @@ -280,10 +280,9 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl) SDL_EnumUnixAudioDevices(SDL_FALSE, look_for_devices_test); if (!InitTimeDevicesExist) { SDL_SetError("dsp: No such audio device"); - return SDL_FALSE; /* maybe try a different backend. */ + return SDL_FALSE; // maybe try a different backend. } - /* Set the function pointers */ impl->DetectDevices = DSP_DetectDevices; impl->OpenDevice = DSP_OpenDevice; impl->WaitDevice = DSP_WaitDevice; @@ -296,11 +295,11 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl) impl->HasCaptureSupport = SDL_TRUE; - return SDL_TRUE; /* this audio target is available. */ + return SDL_TRUE; } AudioBootStrap DSP_bootstrap = { "dsp", "Open Sound System (/dev/dsp)", DSP_Init, SDL_FALSE }; -#endif /* SDL_AUDIO_DRIVER_OSS */ +#endif // SDL_AUDIO_DRIVER_OSS diff --git a/src/audio/dsp/SDL_dspaudio.h b/src/audio/dsp/SDL_dspaudio.h index abe0c347df3fb..00d329be5b364 100644 --- a/src/audio/dsp/SDL_dspaudio.h +++ b/src/audio/dsp/SDL_dspaudio.h @@ -27,11 +27,11 @@ struct SDL_PrivateAudioData { - /* The file descriptor for the audio device */ + // The file descriptor for the audio device int audio_fd; - /* Raw mixing buffer */ + // Raw mixing buffer Uint8 *mixbuf; }; -#endif /* SDL_dspaudio_h_ */ +#endif // SDL_dspaudio_h_ diff --git a/src/audio/emscripten/SDL_emscriptenaudio.h b/src/audio/emscripten/SDL_emscriptenaudio.h index cc2f49b27397a..89a08a9655b45 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.h +++ b/src/audio/emscripten/SDL_emscriptenaudio.h @@ -30,4 +30,4 @@ struct SDL_PrivateAudioData Uint8 *mixbuf; }; -#endif /* SDL_emscriptenaudio_h_ */ +#endif // SDL_emscriptenaudio_h_ diff --git a/src/audio/haiku/SDL_haikuaudio.h b/src/audio/haiku/SDL_haikuaudio.h index c78c6061dd4a5..9187ef642291e 100644 --- a/src/audio/haiku/SDL_haikuaudio.h +++ b/src/audio/haiku/SDL_haikuaudio.h @@ -32,4 +32,4 @@ struct SDL_PrivateAudioData int current_buffer_len; }; -#endif /* SDL_haikuaudio_h_ */ +#endif // SDL_haikuaudio_h_ diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 4f0691bc3dde3..1521eb697af46 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -53,19 +53,19 @@ static int load_jack_syms(void); static const char *jack_library = SDL_AUDIO_DRIVER_JACK_DYNAMIC; static void *jack_handle = NULL; -/* !!! FIXME: this is copy/pasted in several places now */ +// !!! FIXME: this is copy/pasted in several places now static int load_jack_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(jack_handle, fn); if (*addr == NULL) { - /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ + // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } return 1; } -/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +// cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_JACK_SYM(x) \ if (!load_jack_sym(#x, (void **)(char *)&JACK_##x)) \ return -1 @@ -85,7 +85,7 @@ static int LoadJackLibrary(void) jack_handle = SDL_LoadObject(jack_library); if (jack_handle == NULL) { retval = -1; - /* Don't call SDL_SetError(): SDL_LoadObject already did. */ + // Don't call SDL_SetError(): SDL_LoadObject already did. } else { retval = load_jack_syms(); if (retval < 0) { @@ -110,7 +110,7 @@ static int LoadJackLibrary(void) return 0; } -#endif /* SDL_AUDIO_DRIVER_JACK_DYNAMIC */ +#endif // SDL_AUDIO_DRIVER_JACK_DYNAMIC static int load_jack_syms(void) { @@ -137,7 +137,7 @@ static int load_jack_syms(void) return 0; } -static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. */ +static void jackShutdownCallback(void *arg) // JACK went away; device is lost. { SDL_AudioDeviceDisconnected((SDL_AudioDevice *)arg); } @@ -294,7 +294,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) int ports = 0; int i; - /* Initialize all variables that we clean on shutdown */ + // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { return SDL_OutOfMemory(); @@ -314,16 +314,16 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) } while (devports[++ports]) { - /* spin to count devports */ + // spin to count devports } - /* Filter out non-audio ports */ + // Filter out non-audio ports audio_ports = SDL_calloc(ports, sizeof(*audio_ports)); for (i = 0; i < ports; i++) { const jack_port_t *dport = JACK_jack_port_by_name(client, devports[i]); const char *type = JACK_jack_port_type(dport); const int len = SDL_strlen(type); - /* See if type ends with "audio" */ + // See if type ends with "audio" if (len >= 5 && !SDL_memcmp(type + len - 5, "audio", 5)) { audio_ports[channels++] = i; } @@ -335,7 +335,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) /* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */ - /* Jack pretty much demands what it wants. */ + // Jack pretty much demands what it wants. device->spec.format = SDL_AUDIO_F32; device->spec.freq = JACK_jack_get_sample_rate(client); device->spec.channels = channels; @@ -351,7 +351,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) } } - /* Build SDL's ports, which we will connect to the device ports. */ + // Build SDL's ports, which we will connect to the device ports. device->hidden->sdlports = (jack_port_t **)SDL_calloc(channels, sizeof(jack_port_t *)); if (device->hidden->sdlports == NULL) { SDL_free(audio_ports); @@ -386,7 +386,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Failed to activate JACK client"); } - /* once activated, we can connect all the ports. */ + // once activated, we can connect all the ports. for (i = 0; i < channels; i++) { const char *sdlport = JACK_jack_port_name(device->hidden->sdlports[i]); const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport; @@ -397,11 +397,11 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) } } - /* don't need these anymore. */ + // don't need these anymore. JACK_jack_free(devports); SDL_free(audio_ports); - /* We're ready to rock and roll. :-) */ + // We're ready to rock and roll. :-) return 0; } @@ -415,7 +415,7 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) if (LoadJackLibrary() < 0) { return SDL_FALSE; } else { - /* Make sure a JACK server is running and available. */ + // Make sure a JACK server is running and available. jack_status_t status; jack_client_t *client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL); if (client == NULL) { @@ -425,7 +425,6 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) JACK_jack_client_close(client); } - /* Set the function pointers */ impl->OpenDevice = JACK_OpenDevice; impl->GetDeviceBuf = JACK_GetDeviceBuf; impl->PlayDevice = JACK_PlayDevice; @@ -438,11 +437,11 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) impl->HasCaptureSupport = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE; - return SDL_TRUE; /* this audio target is available. */ + return SDL_TRUE; } AudioBootStrap JACK_bootstrap = { "jack", "JACK Audio Connection Kit", JACK_Init, SDL_FALSE }; -#endif /* SDL_AUDIO_DRIVER_JACK */ +#endif // SDL_AUDIO_DRIVER_JACK diff --git a/src/audio/jack/SDL_jackaudio.h b/src/audio/jack/SDL_jackaudio.h index a8cf81d4fa2d1..9a9d082f85104 100644 --- a/src/audio/jack/SDL_jackaudio.h +++ b/src/audio/jack/SDL_jackaudio.h @@ -32,4 +32,4 @@ struct SDL_PrivateAudioData float *iobuffer; }; -#endif /* SDL_jackaudio_h_ */ +#endif // SDL_jackaudio_h_ diff --git a/src/audio/n3ds/SDL_n3dsaudio.h b/src/audio/n3ds/SDL_n3dsaudio.h index 83f9ca83c98c5..eb47ab19ed58b 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.h +++ b/src/audio/n3ds/SDL_n3dsaudio.h @@ -24,11 +24,11 @@ #include <3ds.h> -#define NUM_BUFFERS 2 /* -- Don't lower this! */ +#define NUM_BUFFERS 2 // -- Don't lower this! struct SDL_PrivateAudioData { - /* Speaker data */ + // Speaker data Uint8 *mixbuf; Uint32 nextbuf; ndspWaveBuf waveBuf[NUM_BUFFERS]; @@ -37,4 +37,4 @@ struct SDL_PrivateAudioData SDL_bool isCancelled; }; -#endif /* SDL_n3dsaudio_h */ +#endif // SDL_n3dsaudio_h diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index 0340bfb23f284..4aba643a6c860 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -135,7 +135,7 @@ static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) } else if (iscapture && (remain < device->buffer_size)) { SDL_Delay(10); } else { - break; /* ready to go! */ + break; // ready to go! } } diff --git a/src/audio/netbsd/SDL_netbsdaudio.h b/src/audio/netbsd/SDL_netbsdaudio.h index 9c1d93c52d895..72bbacfe9df28 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.h +++ b/src/audio/netbsd/SDL_netbsdaudio.h @@ -27,18 +27,18 @@ struct SDL_PrivateAudioData { - /* The file descriptor for the audio device */ + // The file descriptor for the audio device int audio_fd; - /* Raw mixing buffer */ + // Raw mixing buffer Uint8 *mixbuf; int mixlen; - /* Support for audio timing using a timer, in addition to SDL_IOReady() */ + // Support for audio timing using a timer, in addition to SDL_IOReady() float frame_ticks; float next_frame; }; -#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ +#define FUDGE_TICKS 10 // The scheduler overhead ticks per frame -#endif /* SDL_netbsdaudio_h_ */ +#endif // SDL_netbsdaudio_h_ diff --git a/src/audio/openslES/SDL_openslES.h b/src/audio/openslES/SDL_openslES.h index 74d0da445d1ab..a13e11129d935 100644 --- a/src/audio/openslES/SDL_openslES.h +++ b/src/audio/openslES/SDL_openslES.h @@ -35,4 +35,4 @@ static void OPENSLES_PauseDevices(void) {} #endif -#endif /* SDL_openslesaudio_h_ */ +#endif // SDL_openslesaudio_h_ diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index b5cbbe74c1afc..9c46d770b3f38 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -63,7 +63,7 @@ * This seems to be a sane lower limit as Pipewire * uses it in several of it's own modules. */ -#define PW_MIN_SAMPLES 32 /* About 0.67ms at 48kHz */ +#define PW_MIN_SAMPLES 32 // About 0.67ms at 48kHz #define PW_BASE_CLOCK_RATE 48000 #define PW_POD_BUFFER_LENGTH 1024 @@ -82,7 +82,7 @@ enum PW_READY_FLAGS static SDL_bool pipewire_initialized = SDL_FALSE; -/* Pipewire entry points */ +// Pipewire entry points static const char *(*PIPEWIRE_pw_get_library_version)(void); static void (*PIPEWIRE_pw_init)(int *, char ***); static void (*PIPEWIRE_pw_deinit)(void); @@ -127,7 +127,7 @@ static int pipewire_dlsym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pipewire_handle, fn); if (*addr == NULL) { - /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ + // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } @@ -163,10 +163,11 @@ static int load_pipewire_library(void) } static void unload_pipewire_library(void) -{ /* Nothing to do */ +{ + // Nothing to do } -#endif /* SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC */ +#endif // SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC static int load_pipewire_syms(void) { @@ -220,7 +221,7 @@ static int init_pipewire_library(void) return -1; } - /* SDL can build against 0.3.20, but requires 0.3.24 */ + // SDL can build against 0.3.20, but requires 0.3.24 if (pipewire_version_at_least(0, 3, 24)) { PIPEWIRE_pw_init(NULL, NULL); return 0; @@ -237,7 +238,7 @@ static void deinit_pipewire_library(void) unload_pipewire_library(); } -/* A generic Pipewire node object used for enumeration. */ +// A generic Pipewire node object used for enumeration. struct node_object { struct spa_list link; @@ -260,7 +261,7 @@ struct node_object struct spa_hook core_listener; }; -/* A sink/source node used for stream I/O. */ +// A sink/source node used for stream I/O. struct io_node { struct spa_list link; @@ -269,13 +270,13 @@ struct io_node SDL_bool is_capture; SDL_AudioSpec spec; - const char *name; /* Friendly name */ - const char *path; /* OS identifier (i.e. ALSA endpoint) */ + const char *name; // Friendly name + const char *path; // OS identifier (i.e. ALSA endpoint) - char buf[]; /* Buffer to hold the name and path strings. */ + char buf[]; // Buffer to hold the name and path strings. }; -/* The global hotplug thread and associated objects. */ +// The global hotplug thread and associated objects. static struct pw_thread_loop *hotplug_loop; static struct pw_core *hotplug_core; static struct pw_context *hotplug_context; @@ -291,13 +292,13 @@ static SDL_bool hotplug_events_enabled; static char *pipewire_default_sink_id = NULL; static char *pipewire_default_source_id = NULL; -/* The active node list */ +// The active node list static SDL_bool io_list_check_add(struct io_node *node) { struct io_node *n; SDL_bool ret = SDL_TRUE; - /* See if the node is already in the list */ + // See if the node is already in the list spa_list_for_each (n, &hotplug_io_list, link) { if (n->id == node->id) { ret = SDL_FALSE; @@ -305,7 +306,7 @@ static SDL_bool io_list_check_add(struct io_node *node) } } - /* Add to the list if the node doesn't already exist */ + // Add to the list if the node doesn't already exist spa_list_append(&hotplug_io_list, &node->link); if (hotplug_events_enabled) { @@ -321,7 +322,7 @@ static void io_list_remove(Uint32 id) { struct io_node *n, *temp; - /* Find and remove the node from the list */ + // Find and remove the node from the list spa_list_for_each_safe (n, temp, &hotplug_io_list, link) { if (n->id == id) { spa_list_remove(&n->link); @@ -369,7 +370,7 @@ static void node_object_destroy(struct node_object *node) PIPEWIRE_pw_proxy_destroy(node->proxy); } -/* The pending node list */ +// The pending node list static void pending_list_add(struct node_object *node) { SDL_assert(node); @@ -401,7 +402,7 @@ static void *node_object_new(Uint32 id, const char *type, Uint32 version, const struct pw_proxy *proxy; struct node_object *node; - /* Create the proxy object */ + // Create the proxy object proxy = pw_registry_bind(hotplug_registry, id, type, version, sizeof(struct node_object)); if (proxy == NULL) { SDL_SetError("Pipewire: Failed to create proxy object (%i)", errno); @@ -414,24 +415,24 @@ static void *node_object_new(Uint32 id, const char *type, Uint32 version, const node->id = id; node->proxy = proxy; - /* Add the callbacks */ + // Add the callbacks pw_core_add_listener(hotplug_core, &node->core_listener, core_events, node); PIPEWIRE_pw_proxy_add_object_listener(node->proxy, &node->node_listener, funcs, node); - /* Add the node to the active list */ + // Add the node to the active list pending_list_add(node); return node; } -/* Core sync points */ +// Core sync points static void core_events_hotplug_init_callback(void *object, uint32_t id, int seq) { if (id == PW_ID_CORE && seq == hotplug_init_seq_val) { - /* This core listener is no longer needed. */ + // This core listener is no longer needed. spa_hook_remove(&hotplug_core_listener); - /* Signal that the initial I/O list is populated */ + // Signal that the initial I/O list is populated hotplug_init_complete = SDL_TRUE; PIPEWIRE_pw_thread_loop_signal(hotplug_loop, false); } @@ -483,7 +484,7 @@ static void hotplug_core_sync(struct node_object *node) } } -/* Helpers for retrieving values from params */ +// Helpers for retrieving values from params static SDL_bool get_range_param(const struct spa_pod *param, Uint32 key, int *def, int *min, int *max) { const struct spa_pod_prop *prop; @@ -535,7 +536,7 @@ static SDL_bool get_int_param(const struct spa_pod *param, Uint32 key, int *val) return SDL_FALSE; } -/* Interface node callbacks */ +// Interface node callbacks static void node_event_info(void *object, const struct pw_node_info *info) { struct node_object *node = object; @@ -549,7 +550,7 @@ static void node_event_info(void *object, const struct pw_node_info *info) io->spec.channels = (Uint8)SDL_atoi(prop_val); } - /* Need to parse the parameters to get the sample rate */ + // Need to parse the parameters to get the sample rate for (i = 0; i < info->n_params; ++i) { pw_node_enum_params(node->proxy, 0, info->params[i].id, 0, 0, NULL); } @@ -563,7 +564,7 @@ static void node_event_param(void *object, int seq, uint32_t id, uint32_t index, struct node_object *node = object; struct io_node *io = node->userdata; - /* Get the default frequency */ + // Get the default frequency if (io->spec.freq == 0) { get_range_param(param, SPA_FORMAT_AUDIO_rate, &io->spec.freq, NULL, NULL); } @@ -586,19 +587,19 @@ static const struct pw_node_events interface_node_events = { PW_VERSION_NODE_EVE static char *get_name_from_json(const char *json) { struct spa_json parser[2]; - char key[7]; /* "name" */ + char key[7]; // "name" char value[PW_MAX_IDENTIFIER_LENGTH]; spa_json_init(&parser[0], json, SDL_strlen(json)); if (spa_json_enter_object(&parser[0], &parser[1]) <= 0) { - /* Not actually JSON */ + // Not actually JSON return NULL; } if (spa_json_get_string(&parser[1], key, sizeof(key)) <= 0) { - /* Not actually a key/value pair */ + // Not actually a key/value pair return NULL; } if (spa_json_get_string(&parser[1], value, sizeof(value)) <= 0) { - /* Somehow had a key with no value? */ + // Somehow had a key with no value? return NULL; } return SDL_strdup(value); @@ -617,7 +618,7 @@ static void change_default_device(const char *path) } } -/* Metadata node callback */ +// Metadata node callback static int metadata_property(void *object, Uint32 subject, const char *key, const char *type, const char *value) { struct node_object *node = object; @@ -645,13 +646,13 @@ static int metadata_property(void *object, Uint32 subject, const char *key, cons static const struct pw_metadata_events metadata_node_events = { PW_VERSION_METADATA_EVENTS, .property = metadata_property }; -/* Global registry callbacks */ +// Global registry callbacks static void registry_event_global_callback(void *object, uint32_t id, uint32_t permissions, const char *type, uint32_t version, const struct spa_dict *props) { struct node_object *node; - /* We're only interested in interface and metadata nodes. */ + // We're only interested in interface and metadata nodes. if (!SDL_strcmp(type, PW_TYPE_INTERFACE_Node)) { const char *media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); @@ -663,7 +664,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p int desc_buffer_len; int path_buffer_len; - /* Just want sink and capture */ + // Just want sink and capture if (!SDL_strcasecmp(media_class, "Audio/Sink")) { is_capture = SDL_FALSE; } else if (!SDL_strcasecmp(media_class, "Audio/Source")) { @@ -682,7 +683,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p return; } - /* Allocate and initialize the I/O node information struct */ + // Allocate and initialize the I/O node information struct desc_buffer_len = SDL_strlen(node_desc) + 1; path_buffer_len = SDL_strlen(node_path) + 1; node->userdata = io = SDL_calloc(1, sizeof(struct io_node) + desc_buffer_len + path_buffer_len); @@ -692,16 +693,16 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p return; } - /* Begin setting the node properties */ + // Begin setting the node properties io->id = id; io->is_capture = is_capture; - io->spec.format = SDL_AUDIO_F32; /* Pipewire uses floats internally, other formats require conversion. */ + io->spec.format = SDL_AUDIO_F32; // Pipewire uses floats internally, other formats require conversion. io->name = io->buf; io->path = io->buf + desc_buffer_len; SDL_strlcpy(io->buf, node_desc, desc_buffer_len); SDL_strlcpy(io->buf + desc_buffer_len, node_path, path_buffer_len); - /* Update sync points */ + // Update sync points hotplug_core_sync(node); } } @@ -712,7 +713,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p return; } - /* Update sync points */ + // Update sync points hotplug_core_sync(node); } } @@ -726,7 +727,7 @@ static void registry_event_remove_callback(void *object, uint32_t id) static const struct pw_registry_events registry_events = { PW_VERSION_REGISTRY_EVENTS, .global = registry_event_global_callback, .global_remove = registry_event_remove_callback }; -/* The hotplug thread */ +// The hotplug thread static int hotplug_loop_init(void) { int res; @@ -818,7 +819,7 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe PIPEWIRE_pw_thread_loop_lock(hotplug_loop); - /* Wait until the initial registry enumeration is complete */ + // Wait until the initial registry enumeration is complete if (!hotplug_init_complete) { PIPEWIRE_pw_thread_loop_wait(hotplug_loop); } @@ -839,7 +840,7 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); } -/* Channel maps that match the order in SDL_Audio.h */ +// Channel maps that match the order in SDL_Audio.h static const enum spa_audio_channel PIPEWIRE_channel_map_1[] = { SPA_AUDIO_CHANNEL_MONO }; static const enum spa_audio_channel PIPEWIRE_channel_map_2[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR }; static const enum spa_audio_channel PIPEWIRE_channel_map_3[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_LFE }; @@ -890,7 +891,7 @@ static void initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info break; } - /* Pipewire natively supports all of SDL's sample formats */ + // Pipewire natively supports all of SDL's sample formats switch (spec->format) { case SDL_AUDIO_U8: info->format = SPA_AUDIO_FORMAT_U8; @@ -1065,10 +1066,10 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) const SDL_bool iscapture = device->iscapture; int res; - /* Clamp the period size to sane values */ + // Clamp the period size to sane values const int min_period = PW_MIN_SAMPLES * SPA_MAX(device->spec.freq / PW_BASE_CLOCK_RATE, 1); - /* Get the hints for the application name, stream name and role */ + // Get the hints for the application name, stream name and role app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); if (app_name == NULL || *app_name == '\0') { app_name = SDL_GetHint(SDL_HINT_APP_NAME); @@ -1077,7 +1078,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) } } - /* App ID. Default to NULL if not available. */ + // App ID. Default to NULL if not available. app_id = SDL_GetHint(SDL_HINT_APP_ID); stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); @@ -1094,7 +1095,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) stream_role = "Game"; } - /* Initialize the Pipewire stream info from the SDL audio spec */ + // Initialize the Pipewire stream info from the SDL audio spec initialize_spa_info(&device->spec, &spa_info); params = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &spa_info); if (params == NULL) { @@ -1107,7 +1108,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } - /* Size of a single audio frame in bytes */ + // Size of a single audio frame in bytes priv->stride = SDL_AUDIO_FRAMESIZE(device->spec); if (device->sample_frames < min_period) { @@ -1122,7 +1123,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Pipewire: Failed to create stream loop (%i)", errno); } - /* Load the realtime module so Pipewire can set the loop thread to the appropriate priority. */ + // Load the realtime module so Pipewire can set the loop thread to the appropriate priority. props = PIPEWIRE_pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", NULL); if (props == NULL) { return SDL_SetError("Pipewire: Failed to create stream context properties (%i)", errno); @@ -1173,7 +1174,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) } } - /* Create the new stream */ + // Create the new stream priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props, iscapture ? &stream_input_events : &stream_output_events, device); if (priv->stream == NULL) { @@ -1191,7 +1192,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Pipewire: Failed to start stream loop"); } - /* Wait until all init flags are set or the stream has failed. */ + // Wait until all init flags are set or the stream has failed. PIPEWIRE_pw_thread_loop_lock(priv->loop); while (priv->stream_init_status != PW_READY_FLAG_ALL_BITS && PIPEWIRE_pw_stream_get_state(priv->stream, NULL) != PW_STREAM_STATE_ERROR) { @@ -1264,7 +1265,6 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) } } - /* Set the function pointers */ impl->DetectDevices = PIPEWIRE_DetectDevices; impl->OpenDevice = PIPEWIRE_OpenDevice; impl->DeinitializeStart = PIPEWIRE_DeinitializeStart; @@ -1283,4 +1283,4 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) AudioBootStrap PIPEWIRE_bootstrap = { "pipewire", "Pipewire", PIPEWIRE_Init, SDL_FALSE }; -#endif /* SDL_AUDIO_DRIVER_PIPEWIRE */ +#endif // SDL_AUDIO_DRIVER_PIPEWIRE diff --git a/src/audio/pipewire/SDL_pipewire.h b/src/audio/pipewire/SDL_pipewire.h index 5a6772ab52785..1350fffb14d94 100644 --- a/src/audio/pipewire/SDL_pipewire.h +++ b/src/audio/pipewire/SDL_pipewire.h @@ -33,11 +33,11 @@ struct SDL_PrivateAudioData struct pw_stream *stream; struct pw_context *context; - Sint32 stride; /* Bytes-per-frame */ + Sint32 stride; // Bytes-per-frame int stream_init_status; // Set in GetDeviceBuf, filled in AudioThreadIterate, queued in PlayDevice struct pw_buffer *pw_buf; }; -#endif /* SDL_pipewire_h_ */ +#endif // SDL_pipewire_h_ diff --git a/src/audio/ps2/SDL_ps2audio.h b/src/audio/ps2/SDL_ps2audio.h index b4ed26f10307f..5b5f71a8cf277 100644 --- a/src/audio/ps2/SDL_ps2audio.h +++ b/src/audio/ps2/SDL_ps2audio.h @@ -29,14 +29,14 @@ struct SDL_PrivateAudioData { - /* The hardware output channel. */ + // The hardware output channel. int channel; - /* The raw allocated mixing buffer. */ + // The raw allocated mixing buffer. Uint8 *rawbuf; - /* Individual mixing buffers. */ + // Individual mixing buffers. Uint8 *mixbufs[NUM_BUFFERS]; - /* Index of the next available mixing buffer. */ + // Index of the next available mixing buffer. int next_buffer; }; -#endif /* SDL_ps2audio_h_ */ +#endif // SDL_ps2audio_h_ diff --git a/src/audio/psp/SDL_pspaudio.h b/src/audio/psp/SDL_pspaudio.h index c030db82e0152..da535e2a72f9e 100644 --- a/src/audio/psp/SDL_pspaudio.h +++ b/src/audio/psp/SDL_pspaudio.h @@ -28,14 +28,14 @@ struct SDL_PrivateAudioData { - /* The hardware output channel. */ + // The hardware output channel. int channel; - /* The raw allocated mixing buffer. */ + // The raw allocated mixing buffer. Uint8 *rawbuf; - /* Individual mixing buffers. */ + // Individual mixing buffers. Uint8 *mixbufs[NUM_BUFFERS]; - /* Index of the next available mixing buffer. */ + // Index of the next available mixing buffer. int next_buffer; }; -#endif /* SDL_pspaudio_h_ */ +#endif // SDL_pspaudio_h_ diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 0703fc7401e69..2022156eaadeb 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -23,7 +23,7 @@ #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO -/* Allow access to a raw mixing buffer */ +// Allow access to a raw mixing buffer #ifdef HAVE_SIGNAL_H #include @@ -39,7 +39,7 @@ typedef void (*pa_operation_notify_cb_t) (pa_operation *o, void *userdata); #endif -/* should we include monitors in the device list? Set at SDL_Init time */ +// should we include monitors in the device list? Set at SDL_Init time static SDL_bool include_monitors = SDL_FALSE; static pa_threaded_mainloop *pulseaudio_threaded_mainloop = NULL; @@ -128,14 +128,14 @@ static int load_pulseaudio_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pulseaudio_handle, fn); if (*addr == NULL) { - /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ + // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } return 1; } -/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +// cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_PULSEAUDIO_SYM(x) \ if (!load_pulseaudio_sym(#x, (void **)(char *)&PULSEAUDIO_##x)) \ return -1 @@ -155,7 +155,7 @@ static int LoadPulseAudioLibrary(void) pulseaudio_handle = SDL_LoadObject(pulseaudio_library); if (pulseaudio_handle == NULL) { retval = -1; - /* Don't call SDL_SetError(): SDL_LoadObject already did. */ + // Don't call SDL_SetError(): SDL_LoadObject already did. } else { retval = load_pulseaudio_syms(); if (retval < 0) { @@ -180,7 +180,7 @@ static int LoadPulseAudioLibrary(void) return 0; } -#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC */ +#endif // SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC static int load_pulseaudio_syms(void) { @@ -231,7 +231,7 @@ static int load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_stream_set_read_callback); SDL_PULSEAUDIO_SYM(pa_context_get_server_info); - /* optional */ + // optional #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC load_pulseaudio_sym("pa_operation_set_state_callback", (void **)(char *)&PULSEAUDIO_pa_operation_set_state_callback); // needs pulseaudio 4.0 load_pulseaudio_sym("pa_threaded_mainloop_set_name", (void **)(char *)&PULSEAUDIO_pa_threaded_mainloop_set_name); // needs pulseaudio 5.0 @@ -254,7 +254,7 @@ static SDL_INLINE int squashVersion(const int major, const int minor, const int return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF); } -/* Workaround for older pulse: pa_context_new() must have non-NULL appname */ +// Workaround for older pulse: pa_context_new() must have non-NULL appname static const char *getAppName(void) { const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); @@ -266,12 +266,12 @@ static const char *getAppName(void) return retval; } else { const char *verstr = PULSEAUDIO_pa_get_library_version(); - retval = "SDL Application"; /* the "oh well" default. */ + retval = "SDL Application"; // the "oh well" default. if (verstr != NULL) { int maj, min, patch; if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) { if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) { - retval = NULL; /* 0.9.15+ handles NULL correctly. */ + retval = NULL; // 0.9.15+ handles NULL correctly. } } } @@ -288,7 +288,7 @@ static void OperationStateChangeCallback(pa_operation *o, void *userdata) you did the work in the callback and just want to know it's done, though. */ static void WaitForPulseOperation(pa_operation *o) { - /* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */ + // This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. SDL_assert(pulseaudio_threaded_mainloop != NULL); if (o) { // note that if PULSEAUDIO_pa_operation_set_state_callback == NULL, then `o` must have a callback that will signal pulseaudio_threaded_mainloop. @@ -299,7 +299,7 @@ static void WaitForPulseOperation(pa_operation *o) PULSEAUDIO_pa_operation_set_state_callback(o, OperationStateChangeCallback, NULL); } while (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); /* this releases the lock and blocks on an internal condition variable. */ + PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); // this releases the lock and blocks on an internal condition variable. } PULSEAUDIO_pa_operation_unref(o); } @@ -323,7 +323,7 @@ static void DisconnectFromPulseServer(void) static void PulseContextStateChangeCallback(pa_context *context, void *userdata) { - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* just signal any waiting code, it can look up the details. */ + PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details. } static int ConnectToPulseServer(void) @@ -334,7 +334,7 @@ static int ConnectToPulseServer(void) SDL_assert(pulseaudio_threaded_mainloop == NULL); SDL_assert(pulseaudio_context == NULL); - /* Set up a new main loop */ + // Set up a new main loop if (!(pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new())) { return SDL_SetError("pa_threaded_mainloop_new() failed"); } @@ -352,7 +352,7 @@ static int ConnectToPulseServer(void) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); mainloop_api = PULSEAUDIO_pa_threaded_mainloop_get_api(pulseaudio_threaded_mainloop); - SDL_assert(mainloop_api); /* this never fails, right? */ + SDL_assert(mainloop_api); // this never fails, right? pulseaudio_context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName()); if (pulseaudio_context == NULL) { @@ -362,7 +362,7 @@ static int ConnectToPulseServer(void) PULSEAUDIO_pa_context_set_state_callback(pulseaudio_context, PulseContextStateChangeCallback, NULL); - /* Connect to the PulseAudio server */ + // Connect to the PulseAudio server if (PULSEAUDIO_pa_context_connect(pulseaudio_context, NULL, 0, NULL) < 0) { SDL_SetError("Could not setup connection to PulseAudio"); goto failed; @@ -381,7 +381,7 @@ static int ConnectToPulseServer(void) PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - return 0; /* connected and ready! */ + return 0; // connected and ready! failed: PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); @@ -392,27 +392,27 @@ static int ConnectToPulseServer(void) static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata) { struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata; - /*printf("PULSEAUDIO WRITE CALLBACK! nbytes=%u\n", (unsigned int) nbytes);*/ + //printf("PULSEAUDIO WRITE CALLBACK! nbytes=%u\n", (unsigned int) nbytes); h->bytes_requested += nbytes; PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -/* This function waits until it is possible to write a full sound buffer */ +// This function waits until it is possible to write a full sound buffer static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; int retval = 0; - /*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/ + //printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested == 0)) { - /*printf("PULSEAUDIO WAIT IN WAITDEVICE!\n");*/ + //printf("PULSEAUDIO WAIT IN WAITDEVICE!\n"); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - /*printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n");*/ + //printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n"); retval = -1; break; } @@ -427,7 +427,7 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i { struct SDL_PrivateAudioData *h = device->hidden; - /*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/ + //printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available); SDL_assert(h->bytes_requested >= buffer_size); @@ -439,10 +439,10 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i return -1; } - /*printf("PULSEAUDIO FEED! nbytes=%d\n", buffer_size);*/ + //printf("PULSEAUDIO FEED! nbytes=%d\n", buffer_size); h->bytes_requested -= buffer_size; - /*printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written);*/ + //printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written); return 0; } @@ -464,8 +464,8 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata) { - /*printf("PULSEAUDIO READ CALLBACK! nbytes=%u\n", (unsigned int) nbytes);*/ - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* the capture code queries what it needs, we just need to signal to end any wait */ + //printf("PULSEAUDIO READ CALLBACK! nbytes=%u\n", (unsigned int) nbytes); + PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the capture code queries what it needs, we just need to signal to end any wait } static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) @@ -527,7 +527,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i PULSEAUDIO_pa_stream_drop(h->stream); // done with this fragment. PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); } - return cpy; /* new data, return it. */ + return cpy; // new data, return it. } return 0; @@ -550,15 +550,15 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - /*printf("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!\n");*/ + //printf("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!\n"); SDL_AudioDeviceDisconnected(device); break; } if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { - /* a new fragment is available! Just dump it. */ + // a new fragment is available! Just dump it. PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes); - PULSEAUDIO_pa_stream_drop(h->stream); /* drop this fragment. */ + PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment. } } @@ -619,7 +619,7 @@ static SDL_bool FindDeviceName(SDL_AudioDevice *device) static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata) { - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* just signal any waiting code, it can look up the details. */ + PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details. } static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) @@ -638,13 +638,13 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) SDL_assert(pulseaudio_threaded_mainloop != NULL); SDL_assert(pulseaudio_context != NULL); - /* Initialize all variables that we clean on shutdown */ + // Initialize all variables that we clean on shutdown h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { return SDL_OutOfMemory(); } - /* Try for a closest match on audio format */ + // Try for a closest match on audio format closefmts = SDL_ClosestAudioFormats(device->spec.format); while ((test_format = *(closefmts++)) != 0) { #ifdef DEBUG_AUDIO @@ -683,10 +683,10 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) device->spec.format = test_format; paspec.format = format; - /* Calculate the final parameters for this audio specification */ + // Calculate the final parameters for this audio specification SDL_UpdatedAudioDeviceFormat(device); - /* Allocate mixing buffer */ + // Allocate mixing buffer if (!iscapture) { h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (h->mixbuf == NULL) { @@ -698,7 +698,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) paspec.channels = device->spec.channels; paspec.rate = device->spec.freq; - /* Reduced prebuffering compared to the defaults. */ + // Reduced prebuffering compared to the defaults. paattr.fragsize = device->buffer_size; // despite the name, this is only used for capture devices, according to PulseAudio docs! paattr.tlength = device->buffer_size; paattr.prebuf = -1; @@ -712,15 +712,15 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) retval = SDL_SetError("Requested PulseAudio sink/source missing?"); } else { const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); - /* The SDL ALSA output hints us that we use Windows' channel mapping */ - /* https://bugzilla.libsdl.org/show_bug.cgi?id=110 */ + // The SDL ALSA output hints us that we use Windows' channel mapping + // https://bugzilla.libsdl.org/show_bug.cgi?id=110 PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX); h->stream = PULSEAUDIO_pa_stream_new( pulseaudio_context, - (name && *name) ? name : "Audio Stream", /* stream description */ - &paspec, /* sample format spec */ - &pacmap /* channel map */ + (name && *name) ? name : "Audio Stream", // stream description + &paspec, // sample format spec + &pacmap // channel map ); if (h->stream == NULL) { @@ -767,11 +767,11 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - /* We're (hopefully) ready to rock and roll. :-) */ + // We're (hopefully) ready to rock and roll. :-) return retval; } -/* device handles are device index + 1, cast to void*, so we never pass a NULL. */ +// device handles are device index + 1, cast to void*, so we never pass a NULL. static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format) { @@ -817,11 +817,11 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -/* This is called when PulseAudio adds a capture ("source") device. */ +// This is called when PulseAudio adds a capture ("source") device. // !!! FIXME: this is almost identical to SinkInfoCallback, merge the two. static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) { - /* Maybe skip "monitor" sources. These are just output from other sinks. */ + // Maybe skip "monitor" sources. These are just output from other sinks. if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) { const SDL_bool add = (SDL_bool) ((intptr_t)data); @@ -843,13 +843,13 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data) { if (!default_sink_path || (SDL_strcmp(i->default_sink_name, default_sink_path) != 0)) { - /*printf("DEFAULT SINK PATH CHANGED TO '%s'\n", i->default_sink_name);*/ + //printf("DEFAULT SINK PATH CHANGED TO '%s'\n", i->default_sink_name); SDL_free(default_sink_path); default_sink_path = SDL_strdup(i->default_sink_name); } if (!default_source_path || (SDL_strcmp(i->default_source_name, default_source_path) != 0)) { - /*printf("DEFAULT SOURCE PATH CHANGED TO '%s'\n", i->default_source_name);*/ + //printf("DEFAULT SOURCE PATH CHANGED TO '%s'\n", i->default_source_name); SDL_free(default_source_path); default_source_path = SDL_strdup(i->default_source_name); } @@ -857,14 +857,14 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -// This is called when PulseAudio has a device connected/removed/changed. */ +// This is called when PulseAudio has a device connected/removed/changed. static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data) { const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW); const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE); const SDL_bool changed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE); - if (added || removed || changed) { /* we only care about add/remove events. */ + if (added || removed || changed) { // we only care about add/remove events. const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK); const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE); @@ -909,7 +909,7 @@ static int SDLCALL HotplugThread(void *data) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_context_set_subscribe_callback(pulseaudio_context, HotplugCallback, NULL); - /* don't WaitForPulseOperation on the subscription; when it's done we'll be able to get hotplug events, but waiting doesn't changing anything. */ + // don't WaitForPulseOperation on the subscription; when it's done we'll be able to get hotplug events, but waiting doesn't changing anything. op = PULSEAUDIO_pa_context_subscribe(pulseaudio_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SERVER, NULL, NULL); SDL_PostSemaphore((SDL_Semaphore *) data); @@ -961,7 +961,7 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio *default_capture = device; } - /* ok, we have a sane list, let's set up hotplug notifications now... */ + // ok, we have a sane list, let's set up hotplug notifications now... SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1); pulseaudio_hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, ready_sem); // !!! FIXME: this can probably survive in significantly less stack space. SDL_WaitSemaphore(ready_sem); @@ -1006,7 +1006,6 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, SDL_FALSE); - /* Set the function pointers */ impl->DetectDevices = PULSEAUDIO_DetectDevices; impl->OpenDevice = PULSEAUDIO_OpenDevice; impl->PlayDevice = PULSEAUDIO_PlayDevice; @@ -1021,11 +1020,11 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) impl->HasCaptureSupport = SDL_TRUE; - return SDL_TRUE; /* this audio target is available. */ + return SDL_TRUE; } AudioBootStrap PULSEAUDIO_bootstrap = { "pulseaudio", "PulseAudio", PULSEAUDIO_Init, SDL_FALSE }; -#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO */ +#endif // SDL_AUDIO_DRIVER_PULSEAUDIO diff --git a/src/audio/pulseaudio/SDL_pulseaudio.h b/src/audio/pulseaudio/SDL_pulseaudio.h index 10a7d9d1215d9..6a0328e3fd828 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/src/audio/pulseaudio/SDL_pulseaudio.h @@ -31,16 +31,16 @@ struct SDL_PrivateAudioData { char *device_name; - /* pulseaudio structures */ + // pulseaudio structures pa_stream *stream; - /* Raw mixing buffer */ + // Raw mixing buffer Uint8 *mixbuf; - int bytes_requested; /* bytes of data the hardware wants _now_. */ + int bytes_requested; // bytes of data the hardware wants _now_. const Uint8 *capturebuf; int capturelen; }; -#endif /* SDL_pulseaudio_h_ */ +#endif // SDL_pulseaudio_h_ diff --git a/src/audio/qnx/SDL_qsa_audio.h b/src/audio/qnx/SDL_qsa_audio.h index 29dba24fd44b4..e092612e065af 100644 --- a/src/audio/qnx/SDL_qsa_audio.h +++ b/src/audio/qnx/SDL_qsa_audio.h @@ -36,6 +36,5 @@ struct SDL_PrivateAudioData Uint8 *pcm_buf; // Raw mixing buffer }; -#endif /* __SDL_QSA_AUDIO_H__ */ +#endif // __SDL_QSA_AUDIO_H__ -/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/sndio/SDL_sndioaudio.h b/src/audio/sndio/SDL_sndioaudio.h index 6a36b7df0e286..3337b18452c06 100644 --- a/src/audio/sndio/SDL_sndioaudio.h +++ b/src/audio/sndio/SDL_sndioaudio.h @@ -35,4 +35,4 @@ struct SDL_PrivateAudioData struct pollfd *pfd; // Polling structures for non-blocking sndio devices }; -#endif /* SDL_sndioaudio_h_ */ +#endif // SDL_sndioaudio_h_ diff --git a/src/audio/vita/SDL_vitaaudio.h b/src/audio/vita/SDL_vitaaudio.h index 1046fd57d5adb..00b6d4812f339 100644 --- a/src/audio/vita/SDL_vitaaudio.h +++ b/src/audio/vita/SDL_vitaaudio.h @@ -28,14 +28,14 @@ struct SDL_PrivateAudioData { - /* The hardware input/output port. */ + // The hardware input/output port. int port; - /* The raw allocated mixing buffer. */ + // The raw allocated mixing buffer. Uint8 *rawbuf; - /* Individual mixing buffers. */ + // Individual mixing buffers. Uint8 *mixbufs[NUM_BUFFERS]; - /* Index of the next available mixing buffer. */ + // Index of the next available mixing buffer. int next_buffer; }; -#endif /* SDL_vitaaudio_h */ +#endif // SDL_vitaaudio_h diff --git a/src/audio/wasapi/SDL_wasapi.h b/src/audio/wasapi/SDL_wasapi.h index 00f80a08a3022..8207c32cef87d 100644 --- a/src/audio/wasapi/SDL_wasapi.h +++ b/src/audio/wasapi/SDL_wasapi.h @@ -45,7 +45,7 @@ struct SDL_PrivateAudioData void *activation_handler; }; -/* win32 and winrt implementations call into these. */ +// win32 and winrt implementations call into these. int WASAPI_PrepDevice(SDL_AudioDevice *device); void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device lock when calling this! @@ -54,7 +54,7 @@ void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device typedef int (*ManagementThreadTask)(void *userdata); int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_until_complete); -/* These are functions that are implemented differently for Windows vs WinRT. */ +// These are functions that are implemented differently for Windows vs WinRT. // UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD. int WASAPI_PlatformInit(void); void WASAPI_PlatformDeinit(void); @@ -70,4 +70,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device); } #endif -#endif /* SDL_wasapi_h_ */ +#endif // SDL_wasapi_h_ diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index b43e07941ca12..f128509a399d9 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -37,7 +37,7 @@ #include "SDL_wasapi.h" -/* handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency). */ +// handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency). static HMODULE libavrt = NULL; typedef HANDLE(WINAPI *pfnAvSetMmThreadCharacteristicsW)(LPCWSTR, LPDWORD); typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE); @@ -46,7 +46,7 @@ static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NUL static SDL_bool immdevice_initialized = SDL_FALSE; -/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */ +// Some GUIDs we need to know without linking to libraries that aren't available before Vista. static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } }; int WASAPI_PlatformInit(void) @@ -59,7 +59,7 @@ int WASAPI_PlatformInit(void) immdevice_initialized = SDL_TRUE; - libavrt = LoadLibrary(TEXT("avrt.dll")); /* this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! */ + libavrt = LoadLibrary(TEXT("avrt.dll")); // this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! if (libavrt) { pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW)GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW"); pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics)GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics"); @@ -98,12 +98,12 @@ void WASAPI_PlatformDeinitializeStart(void) void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) { - /* this thread uses COM. */ - if (SUCCEEDED(WIN_CoInitialize())) { /* can't report errors, hope it worked! */ + // this thread uses COM. + if (SUCCEEDED(WIN_CoInitialize())) { // can't report errors, hope it worked! device->hidden->coinitialized = SDL_TRUE; } - /* Set this thread to very high "Pro Audio" priority. */ + // Set this thread to very high "Pro Audio" priority. if (pAvSetMmThreadCharacteristicsW) { DWORD idx = 0; device->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx); @@ -115,7 +115,7 @@ void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device) { - /* Set this thread back to normal priority. */ + // Set this thread back to normal priority. if (device->hidden->task && pAvRevertMmThreadCharacteristics) { pAvRevertMmThreadCharacteristics(device->hidden->task); device->hidden->task = NULL; @@ -132,10 +132,10 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device) IMMDevice *immdevice = NULL; if (SDL_IMMDevice_Get(device, &immdevice, device->iscapture) < 0) { device->hidden->client = NULL; - return -1; /* This is already set by SDL_IMMDevice_Get */ + return -1; // This is already set by SDL_IMMDevice_Get } - /* this is _not_ async in standard win32, yay! */ + // this is _not_ async in standard win32, yay! HRESULT ret = IMMDevice_Activate(immdevice, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&device->hidden->client); IMMDevice_Release(immdevice); @@ -145,11 +145,11 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device) } SDL_assert(device->hidden->client != NULL); - if (WASAPI_PrepDevice(device) == -1) { /* not async, fire it right away. */ + if (WASAPI_PrepDevice(device) == -1) { // not async, fire it right away. return -1; } - return 0; /* good to go. */ + return 0; // good to go. } void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) @@ -159,7 +159,7 @@ void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice void WASAPI_PlatformDeleteActivationHandler(void *handler) { - /* not asynchronous. */ + // not asynchronous. SDL_assert(!"This function should have only been called on WinRT."); } @@ -168,4 +168,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) SDL_IMMDevice_FreeDeviceHandle(device); } -#endif /* SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) */ +#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) From 797b70877d02dcf57e6cfcc0bf56eae7b42788ff Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 15:46:07 -0400 Subject: [PATCH 109/725] audio: Remove stub header SDL_audio_c.h. It was a leftover, that just included SDL_sysaudio.h, in modern times. --- VisualC-GDK/SDL/SDL.vcxproj | 1 - VisualC-GDK/SDL/SDL.vcxproj.filters | 3 --- VisualC-WinRT/SDL-UWP.vcxproj | 1 - VisualC-WinRT/SDL-UWP.vcxproj.filters | 3 --- VisualC/SDL/SDL.vcxproj | 1 - VisualC/SDL/SDL.vcxproj.filters | 3 --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 4 --- src/SDL.c | 2 +- src/audio/SDL_audio.c | 1 - src/audio/SDL_audio_c.h | 29 ---------------------- src/audio/SDL_audiocvt.c | 2 +- src/audio/SDL_audiotypecvt.c | 2 +- src/audio/SDL_wave.c | 2 +- src/audio/aaudio/SDL_aaudio.c | 1 - src/audio/alsa/SDL_alsa_audio.c | 2 +- src/audio/android/SDL_androidaudio.c | 1 - src/audio/coreaudio/SDL_coreaudio.m | 1 - src/audio/directsound/SDL_directsound.c | 2 +- src/audio/disk/SDL_diskaudio.c | 2 +- src/audio/dsp/SDL_dspaudio.c | 1 - src/audio/dummy/SDL_dummyaudio.c | 2 +- src/audio/emscripten/SDL_emscriptenaudio.c | 2 +- src/audio/haiku/SDL_haikuaudio.cc | 1 - src/audio/jack/SDL_jackaudio.c | 2 +- src/audio/netbsd/SDL_netbsdaudio.c | 1 - src/audio/openslES/SDL_openslES.c | 1 - src/audio/ps2/SDL_ps2audio.c | 2 +- src/audio/psp/SDL_pspaudio.c | 1 - src/audio/pulseaudio/SDL_pulseaudio.c | 2 +- src/audio/qnx/SDL_qsa_audio.c | 2 +- src/audio/sndio/SDL_sndioaudio.c | 2 +- src/audio/vita/SDL_vitaaudio.c | 1 - src/audio/wasapi/SDL_wasapi.c | 1 - src/audio/wasapi/SDL_wasapi_win32.c | 1 - src/audio/wasapi/SDL_wasapi_winrt.cpp | 1 - 35 files changed, 14 insertions(+), 72 deletions(-) delete mode 100644 src/audio/SDL_audio_c.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index bb003d0f08311..565362dbd5b95 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -367,7 +367,6 @@ - diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index bbdc75985c4d5..3ebac004e3ab8 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -411,9 +411,6 @@ API Headers - - audio - audio diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 372a283396838..f6c11b5a518f0 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -93,7 +93,6 @@ - diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 92e6f4a8d4e7b..f6aee5712a03e 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -177,9 +177,6 @@ Source Files - - Source Files - Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index a40d5acb57176..219e93ed345e7 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -317,7 +317,6 @@ - diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index f72a3a0fca882..5dd954cf213fe 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -402,9 +402,6 @@ API Headers - - audio - audio diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 279a74856b0ff..2fb3aca92e3bd 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -238,7 +238,6 @@ A7D8B76A23E2514300DCD162 /* SDL_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A86623E2513F00DCD162 /* SDL_wave.c */; }; A7D8B79423E2514400DCD162 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87123E2513F00DCD162 /* SDL_dummyaudio.h */; }; A7D8B79A23E2514400DCD162 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A87223E2513F00DCD162 /* SDL_dummyaudio.c */; }; - A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */; }; A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87723E2513F00DCD162 /* SDL_audiodev_c.h */; }; A7D8B81823E2514400DCD162 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A88F23E2513F00DCD162 /* SDL_audiodev.c */; }; A7D8B85A23E2514400DCD162 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A89F23E2513F00DCD162 /* SDL_sysaudio.h */; }; @@ -747,7 +746,6 @@ A7D8A86623E2513F00DCD162 /* SDL_wave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_wave.c; sourceTree = ""; }; A7D8A87123E2513F00DCD162 /* SDL_dummyaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dummyaudio.h; sourceTree = ""; }; A7D8A87223E2513F00DCD162 /* SDL_dummyaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyaudio.c; sourceTree = ""; }; - A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = ""; }; A7D8A87723E2513F00DCD162 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = ""; }; A7D8A88F23E2513F00DCD162 /* SDL_audiodev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiodev.c; sourceTree = ""; }; A7D8A89F23E2513F00DCD162 /* SDL_sysaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysaudio.h; sourceTree = ""; }; @@ -1815,7 +1813,6 @@ A7D8A8B923E2513F00DCD162 /* coreaudio */, A7D8A8AF23E2513F00DCD162 /* disk */, A7D8A87023E2513F00DCD162 /* dummy */, - A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */, F32DDAC92AB795A30041EAA5 /* SDL_audio_channel_converters.h */, F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */, A7D8A8B823E2513F00DCD162 /* SDL_audio.c */, @@ -2071,7 +2068,6 @@ A7D8B61723E2514300DCD162 /* SDL_assert_c.h in Headers */, F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */, F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */, - A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */, A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */, F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */, F3F7D9A52933074E00816151 /* SDL_bits.h in Headers */, diff --git a/src/SDL.c b/src/SDL.c index 31bd02ea41998..cfd096cdc1e5b 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -39,7 +39,7 @@ #include "SDL_assert_c.h" #include "SDL_log_c.h" #include "SDL_properties_c.h" -#include "audio/SDL_audio_c.h" +#include "audio/SDL_sysaudio.h" #include "video/SDL_video_c.h" #include "events/SDL_events_c.h" #include "haptic/SDL_haptic_c.h" diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b74795649df36..b96dae2d9c72a 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -20,7 +20,6 @@ */ #include "SDL_internal.h" -#include "SDL_audio_c.h" #include "SDL_sysaudio.h" #include "../thread/SDL_systhread.h" #include "../SDL_utils_c.h" diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h deleted file mode 100644 index 7b00ceacc9b50..0000000000000 --- a/src/audio/SDL_audio_c.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SDL_audio_c_h_ -#define SDL_audio_c_h_ - -/* !!! FIXME: remove this header and have things just include SDL_sysaudio.h directly. */ - -#include "SDL_sysaudio.h" - -#endif /* SDL_audio_c_h_ */ diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 126a26c64e420..7681e76cb9cd4 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#include "SDL_audio_c.h" +#include "SDL_sysaudio.h" #include "SDL_audioqueue.h" #include "SDL_audioresample.h" diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index deabeee474b94..6f54265a83c62 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#include "SDL_audio_c.h" +#include "SDL_sysaudio.h" // TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 can be fixed #undef SDL_NEON_INTRINSICS diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 2afb70bd2cd9b..3701a432096de 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -34,7 +34,7 @@ /* Microsoft WAVE file loading routines */ #include "SDL_wave.h" -#include "SDL_audio_c.h" +#include "SDL_sysaudio.h" /* Reads the value stored at the location of the f1 pointer, multiplies it * with the second argument and then stores the result to f1. diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index ea569503ec88a..f1f8674b743e9 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -23,7 +23,6 @@ #ifdef SDL_AUDIO_DRIVER_AAUDIO #include "../SDL_sysaudio.h" -#include "../SDL_audio_c.h" #include "SDL_aaudio.h" #include "../../core/android/SDL_android.h" diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 9d11cdc180300..4c455d30efec3 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -37,7 +37,7 @@ #include // For kill() #include -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_alsa_audio.h" #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index 9d49ce9b8cb7e..cd0a942640599 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -25,7 +25,6 @@ // Output audio to Android (legacy interface) #include "../SDL_sysaudio.h" -#include "../SDL_audio_c.h" #include "SDL_androidaudio.h" #include "../../core/android/SDL_android.h" diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 923eb8fe60d71..0cb1d3f9c3518 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -22,7 +22,6 @@ #ifdef SDL_AUDIO_DRIVER_COREAUDIO -#include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" #include "SDL_coreaudio.h" #include "../../thread/SDL_systhread.h" diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index 2a6bb47e7ceb8..432e740f80c95 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -22,7 +22,7 @@ #ifdef SDL_AUDIO_DRIVER_DSOUND -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_directsound.h" #include #ifdef HAVE_MMDEVICEAPI_H diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index 695360aa3ba9a..69d2d6d35afc2 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -24,7 +24,7 @@ // Output raw audio data to a file. -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_diskaudio.h" // !!! FIXME: these should be SDL hints, not environment variables. diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 22d3923d792a7..8178d52a299f5 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -36,7 +36,6 @@ #include -#include "../SDL_audio_c.h" #include "../SDL_audiodev_c.h" #include "../../SDL_utils_c.h" #include "SDL_dspaudio.h" diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index aa0c51ecfd851..9b2068a488222 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -22,7 +22,7 @@ // Output audio to nowhere... -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_dummyaudio.h" // !!! FIXME: this should be an SDL hint, not an environment variable. diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index d2ee78b9dd9fe..368499227fb80 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -22,7 +22,7 @@ #ifdef SDL_AUDIO_DRIVER_EMSCRIPTEN -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_emscriptenaudio.h" #include diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 5d74462672b26..f52dae593ef79 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -32,7 +32,6 @@ extern "C" { -#include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" #include "SDL_haikuaudio.h" diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 1521eb697af46..1e8d18bb479c8 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -22,7 +22,7 @@ #ifdef SDL_AUDIO_DRIVER_JACK -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_jackaudio.h" #include "../../thread/SDL_systhread.h" diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index 4aba643a6c860..ca95a3a1656b7 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -34,7 +34,6 @@ #include #include "../../core/unix/SDL_poll.h" -#include "../SDL_audio_c.h" #include "../SDL_audiodev_c.h" #include "SDL_netbsdaudio.h" diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index b40e702ba6c4b..5b7112b20b6a1 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -26,7 +26,6 @@ // https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html #include "../SDL_sysaudio.h" -#include "../SDL_audio_c.h" #include "SDL_openslES.h" #include "../../core/android/SDL_android.h" diff --git a/src/audio/ps2/SDL_ps2audio.c b/src/audio/ps2/SDL_ps2audio.c index 4debff45d8340..78717cc12a2e9 100644 --- a/src/audio/ps2/SDL_ps2audio.c +++ b/src/audio/ps2/SDL_ps2audio.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_ps2audio.h" #include diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index 8e35897600629..ff9bb358f3fe3 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -26,7 +26,6 @@ #include #include -#include "../SDL_audio_c.h" #include "../SDL_audiodev_c.h" #include "../SDL_sysaudio.h" #include "SDL_pspaudio.h" diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 2022156eaadeb..73f5da4912a0a 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -31,7 +31,7 @@ #include #include -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_pulseaudio.h" #include "../../thread/SDL_systhread.h" diff --git a/src/audio/qnx/SDL_qsa_audio.c b/src/audio/qnx/SDL_qsa_audio.c index 7c242ce94d6bc..e6de9e6f7a2e9 100644 --- a/src/audio/qnx/SDL_qsa_audio.c +++ b/src/audio/qnx/SDL_qsa_audio.c @@ -39,7 +39,7 @@ #include "SDL3/SDL_timer.h" #include "SDL3/SDL_audio.h" #include "../../core/unix/SDL_poll.h" -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_qsa_audio.h" // default channel communication parameters diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 4319d385b8832..8cca105d5b0fb 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -36,7 +36,7 @@ #include #include -#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" #include "SDL_sndioaudio.h" #ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index 7f13f0e4ead29..d26698bbec17a 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -26,7 +26,6 @@ #include #include -#include "../SDL_audio_c.h" #include "../SDL_audiodev_c.h" #include "../SDL_sysaudio.h" #include "SDL_vitaaudio.h" diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 620c15fbe191a..f68fb0f694e61 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -25,7 +25,6 @@ #include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_immdevice.h" #include "../../thread/SDL_systhread.h" -#include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" #define COBJMACROS diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index f128509a399d9..19dfbd4d9bbc5 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -30,7 +30,6 @@ #include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_immdevice.h" -#include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" #include diff --git a/src/audio/wasapi/SDL_wasapi_winrt.cpp b/src/audio/wasapi/SDL_wasapi_winrt.cpp index c3701a8a5f149..f3aeadc794379 100644 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp @@ -36,7 +36,6 @@ extern "C" { #include "../../core/windows/SDL_windows.h" -#include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" } From bf269571fc484afe5155f2f5e5f269dd328ce6f6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Oct 2023 15:47:01 -0400 Subject: [PATCH 110/725] jack: Removed FIXME comment that has since been fixed. --- src/audio/jack/SDL_jackaudio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 1e8d18bb479c8..703122c8a8aad 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -333,8 +333,6 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("No physical JACK ports available"); } - /* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */ - // Jack pretty much demands what it wants. device->spec.format = SDL_AUDIO_F32; device->spec.freq = JACK_jack_get_sample_rate(client); From 15533dce05a9e763cd8c959f1b13170474ee6d04 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 21:37:59 -0700 Subject: [PATCH 111/725] Cleaned up warnings from check_stdlib_usage.py --- src/audio/alsa/SDL_alsa_audio.c | 6 +++--- src/audio/vita/SDL_vitaaudio.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 4c455d30efec3..5e116d653d4e8 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -813,10 +813,10 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de SDL_bool have_output = SDL_FALSE; SDL_bool have_input = SDL_FALSE; - free(ioid); + free(ioid); // This should NOT be SDL_free() if (!isoutput && !isinput) { - free(name); + free(name); // This should NOT be SDL_free() continue; } @@ -826,7 +826,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de } else if (has_default_capture && isinput) { *has_default_capture = SDL_TRUE; } - free(name); + free(name); // This should NOT be SDL_free() continue; } diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index d26698bbec17a..705d19ede13f7 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -164,7 +164,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device) } if (!device->iscapture && device->hidden->rawbuf != NULL) { - SDL_aligned_free(device->hidden->rawbuf); // this uses memalign(), not SDL_malloc(). + SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc() device->hidden->rawbuf = NULL; } SDL_free(device->hidden); From 1c70760c0bc23c056ec3269a2c26d2058cc74e04 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 22:13:33 -0700 Subject: [PATCH 112/725] Added thread-safety information for the new SDL properties API --- include/SDL3/SDL_properties.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 4c1335fb737fb..5cba83f8d4e29 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -42,9 +42,13 @@ typedef Uint32 SDL_PropertiesID; /** * Create a set of properties * + * All properties are automatically destroyed when SDL_Quit() is called. + * * \returns an ID for a new set of properties, or 0 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroyProperties @@ -67,6 +71,8 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_UnlockProperties @@ -78,6 +84,8 @@ extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props); * * \param props the properties to unlock * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockProperties @@ -96,6 +104,8 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetProperty @@ -109,6 +119,8 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * \param name the name of the property to query * \returns the value of the property, or NULL if it is not set. * + * \threadsafety It is safe to call this function from any thread, although the data returned is not protected and could potentially be freed if you call SDL_SetProperty() on this set of properties or destroy this set of properties from another thread. If you need to avoid this, use SDL_LockProperties() and SDL_UnlockProperties(). + * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetProperty @@ -123,6 +135,8 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetProperty @@ -137,6 +151,8 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char * * \param props the properties to destroy * + * \threadsafety This function should not be called while other threads might be setting or getting values from this set of properties. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateProperties From 4fa821cb3e93025a139618d63dc2d956eda8b6ff Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 19 Oct 2023 05:14:13 +0000 Subject: [PATCH 113/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_properties.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 5cba83f8d4e29..b3a0851ff023e 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -119,7 +119,12 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * \param name the name of the property to query * \returns the value of the property, or NULL if it is not set. * - * \threadsafety It is safe to call this function from any thread, although the data returned is not protected and could potentially be freed if you call SDL_SetProperty() on this set of properties or destroy this set of properties from another thread. If you need to avoid this, use SDL_LockProperties() and SDL_UnlockProperties(). + * \threadsafety It is safe to call this function from any thread, although + * the data returned is not protected and could potentially be + * freed if you call SDL_SetProperty() on this set of properties + * or destroy this set of properties from another thread. If you + * need to avoid this, use SDL_LockProperties() and + * SDL_UnlockProperties(). * * \since This function is available since SDL 3.0.0. * @@ -151,7 +156,8 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char * * \param props the properties to destroy * - * \threadsafety This function should not be called while other threads might be setting or getting values from this set of properties. + * \threadsafety This function should not be called while other threads might + * be setting or getting values from this set of properties. * * \since This function is available since SDL 3.0.0. * From 3c8edeb79bb88add61d3d62a62f966a872712820 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 22:17:02 -0700 Subject: [PATCH 114/725] Clarified SDL property thread-safety information --- include/SDL3/SDL_properties.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index b3a0851ff023e..16d0308607806 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -121,8 +121,7 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * * \threadsafety It is safe to call this function from any thread, although * the data returned is not protected and could potentially be - * freed if you call SDL_SetProperty() on this set of properties - * or destroy this set of properties from another thread. If you + * freed if you call SDL_SetProperty() or SDL_ClearProperty() on these properties from another thread. If you * need to avoid this, use SDL_LockProperties() and * SDL_UnlockProperties(). * @@ -156,8 +155,8 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char * * \param props the properties to destroy * - * \threadsafety This function should not be called while other threads might - * be setting or getting values from this set of properties. + * \threadsafety This function should not be called while these properties are locked or other threads might + * be setting or getting values from these properties. * * \since This function is available since SDL 3.0.0. * From a6edc75fe74a86a2d67868c827d47e6fdeba0b73 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 19 Oct 2023 05:18:12 +0000 Subject: [PATCH 115/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_properties.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 16d0308607806..01ae37d05e006 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -121,9 +121,9 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * * \threadsafety It is safe to call this function from any thread, although * the data returned is not protected and could potentially be - * freed if you call SDL_SetProperty() or SDL_ClearProperty() on these properties from another thread. If you - * need to avoid this, use SDL_LockProperties() and - * SDL_UnlockProperties(). + * freed if you call SDL_SetProperty() or SDL_ClearProperty() on + * these properties from another thread. If you need to avoid + * this, use SDL_LockProperties() and SDL_UnlockProperties(). * * \since This function is available since SDL 3.0.0. * @@ -155,8 +155,9 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char * * \param props the properties to destroy * - * \threadsafety This function should not be called while these properties are locked or other threads might - * be setting or getting values from these properties. + * \threadsafety This function should not be called while these properties are + * locked or other threads might be setting or getting values + * from these properties. * * \since This function is available since SDL 3.0.0. * From 1f8f82b379fff40281eb15157f18531b4ede95e4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 22:19:50 -0700 Subject: [PATCH 116/725] Removed redundant thread-safety information --- include/SDL3/SDL_properties.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 01ae37d05e006..9d01c9381ab9c 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -151,7 +151,7 @@ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char * Destroy a set of properties * * All properties are deleted and their cleanup functions will be called, if - * any. The set of properties must be unlocked when it is destroyed. + * any. * * \param props the properties to destroy * From 3a4c9d6990de06510a2efc87f806ab0062da793c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2023 22:30:16 -0700 Subject: [PATCH 117/725] Fixed build error when API logging is enabled --- src/dynapi/SDL_dynapi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 8dc4b999a1f22..603ea36a3df2b 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -275,6 +275,16 @@ static int SDLCALL SDL_asprintf_LOGSDLCALLS(char **strp, SDL_PRINTF_FORMAT_STRIN va_end(ap); return retval; } +static int SDLCALL SDL_swprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) wchar_t *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ...) +{ + int retval; + va_list ap; + SDL_Log_REAL("SDL3CALL SDL_swprintf"); + va_start(ap, fmt); + retval = SDL_vswprintf_REAL(buf, maxlen, fmt, ap); + va_end(ap); + return retval; +} static void SDLCALL SDL_Log_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { va_list ap; From 142366c837b506dda9563e34d31c229017de77af Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 19 Oct 2023 14:03:06 +0000 Subject: [PATCH 118/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_audio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 007905d3e14c3..2287259352f8e 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -660,7 +660,7 @@ extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetAudioStreamDevice(SDL_AudioStre * * \param src_spec The format details of the input audio * \param dst_spec The format details of the output audio - * \returns 0 on success, or -1 on error. + * \returns a new audio stream on success, or NULL on failure. * * \threadsafety It is safe to call this function from any thread. * From 0df888c584ed525096083d0f6b1444324280f4a2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 19 Oct 2023 08:54:11 -0700 Subject: [PATCH 119/725] Moved Android low latency audio behind a hint "SDL_ANDROID_LOW_LATENCY_AUDIO" --- src/audio/aaudio/SDL_aaudio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index f1f8674b743e9..9d9c98b8eec5e 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -311,9 +311,10 @@ static int BuildAAudioStream(SDL_AudioDevice *device) ctx.AAudioStreamBuilder_setDirection(builder, direction); ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device); ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device); -#if 0 // Some devices have flat sounding audio when low latency mode is enabled - ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); -#endif + // Some devices have flat sounding audio when low latency mode is enabled, but this is a better experience for most people + if (SDL_GetHintBoolean("SDL_ANDROID_LOW_LATENCY_AUDIO", SDL_TRUE)) { + ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); + } LOGI("AAudio Try to open %u hz %u bit chan %u %s samples %u", device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), From 0d7c5a2c560194486620187a4449e761c75e2933 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 19 Oct 2023 10:12:34 -0700 Subject: [PATCH 120/725] Updated Android API documentation --- include/SDL3/SDL_system.h | 47 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index 8b9539b982546..bccc457ab2ae0 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -289,28 +289,31 @@ extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void); /** * Query Android API level of the current device. * - * - API level 31: Android 12 - * - API level 30: Android 11 - * - API level 29: Android 10 - * - API level 28: Android 9 - * - API level 27: Android 8.1 - * - API level 26: Android 8.0 - * - API level 25: Android 7.1 - * - API level 24: Android 7.0 - * - API level 23: Android 6.0 - * - API level 22: Android 5.1 - * - API level 21: Android 5.0 - * - API level 20: Android 4.4W - * - API level 19: Android 4.4 - * - API level 18: Android 4.3 - * - API level 17: Android 4.2 - * - API level 16: Android 4.1 - * - API level 15: Android 4.0.3 - * - API level 14: Android 4.0 - * - API level 13: Android 3.2 - * - API level 12: Android 3.1 - * - API level 11: Android 3.0 - * - API level 10: Android 2.3.3 + * - API level 34: Android 14 (UPSIDE_DOWN_CAKE) + * - API level 33: Android 13 (TIRAMISU) + * - API level 32: Android 12L (S_V2) + * - API level 31: Android 12 (S) + * - API level 30: Android 11 (R) + * - API level 29: Android 10 (Q) + * - API level 28: Android 9 (P) + * - API level 27: Android 8.1 (O_MR1) + * - API level 26: Android 8.0 (O) + * - API level 25: Android 7.1 (N_MR1) + * - API level 24: Android 7.0 (N) + * - API level 23: Android 6.0 (M) + * - API level 22: Android 5.1 (LOLLIPOP_MR1) + * - API level 21: Android 5.0 (LOLLIPOP, L) + * - API level 20: Android 4.4W (KITKAT_WATCH) + * - API level 19: Android 4.4 (KITKAT) + * - API level 18: Android 4.3 (JELLY_BEAN_MR2) + * - API level 17: Android 4.2 (JELLY_BEAN_MR1) + * - API level 16: Android 4.1 (JELLY_BEAN) + * - API level 15: Android 4.0.3 (ICE_CREAM_SANDWICH_MR1) + * - API level 14: Android 4.0 (ICE_CREAM_SANDWICH) + * - API level 13: Android 3.2 (HONEYCOMB_MR2) + * - API level 12: Android 3.1 (HONEYCOMB_MR1) + * - API level 11: Android 3.0 (HONEYCOMB) + * - API level 10: Android 2.3.3 (GINGERBREAD_MR1) * * \returns the Android API level. * From 594fda412030c3635d6e39de6a5f3b93caa300f5 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 19 Oct 2023 17:13:15 +0000 Subject: [PATCH 121/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_system.h | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index bccc457ab2ae0..a35f688b4a035 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -289,30 +289,30 @@ extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void); /** * Query Android API level of the current device. * - * - API level 34: Android 14 (UPSIDE_DOWN_CAKE) - * - API level 33: Android 13 (TIRAMISU) - * - API level 32: Android 12L (S_V2) - * - API level 31: Android 12 (S) - * - API level 30: Android 11 (R) - * - API level 29: Android 10 (Q) - * - API level 28: Android 9 (P) - * - API level 27: Android 8.1 (O_MR1) - * - API level 26: Android 8.0 (O) - * - API level 25: Android 7.1 (N_MR1) - * - API level 24: Android 7.0 (N) - * - API level 23: Android 6.0 (M) - * - API level 22: Android 5.1 (LOLLIPOP_MR1) - * - API level 21: Android 5.0 (LOLLIPOP, L) + * - API level 34: Android 14 (UPSIDE_DOWN_CAKE) + * - API level 33: Android 13 (TIRAMISU) + * - API level 32: Android 12L (S_V2) + * - API level 31: Android 12 (S) + * - API level 30: Android 11 (R) + * - API level 29: Android 10 (Q) + * - API level 28: Android 9 (P) + * - API level 27: Android 8.1 (O_MR1) + * - API level 26: Android 8.0 (O) + * - API level 25: Android 7.1 (N_MR1) + * - API level 24: Android 7.0 (N) + * - API level 23: Android 6.0 (M) + * - API level 22: Android 5.1 (LOLLIPOP_MR1) + * - API level 21: Android 5.0 (LOLLIPOP, L) * - API level 20: Android 4.4W (KITKAT_WATCH) - * - API level 19: Android 4.4 (KITKAT) - * - API level 18: Android 4.3 (JELLY_BEAN_MR2) - * - API level 17: Android 4.2 (JELLY_BEAN_MR1) - * - API level 16: Android 4.1 (JELLY_BEAN) + * - API level 19: Android 4.4 (KITKAT) + * - API level 18: Android 4.3 (JELLY_BEAN_MR2) + * - API level 17: Android 4.2 (JELLY_BEAN_MR1) + * - API level 16: Android 4.1 (JELLY_BEAN) * - API level 15: Android 4.0.3 (ICE_CREAM_SANDWICH_MR1) - * - API level 14: Android 4.0 (ICE_CREAM_SANDWICH) - * - API level 13: Android 3.2 (HONEYCOMB_MR2) - * - API level 12: Android 3.1 (HONEYCOMB_MR1) - * - API level 11: Android 3.0 (HONEYCOMB) + * - API level 14: Android 4.0 (ICE_CREAM_SANDWICH) + * - API level 13: Android 3.2 (HONEYCOMB_MR2) + * - API level 12: Android 3.1 (HONEYCOMB_MR1) + * - API level 11: Android 3.0 (HONEYCOMB) * - API level 10: Android 2.3.3 (GINGERBREAD_MR1) * * \returns the Android API level. From 76f81797b71e12391ce434582b911ef4f6b61390 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Oct 2023 15:44:58 -0400 Subject: [PATCH 122/725] audio: Device threads don't increment physical device refcounts. Otherwise, they risk the device thread joining on itself. Now we make sure the reference is held at the logical device level until the physical device is closed, so it can't destroy the device in normal usage until the thread is joined, etc. --- src/audio/SDL_audio.c | 6 ++---- src/audio/emscripten/SDL_emscriptenaudio.c | 2 -- src/audio/haiku/SDL_haikuaudio.cc | 2 -- src/audio/jack/SDL_jackaudio.c | 2 -- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b96dae2d9c72a..05e1ffac9b555 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -848,7 +848,6 @@ void SDL_QuitAudio(void) void SDL_AudioThreadFinalize(SDL_AudioDevice *device) { - UnrefPhysicalAudioDevice(device); } static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) @@ -864,7 +863,6 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(!device->iscapture); - RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1014,7 +1012,6 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(device->iscapture); - RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1354,13 +1351,14 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) if (logdev) { SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); - UnrefPhysicalAudioDevice(device); // one reference for each logical device. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. ClosePhysicalAudioDevice(device); } + + UnrefPhysicalAudioDevice(device); // one reference for each logical device. } } diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 368499227fb80..32afd20bc87ae 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -181,8 +181,6 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - // limit to native freq device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; }); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index f52dae593ef79..5772fbe056507 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -111,8 +111,6 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) } SDL_zerop(device->hidden); - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - // Parse the audio format and fill the Be raw audio format media_raw_audio_format format; SDL_zero(format); diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 703122c8a8aad..77e2f03fa9909 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -300,8 +300,6 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); device->hidden->client = client; if (client == NULL) { From 70fd8e2ba29522dfeaa897dc4a37ab59f8b25f92 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 19 Oct 2023 22:35:53 -0700 Subject: [PATCH 123/725] Lock joysticks when adding gamepad mappings Fixes https://github.com/libsdl-org/SDL/issues/8412 --- src/joystick/SDL_gamepad.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 6bb982c57e370..1af2159a5d53e 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1670,6 +1670,8 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) } line = buf; + SDL_LockJoysticks(); + PushMappingChangeTracking(); while (line < buf + db_size) { @@ -1702,6 +1704,8 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) PopMappingChangeTracking(); + SDL_UnlockJoysticks(); + SDL_free(buf); return gamepads; } From e5a15f94e2f1a8fbbffb25ea9932cda9679a68fd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 22 Oct 2023 09:10:14 -0700 Subject: [PATCH 124/725] Revert "Check to make sure the Windows joystick device has buttons and axes" This reverts commit 642504bc5993a6acd4d9c1d4c1314c6b1cf6e4e1. We have SDL_HINT_JOYSTICK_ROG_CHAKRAM to ignore or allow the ROG Chakram X mouse to be used as a joystick. Fixes https://github.com/libsdl-org/SDL/issues/8227 --- src/joystick/windows/SDL_dinputjoystick.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index b6868891a9fa1..fbb0e8240c618 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -451,7 +451,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta char *hidPath = NULL; char *name = NULL; LPDIRECTINPUTDEVICE8 device = NULL; - DIDEVCAPS caps; /* We are only supporting HID devices. */ CHECK(pDeviceInstance->dwDevType & DIDEVTYPE_HID); @@ -461,13 +460,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta CHECK(QueryDevicePath(device, &hidPath)); CHECK(QueryDeviceInfo(device, &vendor, &product)); - /* Check to make sure the device has buttons and axes. - * This fixes incorrectly detecting the ROG CHAKRAM X mouse as a game controller on Windows 10 - */ - caps.dwSize = sizeof(caps); - CHECK(SUCCEEDED(IDirectInputDevice8_GetCapabilities(device, &caps))); - CHECK(caps.dwAxes > 0 && caps.dwButtons > 0); - CHECK(!SDL_IsXInputDevice(vendor, product, hidPath)); pNewJoystick = *(JoyStick_DeviceData **)pContext; From 33c9eeec7cda9da3a97543ae70289ac365acf297 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 22 Oct 2023 16:14:01 -0400 Subject: [PATCH 125/725] Revert "audio: Device threads don't increment physical device refcounts." This reverts commit 76f81797b71e12391ce434582b911ef4f6b61390. This worked in the normal cases, but: A device thread that calls SDL_DisconnectAudioDevice due to failure will fire the disconnect event from the device thread...and if there's an event watcher that uses that moment to close the device, we still end up in the same situation, where the device thread tries to join on itself. Better solutions are still pending. --- src/audio/SDL_audio.c | 6 ++++-- src/audio/emscripten/SDL_emscriptenaudio.c | 2 ++ src/audio/haiku/SDL_haikuaudio.cc | 2 ++ src/audio/jack/SDL_jackaudio.c | 2 ++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 05e1ffac9b555..b96dae2d9c72a 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -848,6 +848,7 @@ void SDL_QuitAudio(void) void SDL_AudioThreadFinalize(SDL_AudioDevice *device) { + UnrefPhysicalAudioDevice(device); } static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) @@ -863,6 +864,7 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(!device->iscapture); + RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1012,6 +1014,7 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(device->iscapture); + RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1351,14 +1354,13 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) if (logdev) { SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); + UnrefPhysicalAudioDevice(device); // one reference for each logical device. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. ClosePhysicalAudioDevice(device); } - - UnrefPhysicalAudioDevice(device); // one reference for each logical device. } } diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 32afd20bc87ae..368499227fb80 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -181,6 +181,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + // limit to native freq device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; }); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 5772fbe056507..f52dae593ef79 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -111,6 +111,8 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) } SDL_zerop(device->hidden); + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + // Parse the audio format and fill the Be raw audio format media_raw_audio_format format; SDL_zero(format); diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 77e2f03fa9909..703122c8a8aad 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -300,6 +300,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } + RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. + client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); device->hidden->client = client; if (client == NULL) { From 9abc692156aa183b05f05e8395a44d0bd5f72b10 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 22 Oct 2023 17:01:49 -0400 Subject: [PATCH 126/725] audio: Another attempt to deal with device destruction from device thread. This only happens when closing a device from an event watcher, when the device reports failure from its own thread. --- src/audio/SDL_audio.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b96dae2d9c72a..f2d28a2989500 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1321,9 +1321,14 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * // this expects the device lock to be held. !!! FIXME: no it doesn't...? static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { - SDL_AtomicSet(&device->shutdown, 1); + SDL_AtomicSet(&device->shutdown, 1); // alert device thread that it should terminate. + if (device->thread != NULL) { - SDL_WaitThread(device->thread, NULL); + if (SDL_GetThreadID(device->thread) == SDL_ThreadID()) { + SDL_DetachThread(device->thread); // we _are_ the device thread, just drift off into the ether when finished, nothing is waiting for us. + } else { + SDL_WaitThread(device->thread, NULL); // we're not the device thread, wait for it to terminate. + } device->thread = NULL; } @@ -1345,7 +1350,6 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) SDL_copyp(&device->spec, &device->default_spec); device->sample_frames = 0; device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); - SDL_AtomicSet(&device->shutdown, 0); // ready to go again. } void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) @@ -1442,6 +1446,8 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec return 0; // Braaaaaaaaains. } + SDL_AtomicSet(&device->shutdown, 0); // make sure we don't kill the new thread immediately. + // These start with the backend's implementation, but we might swap them out with zombie versions later. device->WaitDevice = current_audio.impl.WaitDevice; device->PlayDevice = current_audio.impl.PlayDevice; From 43d41c9dcbbaaa4fdd3b196ed95a52143d1b2a01 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 00:38:41 -0400 Subject: [PATCH 127/725] audio: Another attempt to make device add/remove work vs event watchers. This patch reverts the previous reversion, and then adds code to queue up events to be sent the next time SDL pumps the event queue. This guarantees that the event watcher/filter _never_ runs from an SDL audio device thread or some other backend-specific internal thread. --- src/audio/SDL_audio.c | 170 ++++++++++++--------- src/audio/SDL_sysaudio.h | 12 +- src/audio/emscripten/SDL_emscriptenaudio.c | 2 - src/audio/haiku/SDL_haikuaudio.cc | 2 - src/audio/jack/SDL_jackaudio.c | 2 - src/events/SDL_events.c | 5 + 6 files changed, 114 insertions(+), 79 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index f2d28a2989500..5afe415edb898 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -455,15 +455,20 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, } SDL_AudioDevice *device = iscapture ? CreateAudioCaptureDevice(name, &spec, handle) : CreateAudioOutputDevice(name, &spec, handle); + + // Add a device add event to the pending list, to be pushed when the event queue is pumped (away from any of our internal threads). if (device) { - // Post the event, if desired - if (SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_ADDED)) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_ADDED; - event.adevice.which = device->instance_id; - event.adevice.iscapture = iscapture; - SDL_PushEvent(&event); + SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); + if (p) { // if allocation fails, you won't get an event, but we can't help that. + p->type = SDL_EVENT_AUDIO_DEVICE_ADDED; + p->devid = device->instance_id; + p->next = NULL; + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); + current_audio.pending_events_tail->next = p; + current_audio.pending_events_tail = p; + SDL_UnlockRWLock(current_audio.device_hash_lock); } } @@ -498,59 +503,47 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) const SDL_AudioDeviceID devid = device->instance_id; const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)) ? SDL_TRUE : SDL_FALSE; - // get a count of all devices currently attached. Save these off in an array so we can - // send events for each after we're done with the device lock, in case something tries - // to close a device from an event filter, as this would deadlock waiting on the device - // thread to join, which will be waiting for the device lock, too. - int total_devices = 0; - SDL_bool isstack = SDL_FALSE; - SDL_AudioDeviceID *devices = NULL; - if (SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED)) { - total_devices++; // count the physical device. - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - total_devices++; - } - - devices = SDL_small_alloc(SDL_AudioDeviceID, total_devices, &isstack); - int deviceidx = 0; - - if (devices) { // if we ran out of memory, we won't send disconnect events, but you probably have deeper problems anyhow. - if (is_default_device) { - // dump any logical devices that explicitly opened this device. Things that opened the system default can stay. - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - if (!logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. - SDL_assert(deviceidx < total_devices); - devices[deviceidx++] = logdev->instance_id; - } - } - } else { - // report _all_ logical devices as disconnected. - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - SDL_assert(deviceidx < total_devices); - devices[deviceidx++] = logdev->instance_id; - } + // Save off removal info in a list so we can send events for each, next + // time the event queue pumps, in case something tries to close a device + // from an event filter, as this would risk deadlocks and other disasters + // if done from the device thread. + SDL_PendingAudioDeviceEvent pending; + pending.next = NULL; + SDL_PendingAudioDeviceEvent *pending_tail = &pending; + + // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. + // on non-default devices, dump everything. + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + if (!is_default_device || !logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. + SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; + p->devid = logdev->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; } - - SDL_assert(deviceidx < total_devices); - devices[deviceidx++] = device->instance_id; - total_devices = deviceidx; } } - // Let go of the lock before sending events, so an event filter trying to close a device won't deadlock with the device thread. + SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; + p->devid = device->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } + SDL_UnlockMutex(device->lock); - if (devices) { // NULL if event is disabled or disaster struck. - const Uint8 iscapture = device->iscapture ? 1 : 0; - for (int i = 0; i < total_devices; i++) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_REMOVED; - event.adevice.which = devices[i]; - event.adevice.iscapture = iscapture; - SDL_PushEvent(&event); - } - SDL_small_free(devices, isstack); + if (pending.next) { // NULL if event is disabled or disaster struck. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); + current_audio.pending_events_tail->next = pending.next; + current_audio.pending_events_tail = pending_tail; + SDL_UnlockRWLock(current_audio.device_hash_lock); } // Is this a non-default device? We can unref it now. @@ -688,7 +681,6 @@ int SDL_InitAudio(const char *driver_name) return -1; } - // Select the proper audio driver if (driver_name == NULL) { driver_name = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); @@ -724,6 +716,7 @@ int SDL_InitAudio(const char *driver_name) if (SDL_strcasecmp(bootstrap[i]->name, driver_attempt) == 0) { tried_to_init = SDL_TRUE; SDL_zero(current_audio); + current_audio.pending_events_tail = ¤t_audio.pending_events; SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. current_audio.device_hash_lock = device_hash_lock; current_audio.device_hash = device_hash; @@ -748,6 +741,7 @@ int SDL_InitAudio(const char *driver_name) tried_to_init = SDL_TRUE; SDL_zero(current_audio); + current_audio.pending_events_tail = ¤t_audio.pending_events; SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. current_audio.device_hash_lock = device_hash_lock; current_audio.device_hash = device_hash; @@ -769,11 +763,9 @@ int SDL_InitAudio(const char *driver_name) } } - SDL_zero(current_audio); SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); - current_audio.device_hash_lock = NULL; - current_audio.device_hash = NULL; + SDL_zero(current_audio); return -1; // No driver was available, so fail. } @@ -820,10 +812,18 @@ void SDL_QuitAudio(void) SDL_AtomicSet(¤t_audio.shutting_down, 1); SDL_HashTable *device_hash = current_audio.device_hash; current_audio.device_hash = NULL; + SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next; + current_audio.pending_events.next = NULL; SDL_AtomicSet(¤t_audio.output_device_count, 0); SDL_AtomicSet(¤t_audio.capture_device_count, 0); SDL_UnlockRWLock(current_audio.device_hash_lock); + SDL_PendingAudioDeviceEvent *pending_next = NULL; + for (SDL_PendingAudioDeviceEvent *i = pending_events; i != NULL; i = pending_next) { + pending_next = i->next; + SDL_free(i); + } + const void *key; const void *value; void *iter = NULL; @@ -848,7 +848,6 @@ void SDL_QuitAudio(void) void SDL_AudioThreadFinalize(SDL_AudioDevice *device) { - UnrefPhysicalAudioDevice(device); } static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) @@ -864,7 +863,6 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(!device->iscapture); - RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1014,7 +1012,6 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) { SDL_assert(device->iscapture); - RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately). current_audio.impl.ThreadInit(device); } @@ -1321,14 +1318,9 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * // this expects the device lock to be held. !!! FIXME: no it doesn't...? static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { - SDL_AtomicSet(&device->shutdown, 1); // alert device thread that it should terminate. - + SDL_AtomicSet(&device->shutdown, 1); if (device->thread != NULL) { - if (SDL_GetThreadID(device->thread) == SDL_ThreadID()) { - SDL_DetachThread(device->thread); // we _are_ the device thread, just drift off into the ether when finished, nothing is waiting for us. - } else { - SDL_WaitThread(device->thread, NULL); // we're not the device thread, wait for it to terminate. - } + SDL_WaitThread(device->thread, NULL); device->thread = NULL; } @@ -1350,6 +1342,7 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) SDL_copyp(&device->spec, &device->default_spec); device->sample_frames = 0; device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); + SDL_AtomicSet(&device->shutdown, 0); // ready to go again. } void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) @@ -1358,13 +1351,14 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) if (logdev) { SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); - UnrefPhysicalAudioDevice(device); // one reference for each logical device. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. ClosePhysicalAudioDevice(device); } + + UnrefPhysicalAudioDevice(device); // one reference for each logical device. } } @@ -1446,8 +1440,6 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec return 0; // Braaaaaaaaains. } - SDL_AtomicSet(&device->shutdown, 0); // make sure we don't kill the new thread immediately. - // These start with the backend's implementation, but we might swap them out with zombie versions later. device->WaitDevice = current_audio.impl.WaitDevice; device->PlayDevice = current_audio.impl.PlayDevice; @@ -2098,3 +2090,37 @@ int SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *n return retval; } +// This is an internal function, so SDL_PumpEvents() can check for pending audio device events. +// ("UpdateSubsystem" is the same naming that the other things that hook into PumpEvents use.) +void SDL_UpdateAudio(void) +{ + SDL_LockRWLockForReading(current_audio.device_hash_lock); + SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next; + SDL_UnlockRWLock(current_audio.device_hash_lock); + + if (!pending_events) { + return; // nothing to do, check next time. + } + + // okay, let's take this whole list of events so we can dump the lock, and new ones can queue up for a later update. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + pending_events = current_audio.pending_events.next; // in case this changed... + current_audio.pending_events.next = NULL; + current_audio.pending_events_tail = ¤t_audio.pending_events; + SDL_UnlockRWLock(current_audio.device_hash_lock); + + SDL_PendingAudioDeviceEvent *pending_next = NULL; + for (SDL_PendingAudioDeviceEvent *i = pending_events; i != NULL; i = pending_next) { + pending_next = i->next; + if (SDL_EventEnabled(i->type)) { + SDL_Event event; + SDL_zero(event); + event.type = i->type; + event.adevice.which = (Uint32) i->devid; + event.adevice.iscapture = (i->devid & (1<<0)) ? 0 : 1; // bit #0 of devid is set for output devices and unset for capture. + SDL_PushEvent(&event); + } + SDL_free(i); + } +} + diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 9d607bf8886a1..374616c2c456a 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -151,6 +151,14 @@ typedef struct SDL_AudioDriverImpl SDL_bool OnlyHasDefaultCaptureDevice; // !!! FIXME: is there ever a time where you'd have a default output and not a default capture (or vice versa)? } SDL_AudioDriverImpl; + +typedef struct SDL_PendingAudioDeviceEvent +{ + Uint32 type; + SDL_AudioDeviceID devid; + struct SDL_PendingAudioDeviceEvent *next; +} SDL_PendingAudioDeviceEvent; + typedef struct SDL_AudioDriver { const char *name; // The name of this audio driver @@ -161,6 +169,8 @@ typedef struct SDL_AudioDriver SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams. SDL_AudioDeviceID default_output_device_id; SDL_AudioDeviceID default_capture_device_id; + SDL_PendingAudioDeviceEvent pending_events; + SDL_PendingAudioDeviceEvent *pending_events_tail; // !!! FIXME: most (all?) of these don't have to be atomic. SDL_AtomicInt output_device_count; @@ -284,7 +294,7 @@ struct SDL_AudioDevice // non-zero if we are signaling the audio thread to end. SDL_AtomicInt shutdown; - // non-zero if this was a disconnected default device and we're waiting for its replacement. + // non-zero if this was a disconnected device and we're waiting for it to be decommissioned. SDL_AtomicInt zombie; // SDL_TRUE if this is a capture device instead of an output device diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 368499227fb80..32afd20bc87ae 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -181,8 +181,6 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - // limit to native freq device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; }); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index f52dae593ef79..5772fbe056507 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -111,8 +111,6 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) } SDL_zerop(device->hidden); - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - // Parse the audio format and fill the Be raw audio format media_raw_audio_format format; SDL_zero(format); diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 703122c8a8aad..77e2f03fa9909 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -300,8 +300,6 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) return SDL_OutOfMemory(); } - RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread. - client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); device->hidden->client = client; if (client == NULL) { diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 055009fb09d00..13aa0ca9e8e54 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -861,6 +861,11 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) _this->PumpEvents(_this); } +#ifndef SDL_AUDIO_DISABLED + extern void SDL_UpdateAudio(void); // this is internal-only, so it doesn't have a hint and is not a public API. + SDL_UpdateAudio(); +#endif + #ifndef SDL_SENSOR_DISABLED /* Check for sensor state change */ if (SDL_update_sensors) { From 4ac38d13ddce8d247041f92fc45f4ac00c106674 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 00:59:40 -0400 Subject: [PATCH 128/725] alsa: Don't touch free'd memory in hotplug thread. --- src/audio/alsa/SDL_alsa_audio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 5e116d653d4e8..0cec9bf5e2005 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -724,10 +724,13 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", iscapture ? "capture" : "output", name, desc); handle = SDL_strdup(name); - if (handle == NULL) { + dev->name = SDL_strdup(name); + if (!handle || !dev->name) { if (hint) { free(desc); // This should NOT be SDL_free() } + SDL_free(handle); + SDL_free(dev->name); SDL_free(dev); return; } @@ -739,7 +742,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A if (hint) { free(desc); // This should NOT be SDL_free() } - dev->name = handle; + dev->iscapture = iscapture; dev->next = *pSeen; *pSeen = dev; @@ -875,6 +878,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name)); + SDL_free(dev->name); SDL_free(dev); } } @@ -939,6 +943,7 @@ static void ALSA_DeinitializeStart(void) for (dev = hotplug_devices; dev; dev = next) { //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; + SDL_free(dev->name); SDL_free(dev); } hotplug_devices = NULL; From a844d909426153985136433f28ee5621affce97e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 08:27:24 -0700 Subject: [PATCH 129/725] Add missing error reporting in Android_JNI_FileOpen() Fixes https://github.com/libsdl-org/SDL/issues/8427 --- src/core/android/SDL_android.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 34c939e3b206c..8bf816610a0d1 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -1975,12 +1975,12 @@ int Android_JNI_FileOpen(SDL_RWops *ctx, } if (asset_manager == NULL) { - return -1; + return SDL_SetError("Couldn't create asset manager"); } asset = AAssetManager_open(asset_manager, fileName, AASSET_MODE_UNKNOWN); if (asset == NULL) { - return -1; + return SDL_SetError("Couldn't open asset '%s'", fileName); } ctx->hidden.androidio.asset = (void *)asset; From c2a3112b6f4b333762900824afc1b339ff5960e3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 08:36:05 -0700 Subject: [PATCH 130/725] Added "--substring" to the help for rename_symbols.py --- build-scripts/rename_symbols.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-scripts/rename_symbols.py b/build-scripts/rename_symbols.py index d6cf879e17f26..33a92dde042cf 100755 --- a/build-scripts/rename_symbols.py +++ b/build-scripts/rename_symbols.py @@ -25,7 +25,7 @@ def main(): else: if len(args.args) < 3: - print("Usage: %s oldname newname files_or_directories ..." % sys.argv[0]) + print("Usage: %s [--substring] oldname newname files_or_directories ..." % sys.argv[0]) exit(1) replacements = { args.args[0]: args.args[1] } From c98a14fdeba77e7e6fccacc36a6657839a801f40 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 08:59:07 -0700 Subject: [PATCH 131/725] Renamed display added/removed events for consistency with the rest of the API Fixes https://github.com/libsdl-org/SDL/issues/8425 --- docs/README-migration.md | 2 +- include/SDL3/SDL_events.h | 4 ++-- include/SDL3/SDL_oldnames.h | 8 ++++---- src/events/SDL_displayevents.c | 4 ++-- src/events/SDL_events.c | 4 ++-- src/test/SDL_test_common.c | 8 ++++---- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 6 +++--- src/video/windows/SDL_windowsmodes.c | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index db1b8db00669f..ae1693de7c9b0 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -738,7 +738,7 @@ The following functions have been renamed: * SDL_PixelFormatEnumToMasks() => SDL_GetMasksForPixelFormatEnum() The following symbols have been renamed: -* SDL_DISPLAYEVENT_DISCONNECTED => SDL_EVENT_DISPLAY_DISCONNECTED +* SDL_DISPLAYEVENT_DISCONNECTED => SDL_EVENT_DISPLAY_REMOVED * SDL_DISPLAYEVENT_MOVED => SDL_EVENT_DISPLAY_MOVED * SDL_DISPLAYEVENT_ORIENTATION => SDL_EVENT_DISPLAY_ORIENTATION * SDL_WINDOWEVENT_CLOSE => SDL_EVENT_WINDOW_CLOSE_REQUESTED diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index a3c5cced02dee..4e93b0fb13053 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -92,8 +92,8 @@ typedef enum /* Display events */ /* 0x150 was SDL_DISPLAYEVENT, reserve the number for sdl2-compat */ SDL_EVENT_DISPLAY_ORIENTATION = 0x151, /**< Display orientation has changed to data1 */ - SDL_EVENT_DISPLAY_CONNECTED, /**< Display has been added to the system */ - SDL_EVENT_DISPLAY_DISCONNECTED, /**< Display has been removed from the system */ + SDL_EVENT_DISPLAY_ADDED, /**< Display has been added to the system */ + SDL_EVENT_DISPLAY_REMOVED, /**< Display has been removed from the system */ SDL_EVENT_DISPLAY_MOVED, /**< Display has changed position */ SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */ SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION, diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 68f33080eabf6..9eb6994564691 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -91,8 +91,8 @@ #define SDL_ControllerDeviceEvent SDL_GamepadDeviceEvent #define SDL_ControllerSensorEvent SDL_GamepadSensorEvent #define SDL_ControllerTouchpadEvent SDL_GamepadTouchpadEvent -#define SDL_DISPLAYEVENT_CONNECTED SDL_EVENT_DISPLAY_CONNECTED -#define SDL_DISPLAYEVENT_DISCONNECTED SDL_EVENT_DISPLAY_DISCONNECTED +#define SDL_DISPLAYEVENT_CONNECTED SDL_EVENT_DISPLAY_ADDED +#define SDL_DISPLAYEVENT_DISCONNECTED SDL_EVENT_DISPLAY_REMOVED #define SDL_DISPLAYEVENT_MOVED SDL_EVENT_DISPLAY_MOVED #define SDL_DISPLAYEVENT_ORIENTATION SDL_EVENT_DISPLAY_ORIENTATION #define SDL_DROPBEGIN SDL_EVENT_DROP_BEGIN @@ -539,8 +539,8 @@ #define SDL_ControllerDeviceEvent SDL_ControllerDeviceEvent_renamed_SDL_GamepadDeviceEvent #define SDL_ControllerSensorEvent SDL_ControllerSensorEvent_renamed_SDL_GamepadSensorEvent #define SDL_ControllerTouchpadEvent SDL_ControllerTouchpadEvent_renamed_SDL_GamepadTouchpadEvent -#define SDL_DISPLAYEVENT_CONNECTED SDL_DISPLAYEVENT_CONNECTED_renamed_SDL_EVENT_DISPLAY_CONNECTED -#define SDL_DISPLAYEVENT_DISCONNECTED SDL_DISPLAYEVENT_DISCONNECTED_renamed_SDL_EVENT_DISPLAY_DISCONNECTED +#define SDL_DISPLAYEVENT_CONNECTED SDL_DISPLAYEVENT_CONNECTED_renamed_SDL_EVENT_DISPLAY_ADDED +#define SDL_DISPLAYEVENT_DISCONNECTED SDL_DISPLAYEVENT_DISCONNECTED_renamed_SDL_EVENT_DISPLAY_REMOVED #define SDL_DISPLAYEVENT_MOVED SDL_DISPLAYEVENT_MOVED_renamed_SDL_EVENT_DISPLAY_MOVED #define SDL_DISPLAYEVENT_ORIENTATION SDL_DISPLAYEVENT_ORIENTATION_renamed_SDL_EVENT_DISPLAY_ORIENTATION #define SDL_DROPBEGIN SDL_DROPBEGIN_renamed_SDL_EVENT_DROP_BEGIN diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index edccb033f6240..2e1a2ceaf78ca 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -54,8 +54,8 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, } switch (displayevent) { - case SDL_EVENT_DISPLAY_CONNECTED: - SDL_OnDisplayConnected(display); + case SDL_EVENT_DISPLAY_ADDED: + SDL_OnDisplayAdded(display); break; default: break; diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 13aa0ca9e8e54..ed40fd1e8d350 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -222,8 +222,8 @@ static void SDL_LogEvent(const SDL_Event *event) (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1); \ break SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ORIENTATION); - SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONNECTED); - SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DISCONNECTED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ADDED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED); #undef SDL_DISPLAYEVENT_CASE diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 57b65ea6bd07c..e4b62709b9655 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1566,8 +1566,8 @@ static void SDLTest_PrintEvent(SDL_Event *event) case SDL_EVENT_SYSTEM_THEME_CHANGED: SDL_Log("SDL EVENT: System theme changed to %s\n", SystemThemeName()); break; - case SDL_EVENT_DISPLAY_CONNECTED: - SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " connected", + case SDL_EVENT_DISPLAY_ADDED: + SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " attached", event->display.displayID); break; case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: @@ -1585,8 +1585,8 @@ static void SDLTest_PrintEvent(SDL_Event *event) SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed orientation to %s", event->display.displayID, DisplayOrientationName(event->display.data1)); break; - case SDL_EVENT_DISPLAY_DISCONNECTED: - SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " disconnected", + case SDL_EVENT_DISPLAY_REMOVED: + SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " removed", event->display.displayID); break; case SDL_EVENT_WINDOW_SHOWN: diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 20bb76912cbfa..56530fbab7804 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -521,7 +521,7 @@ extern SDL_bool SDL_HasWindows(void); extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int *abs_x, int *abs_y); extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y); -extern void SDL_OnDisplayConnected(SDL_VideoDisplay *display); +extern void SDL_OnDisplayAdded(SDL_VideoDisplay *display); extern void SDL_OnWindowShown(SDL_Window *window); extern void SDL_OnWindowHidden(SDL_Window *window); extern void SDL_OnWindowMoved(SDL_Window *window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 90a2467c519bd..91f0c4b9f9e7b 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -689,12 +689,12 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send } if (send_event) { - SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_CONNECTED, 0); + SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_ADDED, 0); } return id; } -void SDL_OnDisplayConnected(SDL_VideoDisplay *display) +void SDL_OnDisplayAdded(SDL_VideoDisplay *display) { SDL_Window *window; @@ -715,7 +715,7 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) display = _this->displays[display_index]; if (send_event) { - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_DISCONNECTED, 0); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_REMOVED, 0); } SDL_free(display->name); diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index df80ba3f6f59b..714c6f6387d1e 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -677,7 +677,7 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this) SDL_VideoDisplay *display = _this->displays[i]; SDL_DisplayData *driverdata = display->driverdata; if (driverdata->state == DisplayAdded) { - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CONNECTED, 0); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ADDED, 0); } } } From e07f6c0a17fbf60eca96152036b2494d0cfafecd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 10:42:36 -0700 Subject: [PATCH 132/725] SDL_IsJoystickProductWheel() returns SDL_TRUE for Asetek wheelbases (thanks @IOBYTE!) --- src/joystick/SDL_joystick.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 1a58402227bb9..335243ced0890 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2691,6 +2691,10 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid) MAKE_VIDPID(0x0eb7, 0x038e), /* Fanatec ClubSport Wheel Base V1 */ MAKE_VIDPID(0x0eb7, 0x0e03), /* Fanatec CSL Elite Wheel Base */ MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ + MAKE_VIDPID(0x2433, 0xf300), /* Asetek SimSports Invicta Wheelbase */ + MAKE_VIDPID(0x2433, 0xf301), /* Asetek SimSports Forte Wheelbase */ + MAKE_VIDPID(0x2433, 0xf303), /* Asetek SimSports La Prima Wheelbase */ + MAKE_VIDPID(0x2433, 0xf306), /* Asetek SimSports Tony Kannan Wheelbase */ }; int i; From 38afd48daf368c77118681b6155f49aeb88822a1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 09:46:09 -0700 Subject: [PATCH 133/725] Added a single source of SDL object IDs This ensures that we don't accidentally interpret an ID from one system as an ID in another system. Audio device IDs are not covered here, since they have a unique numbering system. --- src/SDL.c | 14 ++++++++++++++ src/SDL_internal.h | 1 + src/joystick/SDL_joystick.c | 10 ---------- src/joystick/SDL_joystick_c.h | 3 --- src/joystick/android/SDL_sysjoystick.c | 2 +- src/joystick/apple/SDL_mfijoystick.m | 2 +- src/joystick/bsd/SDL_bsdjoystick.c | 2 +- src/joystick/darwin/SDL_iokitjoystick.c | 2 +- src/joystick/hidapi/SDL_hidapijoystick.c | 2 +- src/joystick/linux/SDL_sysjoystick.c | 4 ++-- src/joystick/virtual/SDL_virtualjoystick.c | 2 +- src/joystick/windows/SDL_rawinputjoystick.c | 2 +- src/joystick/windows/SDL_windows_gaming_input.c | 2 +- src/joystick/windows/SDL_windowsjoystick.c | 2 +- src/sensor/SDL_sensor.c | 10 ---------- src/sensor/SDL_sensor_c.h | 3 --- src/sensor/android/SDL_androidsensor.c | 2 +- src/sensor/coremotion/SDL_coremotionsensor.m | 4 ++-- src/sensor/n3ds/SDL_n3dssensor.c | 4 ++-- src/sensor/vita/SDL_vitasensor.c | 4 ++-- src/sensor/windows/SDL_windowssensor.c | 2 +- src/video/SDL_sysvideo.h | 1 - src/video/SDL_video.c | 7 +++---- 23 files changed, 37 insertions(+), 50 deletions(-) diff --git a/src/SDL.c b/src/SDL.c index cfd096cdc1e5b..235233ce1ed1f 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -514,6 +514,20 @@ void SDL_Quit(void) SDL_bInMainQuit = SDL_FALSE; } +/* Assume we can wrap SDL_AtomicInt values and cast to Uint32 */ +SDL_COMPILE_TIME_ASSERT(sizeof_object_id, sizeof(int) == sizeof(Uint32)); + +Uint32 SDL_GetNextObjectID(void) +{ + static SDL_AtomicInt last_id; + + Uint32 id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; + if (id == 0) { + id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; + } + return id; +} + /* Get the library version number */ int SDL_GetVersion(SDL_version *ver) { diff --git a/src/SDL_internal.h b/src/SDL_internal.h index 3e2148c3df10e..aa2d6c6271f1f 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -197,6 +197,7 @@ extern "C" { #endif +extern DECLSPEC Uint32 SDLCALL SDL_GetNextObjectID(void); extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS); extern DECLSPEC int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); extern DECLSPEC int SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 335243ced0890..bf5b1f4f56a31 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -116,7 +116,6 @@ static SDL_bool SDL_joysticks_initialized; static SDL_bool SDL_joysticks_quitting; static SDL_bool SDL_joystick_being_added; static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; -static SDL_AtomicInt SDL_last_joystick_instance_id; static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; @@ -413,15 +412,6 @@ SDL_JoystickID *SDL_GetJoysticks(int *count) return joysticks; } -/* - * Return the next available joystick instance ID - * This may be called by drivers from multiple threads, unprotected by any locks - */ -SDL_JoystickID SDL_GetNextJoystickInstanceID(void) -{ - return SDL_AtomicIncRef(&SDL_last_joystick_instance_id) + 1; -} - /* * Get the implementation dependent name of a joystick */ diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 685fbebe31868..d81896e28e6be 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -53,9 +53,6 @@ extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_l /* Function to return whether there are any joysticks opened by the application */ extern SDL_bool SDL_JoysticksOpened(void); -/* Function to get the next available joystick instance ID */ -extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void); - /* Function to standardize the name for a controller This should be freed with SDL_free() when no longer needed */ diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index d8acacc36c09b..0b635ba5c2664 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -378,7 +378,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v } item->naxes = naxes; item->nhats = nhats; - item->device_instance = SDL_GetNextJoystickInstanceID(); + item->device_instance = SDL_GetNextObjectID(); if (SDL_joylist_tail == NULL) { SDL_joylist = SDL_joylist_tail = item; } else { diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 32f6f7ca848ee..b2daeac609825 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -561,7 +561,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet } device->accelerometer = accelerometer; - device->instance_id = SDL_GetNextJoystickInstanceID(); + device->instance_id = SDL_GetNextObjectID(); if (accelerometer) { #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 30ca7965fc14c..176e5eebd6ad0 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -466,7 +466,7 @@ static int MaybeAddDevice(const char *path) return -1; } - item->device_instance = SDL_GetNextJoystickInstanceID(); + item->device_instance = SDL_GetNextObjectID(); if (SDL_joylist_tail == NULL) { SDL_joylist = SDL_joylist_tail = item; } else { diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 7bbc4bd9e13aa..92650b7d48f64 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -549,7 +549,7 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender device->runLoopAttached = SDL_TRUE; /* Allocate an instance ID for this device */ - device->instance_id = SDL_GetNextJoystickInstanceID(); + device->instance_id = SDL_GetNextObjectID(); /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 7fa7da96a7dd2..7ee6abd5f8f57 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -790,7 +790,7 @@ SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJo } } - joystickID = SDL_GetNextJoystickInstanceID(); + joystickID = SDL_GetNextObjectID(); HIDAPI_AddJoystickInstanceToDevice(device, joystickID); for (i = 0; i < device->num_children; ++i) { diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index fea20069544f7..7d9a62ff06898 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -443,7 +443,7 @@ static int MaybeAddDevice(const char *path) return -1; } - item->device_instance = SDL_GetNextJoystickInstanceID(); + item->device_instance = SDL_GetNextObjectID(); if (SDL_joylist_tail == NULL) { SDL_joylist = SDL_joylist_tail = item; } else { @@ -615,7 +615,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG return SDL_FALSE; } - *device_instance = item->device_instance = SDL_GetNextJoystickInstanceID(); + *device_instance = item->device_instance = SDL_GetNextObjectID(); if (SDL_joylist_tail == NULL) { SDL_joylist = SDL_joylist_tail = item; } else { diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index b22ae6acc44cd..29ec65f98b0da 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -237,7 +237,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des } /* Allocate an instance ID for this device */ - hwdata->instance_id = SDL_GetNextJoystickInstanceID(); + hwdata->instance_id = SDL_GetNextObjectID(); /* Add virtual joystick to SDL-global lists */ if (g_VJoys) { diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index fd2e84249ce44..468dd92acea36 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -920,7 +920,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; - device->joystick_id = SDL_GetNextJoystickInstanceID(); + device->joystick_id = SDL_GetNextObjectID(); #ifdef DEBUG_RAWINPUT SDL_Log("Adding RAWINPUT device '%s' VID 0x%.4x, PID 0x%.4x, version %d, handle 0x%.8x\n", device->name, device->vendor_id, device->product_id, device->version, device->hDevice); diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 68c5e37140127..675e21537cd59 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -489,7 +489,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1)); if (controllers) { WindowsGamingInputControllerState *state = &controllers[wgi.controller_count]; - SDL_JoystickID joystickID = SDL_GetNextJoystickInstanceID(); + SDL_JoystickID joystickID = SDL_GetNextObjectID(); SDL_zerop(state); state->instance_id = joystickID; diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index cfb8908a4624b..173ac431edb4e 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -453,7 +453,7 @@ static void SDL_StopJoystickThread(void) void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device) { device->send_add_event = SDL_TRUE; - device->nInstanceID = SDL_GetNextJoystickInstanceID(); + device->nInstanceID = SDL_GetNextObjectID(); device->pNext = SYS_Joystick; SYS_Joystick = device; } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 85a828895efd7..9bc262858e499 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -58,7 +58,6 @@ static SDL_AtomicInt SDL_sensor_lock_pending; static int SDL_sensors_locked; static SDL_bool SDL_sensors_initialized; static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL; -static SDL_AtomicInt SDL_last_sensor_instance_id; static char SDL_sensor_magic; #define CHECK_SENSOR_MAGIC(sensor, retval) \ @@ -218,15 +217,6 @@ SDL_SensorID *SDL_GetSensors(int *count) return sensors; } -/* - * Return the next available sensor instance ID - * This may be called by drivers from multiple threads, unprotected by any locks - */ -SDL_SensorID SDL_GetNextSensorInstanceID(void) -{ - return SDL_AtomicIncRef(&SDL_last_sensor_instance_id) + 1; -} - /* * Get the driver and device index for a sensor instance ID * This should be called while the sensor lock is held, to prevent another thread from updating the list diff --git a/src/sensor/SDL_sensor_c.h b/src/sensor/SDL_sensor_c.h index ece9ec50df725..689a108920012 100644 --- a/src/sensor/SDL_sensor_c.h +++ b/src/sensor/SDL_sensor_c.h @@ -31,9 +31,6 @@ struct SDL_SensorDriver; /* Useful functions and variables from SDL_sensor.c */ -/* Function to get the next available sensor instance ID */ -extern SDL_SensorID SDL_GetNextSensorInstanceID(void); - /* Initialization and shutdown functions */ extern int SDL_InitSensors(void); extern void SDL_QuitSensors(void); diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index 856f64b3db827..f2556b7369b40 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -152,7 +152,7 @@ static int SDL_ANDROID_SensorInit(void) for (i = 0; i < sensors_count; ++i) { SDL_sensors[i].asensor = sensors[i]; - SDL_sensors[i].instance_id = SDL_GetNextSensorInstanceID(); + SDL_sensors[i].instance_id = SDL_GetNextObjectID(); } SDL_sensors_count = sensors_count; } diff --git a/src/sensor/coremotion/SDL_coremotionsensor.m b/src/sensor/coremotion/SDL_coremotionsensor.m index 6afe47c8fcf28..87021ca20759a 100644 --- a/src/sensor/coremotion/SDL_coremotionsensor.m +++ b/src/sensor/coremotion/SDL_coremotionsensor.m @@ -63,12 +63,12 @@ static int SDL_COREMOTION_SensorInit(void) i = 0; if (SDL_motion_manager.accelerometerAvailable) { SDL_sensors[i].type = SDL_SENSOR_ACCEL; - SDL_sensors[i].instance_id = SDL_GetNextSensorInstanceID(); + SDL_sensors[i].instance_id = SDL_GetNextObjectID(); ++i; } if (SDL_motion_manager.gyroAvailable) { SDL_sensors[i].type = SDL_SENSOR_GYRO; - SDL_sensors[i].instance_id = SDL_GetNextSensorInstanceID(); + SDL_sensors[i].instance_id = SDL_GetNextObjectID(); ++i; } SDL_sensors_count = sensors_count; diff --git a/src/sensor/n3ds/SDL_n3dssensor.c b/src/sensor/n3ds/SDL_n3dssensor.c index 21ccb4417569e..0e75c8e66880e 100644 --- a/src/sensor/n3ds/SDL_n3dssensor.c +++ b/src/sensor/n3ds/SDL_n3dssensor.c @@ -54,9 +54,9 @@ static int N3DS_SensorInit(void) } N3DS_sensors[0].type = SDL_SENSOR_ACCEL; - N3DS_sensors[0].instance_id = SDL_GetNextSensorInstanceID(); + N3DS_sensors[0].instance_id = SDL_GetNextObjectID(); N3DS_sensors[1].type = SDL_SENSOR_GYRO; - N3DS_sensors[1].instance_id = SDL_GetNextSensorInstanceID(); + N3DS_sensors[1].instance_id = SDL_GetNextObjectID(); return 0; } diff --git a/src/sensor/vita/SDL_vitasensor.c b/src/sensor/vita/SDL_vitasensor.c index 1f203103c419a..50838a46ff5e7 100644 --- a/src/sensor/vita/SDL_vitasensor.c +++ b/src/sensor/vita/SDL_vitasensor.c @@ -56,9 +56,9 @@ static int SDL_VITA_SensorInit(void) } SDL_sensors[0].type = SDL_SENSOR_ACCEL; - SDL_sensors[0].instance_id = SDL_GetNextSensorInstanceID(); + SDL_sensors[0].instance_id = SDL_GetNextObjectID(); SDL_sensors[1].type = SDL_SENSOR_GYRO; - SDL_sensors[1].instance_id = SDL_GetNextSensorInstanceID(); + SDL_sensors[1].instance_id = SDL_GetNextObjectID(); return 0; } diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index 3d209dc3391be..11fbe3ea3f523 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -315,7 +315,7 @@ static int ConnectSensor(ISensor *sensor) ++SDL_num_sensors; SDL_zerop(new_sensor); - new_sensor->id = SDL_GetNextSensorInstanceID(); + new_sensor->id = SDL_GetNextObjectID(); new_sensor->sensor = sensor; new_sensor->type = type; new_sensor->name = name; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 56530fbab7804..cb5e4c188e82e 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -364,7 +364,6 @@ struct SDL_VideoDevice SDL_Window *windows; SDL_Window *grabbed_window; Uint8 window_magic; - SDL_WindowID next_object_id; Uint32 clipboard_sequence; SDL_ClipboardDataCallback clipboard_callback; SDL_ClipboardCleanupCallback clipboard_cleanup; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 91f0c4b9f9e7b..d68c887004766 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -517,7 +517,6 @@ int SDL_VideoInit(const char *driver_name) pre_driver_error. */ _this = video; _this->name = bootstrap[i]->name; - _this->next_object_id = 1; _this->thread = SDL_ThreadID(); /* Set some very sane GL defaults */ @@ -664,7 +663,7 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send _this->displays = displays; _this->displays[_this->num_displays++] = new_display; - id = _this->next_object_id++; + id = SDL_GetNextObjectID(); SDL_memcpy(new_display, display, sizeof(*new_display)); new_display->id = id; new_display->device = _this; @@ -1950,7 +1949,7 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int return NULL; } window->magic = &_this->window_magic; - window->id = _this->next_object_id++; + window->id = SDL_GetNextObjectID(); window->windowed.x = window->x = x; window->windowed.y = window->y = y; window->windowed.w = window->w = w; @@ -2116,7 +2115,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) return NULL; } window->magic = &_this->window_magic; - window->id = _this->next_object_id++; + window->id = SDL_GetNextObjectID(); window->flags = flags; window->is_destroying = SDL_FALSE; window->display_scale = 1.0f; From b2ae1e835f26165b7efeef4e50625e0bc3f29c48 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 12:47:36 -0400 Subject: [PATCH 134/725] pulseaudio: Change debug printf calls to use SDL_Log instead. --- src/audio/pulseaudio/SDL_pulseaudio.c | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 73f5da4912a0a..b8ed1f9a3e0be 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -392,7 +392,7 @@ static int ConnectToPulseServer(void) static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata) { struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata; - //printf("PULSEAUDIO WRITE CALLBACK! nbytes=%u\n", (unsigned int) nbytes); + //SDL_Log("PULSEAUDIO WRITE CALLBACK! nbytes=%u", (unsigned int) nbytes); h->bytes_requested += nbytes; PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } @@ -403,16 +403,16 @@ static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) struct SDL_PrivateAudioData *h = device->hidden; int retval = 0; - //printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available); + //SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested == 0)) { - //printf("PULSEAUDIO WAIT IN WAITDEVICE!\n"); + //SDL_Log("PULSEAUDIO WAIT IN WAITDEVICE!"); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - //printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n"); + //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!"); retval = -1; break; } @@ -427,7 +427,7 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i { struct SDL_PrivateAudioData *h = device->hidden; - //printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available); + //SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available); SDL_assert(h->bytes_requested >= buffer_size); @@ -439,10 +439,10 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i return -1; } - //printf("PULSEAUDIO FEED! nbytes=%d\n", buffer_size); + //SDL_Log("PULSEAUDIO FEED! nbytes=%d", buffer_size); h->bytes_requested -= buffer_size; - //printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written); + //SDL_Log("PULSEAUDIO PLAYDEVICE END! written=%d", written); return 0; } @@ -464,7 +464,7 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata) { - //printf("PULSEAUDIO READ CALLBACK! nbytes=%u\n", (unsigned int) nbytes); + //SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes); PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the capture code queries what it needs, we just need to signal to end any wait } @@ -483,7 +483,7 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) while (!SDL_AtomicGet(&device->shutdown)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - //printf("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!\n"); + //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!"); retval = -1; break; } else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { @@ -496,7 +496,7 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment. } else { // store this fragment's data for use with CaptureFromDevice - //printf("PULSEAUDIO: captured %d new bytes\n", (int) nbytes); + //SDL_Log("PULSEAUDIO: captured %d new bytes", (int) nbytes); h->capturebuf = (const Uint8 *)data; h->capturelen = nbytes; break; @@ -516,7 +516,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i if (h->capturebuf != NULL) { const int cpy = SDL_min(buflen, h->capturelen); if (cpy > 0) { - //printf("PULSEAUDIO: fed %d captured bytes\n", cpy); + //SDL_Log("PULSEAUDIO: fed %d captured bytes", cpy); SDL_memcpy(buffer, h->capturebuf, cpy); h->capturebuf += cpy; h->capturelen -= cpy; @@ -550,7 +550,7 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - //printf("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!\n"); + //SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!"); SDL_AudioDeviceDisconnected(device); break; } @@ -648,7 +648,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) closefmts = SDL_ClosestAudioFormats(device->spec.format); while ((test_format = *(closefmts++)) != 0) { #ifdef DEBUG_AUDIO - fprintf(stderr, "Trying format 0x%4.4x\n", test_format); + SDL_Log("pulseaudio: Trying format 0x%4.4x", test_format); #endif switch (test_format) { case SDL_AUDIO_U8: @@ -843,13 +843,13 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data) { if (!default_sink_path || (SDL_strcmp(i->default_sink_name, default_sink_path) != 0)) { - //printf("DEFAULT SINK PATH CHANGED TO '%s'\n", i->default_sink_name); + //SDL_Log("DEFAULT SINK PATH CHANGED TO '%s'", i->default_sink_name); SDL_free(default_sink_path); default_sink_path = SDL_strdup(i->default_sink_name); } if (!default_source_path || (SDL_strcmp(i->default_source_name, default_source_path) != 0)) { - //printf("DEFAULT SOURCE PATH CHANGED TO '%s'\n", i->default_source_name); + //SDL_Log("DEFAULT SOURCE PATH CHANGED TO '%s'", i->default_source_name); SDL_free(default_source_path); default_source_path = SDL_strdup(i->default_source_name); } From 182cfc326526b40babe9d203dc8a907f2cddfd08 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 17:00:36 -0400 Subject: [PATCH 135/725] pulseaudio: Rework how we manage default devices and hotplug. This fixes problems where Pulse callbacks don't fire in the order we expect, or fail to fire at all, and avoids extra round trips to the Pulse server to lookup information we could have trivially obtained already. The end result is we would occasionally miss default device changes, etc, and this resolves that better. --- src/audio/pulseaudio/SDL_pulseaudio.c | 286 +++++++++++++------------- src/audio/pulseaudio/SDL_pulseaudio.h | 2 - 2 files changed, 139 insertions(+), 149 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index b8ed1f9a3e0be..6aef52928b936 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -39,6 +39,12 @@ typedef void (*pa_operation_notify_cb_t) (pa_operation *o, void *userdata); #endif +typedef struct PulseDeviceHandle +{ + char *device_path; + uint32_t device_index; +} PulseDeviceHandle; + // should we include monitors in the device list? Set at SDL_Init time static SDL_bool include_monitors = SDL_FALSE; @@ -47,12 +53,12 @@ static pa_context *pulseaudio_context = NULL; static SDL_Thread *pulseaudio_hotplug_thread = NULL; static SDL_AtomicInt pulseaudio_hotplug_thread_active; -// These are the OS identifiers (i.e. ALSA strings)... +// These are the OS identifiers (i.e. ALSA strings)...these are allocated in a callback +// when the default changes, and claimed/free'd by the hotplug thread when it alerts SDL +// to the change. static char *default_sink_path = NULL; static char *default_source_path = NULL; -// ... and these are the PulseAudio device indices of the default devices. -static uint32_t default_sink_index = 0; -static uint32_t default_source_index = 0; + static const char *(*PULSEAUDIO_pa_get_library_version)(void); static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto)( @@ -580,43 +586,9 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); SDL_free(device->hidden->mixbuf); - SDL_free(device->hidden->device_name); SDL_free(device->hidden); } -static void SinkDeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) -{ - if (i) { - char **devname = (char **)data; - *devname = SDL_strdup(i->name); - } - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); -} - -static void SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) -{ - if (i) { - char **devname = (char **)data; - *devname = SDL_strdup(i->name); - } - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); -} - -static SDL_bool FindDeviceName(SDL_AudioDevice *device) -{ - struct SDL_PrivateAudioData *h = device->hidden; - SDL_assert(device->handle != NULL); // this was a thing in SDL2, but shouldn't be in SDL3. - const uint32_t idx = ((uint32_t)((intptr_t)device->handle)) - 1; - - if (device->iscapture) { - WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceDeviceNameCallback, &h->device_name)); - } else { - WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkDeviceNameCallback, &h->device_name)); - } - - return h->device_name != NULL; -} - static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata) { PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details. @@ -708,58 +680,55 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - if (!FindDeviceName(device)) { - retval = SDL_SetError("Requested PulseAudio sink/source missing?"); + const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); + // The SDL ALSA output hints us that we use Windows' channel mapping + // https://bugzilla.libsdl.org/show_bug.cgi?id=110 + PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX); + + h->stream = PULSEAUDIO_pa_stream_new( + pulseaudio_context, + (name && *name) ? name : "Audio Stream", // stream description + &paspec, // sample format spec + &pacmap // channel map + ); + + if (h->stream == NULL) { + retval = SDL_SetError("Could not set up PulseAudio stream"); } else { - const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); - // The SDL ALSA output hints us that we use Windows' channel mapping - // https://bugzilla.libsdl.org/show_bug.cgi?id=110 - PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX); - - h->stream = PULSEAUDIO_pa_stream_new( - pulseaudio_context, - (name && *name) ? name : "Audio Stream", // stream description - &paspec, // sample format spec - &pacmap // channel map - ); - - if (h->stream == NULL) { - retval = SDL_SetError("Could not set up PulseAudio stream"); - } else { - int rc; + int rc; - PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL); + PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL); - // SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream. - flags |= PA_STREAM_DONT_MOVE; + // SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream. + flags |= PA_STREAM_DONT_MOVE; - if (iscapture) { - PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h); - rc = PULSEAUDIO_pa_stream_connect_record(h->stream, h->device_name, &paattr, flags); - } else { - PULSEAUDIO_pa_stream_set_write_callback(h->stream, WriteCallback, h); - rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL); + const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path; + if (iscapture) { + PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h); + rc = PULSEAUDIO_pa_stream_connect_record(h->stream, device_path, &paattr, flags); + } else { + PULSEAUDIO_pa_stream_set_write_callback(h->stream, WriteCallback, h); + rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, device_path, &paattr, flags, NULL, NULL); + } + + if (rc < 0) { + retval = SDL_SetError("Could not connect PulseAudio stream"); + } else { + int state = PULSEAUDIO_pa_stream_get_state(h->stream); + while (PA_STREAM_IS_GOOD(state) && (state != PA_STREAM_READY)) { + PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); + state = PULSEAUDIO_pa_stream_get_state(h->stream); } - if (rc < 0) { + if (!PA_STREAM_IS_GOOD(state)) { retval = SDL_SetError("Could not connect PulseAudio stream"); } else { - int state = PULSEAUDIO_pa_stream_get_state(h->stream); - while (PA_STREAM_IS_GOOD(state) && (state != PA_STREAM_READY)) { - PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); - state = PULSEAUDIO_pa_stream_get_state(h->stream); - } - - if (!PA_STREAM_IS_GOOD(state)) { - retval = SDL_SetError("Could not connect PulseAudio stream"); + const pa_buffer_attr *actual_bufattr = PULSEAUDIO_pa_stream_get_buffer_attr(h->stream); + if (!actual_bufattr) { + retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes"); } else { - const pa_buffer_attr *actual_bufattr = PULSEAUDIO_pa_stream_get_buffer_attr(h->stream); - if (!actual_bufattr) { - retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes"); - } else { - device->buffer_size = (int) iscapture ? actual_bufattr->tlength : actual_bufattr->fragsize; - device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); - } + device->buffer_size = (int) iscapture ? actual_bufattr->tlength : actual_bufattr->fragsize; + device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); } } } @@ -795,68 +764,69 @@ static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format) } } +static void AddPulseAudioDevice(const SDL_bool iscapture, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec) +{ + SDL_AudioSpec spec; + spec.format = PulseFormatToSDLFormat(sample_spec->format); + spec.channels = sample_spec->channels; + spec.freq = sample_spec->rate; + PulseDeviceHandle *handle = (PulseDeviceHandle *) SDL_malloc(sizeof (PulseDeviceHandle)); + if (handle) { + handle->device_path = SDL_strdup(name); + if (!handle->device_path) { + SDL_free(handle); + } else { + handle->device_index = index; + } + SDL_AddAudioDevice(iscapture, description, &spec, handle); + } +} + // This is called when PulseAudio adds an output ("sink") device. -// !!! FIXME: this is almost identical to SourceInfoCallback, merge the two. static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) { if (i) { - const SDL_bool add = (SDL_bool) ((intptr_t)data); - - if (add) { - SDL_AudioSpec spec; - spec.format = PulseFormatToSDLFormat(i->sample_spec.format); - spec.channels = i->sample_spec.channels; - spec.freq = i->sample_spec.rate; - SDL_AddAudioDevice(SDL_FALSE, i->description, &spec, (void *)((intptr_t)i->index + 1)); - } - - if (default_sink_path != NULL && SDL_strcmp(i->name, default_sink_path) == 0) { - default_sink_index = i->index; - } + AddPulseAudioDevice(SDL_FALSE, i->description, i->name, i->index, &i->sample_spec); } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } // This is called when PulseAudio adds a capture ("source") device. -// !!! FIXME: this is almost identical to SinkInfoCallback, merge the two. static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) { // Maybe skip "monitor" sources. These are just output from other sinks. if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) { - const SDL_bool add = (SDL_bool) ((intptr_t)data); - - if (add) { - SDL_AudioSpec spec; - spec.format = PulseFormatToSDLFormat(i->sample_spec.format); - spec.channels = i->sample_spec.channels; - spec.freq = i->sample_spec.rate; - SDL_AddAudioDevice(SDL_TRUE, i->description, &spec, (void *)((intptr_t)i->index + 1)); - } - - if (default_source_path != NULL && SDL_strcmp(i->name, default_source_path) == 0) { - default_source_index = i->index; - } + AddPulseAudioDevice(SDL_TRUE, i->description, i->name, i->index, &i->sample_spec); } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data) { - if (!default_sink_path || (SDL_strcmp(i->default_sink_name, default_sink_path) != 0)) { - //SDL_Log("DEFAULT SINK PATH CHANGED TO '%s'", i->default_sink_name); - SDL_free(default_sink_path); - default_sink_path = SDL_strdup(i->default_sink_name); - } + //SDL_Log("PULSEAUDIO ServerInfoCallback!"); + SDL_free(default_sink_path); + default_sink_path = SDL_strdup(i->default_sink_name); - if (!default_source_path || (SDL_strcmp(i->default_source_name, default_source_path) != 0)) { - //SDL_Log("DEFAULT SOURCE PATH CHANGED TO '%s'", i->default_source_name); - SDL_free(default_source_path); - default_source_path = SDL_strdup(i->default_source_name); - } + SDL_free(default_source_path); + default_source_path = SDL_strdup(i->default_source_name); PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } +static SDL_bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata) +{ + const uint32_t idx = (uint32_t) (uintptr_t) userdata; + const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; + return (handle->device_index == idx) ? SDL_TRUE : SDL_FALSE; +} + +static SDL_bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata) +{ + const char *path = (const char *) userdata; + const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; + return (SDL_strcmp(handle->device_path, path) == 0) ? SDL_TRUE : SDL_FALSE; +} + // This is called when PulseAudio has a device connected/removed/changed. static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data) { @@ -875,24 +845,26 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3 /* adds need sink details from the PulseAudio server. Another callback... (just unref all these operations right away, because we aren't going to wait on them and their callbacks will handle any work, so they can free as soon as that happens.) */ - if ((added || changed) && sink) { - PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkInfoCallback, (void *)((intptr_t)added))); - } else if ((added || changed) && source) { - PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceInfoCallback, (void *)((intptr_t)added))); + if (added && sink) { + PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkInfoCallback, NULL)); + } else if (added && source) { + PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceInfoCallback, NULL)); } else if (removed && (sink || source)) { // removes we can handle just with the device index. - SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)idx + 1))); + SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByIndex, (void *)(uintptr_t)idx)); } } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -static void CheckDefaultDevice(uint32_t *prev_default, uint32_t new_default) +static void CheckDefaultDevice(char **pnew_device) { - if (*prev_default != new_default) { - SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)new_default + 1)); - if (device) { - *prev_default = new_default; + char *new_device = *pnew_device; + if (new_device) { + SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, new_device); + if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later. + SDL_free(new_device); // done with this, free it. + *pnew_device = NULL; SDL_DefaultAudioDeviceChanged(device); } } @@ -901,8 +873,6 @@ static void CheckDefaultDevice(uint32_t *prev_default, uint32_t new_default) // this runs as a thread while the Pulse target is initialized to catch hotplug events. static int SDLCALL HotplugThread(void *data) { - uint32_t prev_default_sink_index = default_sink_index; - uint32_t prev_default_source_index = default_source_index; pa_operation *op; SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); @@ -922,11 +892,29 @@ static int SDLCALL HotplugThread(void *data) } // Update default devices; don't hold the pulse lock during this, since it could deadlock vs a playing device that we're about to lock here. + char *new_default_sink = default_sink_path; + char *new_default_source = default_source_path; + default_sink_path = default_source_path = NULL; // make sure we own these before releasing the lock. PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - CheckDefaultDevice(&prev_default_sink_index, default_sink_index); - CheckDefaultDevice(&prev_default_source_index, default_source_index); + CheckDefaultDevice(&new_default_sink); + CheckDefaultDevice(&new_default_source); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); + if (new_default_sink) { // couldn't find this device, try again later. + if (default_sink_path) { + SDL_free(new_default_sink); // uhoh, something else became default while we were unlocked. Dump ours. + } else { + default_sink_path = new_default_sink; // put string back to try again later. + } + } + + if (new_default_source) { // couldn't find this device, try again later. + if (default_source_path) { + SDL_free(new_default_source); // uhoh, something else became default while we were unlocked. Dump ours. + } else { + default_source_path = new_default_source; // put string back to try again later. + } + } } if (op) { @@ -936,8 +924,6 @@ static int SDLCALL HotplugThread(void *data) PULSEAUDIO_pa_context_set_subscribe_callback(pulseaudio_context, NULL, NULL); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); return 0; - - } static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) @@ -946,19 +932,20 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); WaitForPulseOperation(PULSEAUDIO_pa_context_get_server_info(pulseaudio_context, ServerInfoCallback, NULL)); - WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_list(pulseaudio_context, SinkInfoCallback, (void *)((intptr_t)SDL_TRUE))); - WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, (void *)((intptr_t)SDL_TRUE))); + WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_list(pulseaudio_context, SinkInfoCallback, NULL)); + WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, NULL)); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - SDL_AudioDevice *device; - device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)default_sink_index + 1)); - if (device) { - *default_output = device; + if (default_sink_path) { + *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); + SDL_free(default_sink_path); + default_sink_path = NULL; } - device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)default_source_index + 1)); - if (device) { - *default_capture = device; + if (default_source_path) { + *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); + SDL_free(default_source_path); + default_source_path = NULL; } // ok, we have a sane list, let's set up hotplug notifications now... @@ -968,6 +955,13 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio SDL_DestroySemaphore(ready_sem); } +static void PULSEAUDIO_FreeDeviceHandle(SDL_AudioDevice *device) +{ + PulseDeviceHandle *handle = (PulseDeviceHandle *) device->handle; + SDL_free(handle->device_path); + SDL_free(handle); +} + static void PULSEAUDIO_DeinitializeStart(void) { if (pulseaudio_hotplug_thread) { @@ -989,9 +983,6 @@ static void PULSEAUDIO_Deinitialize(void) SDL_free(default_source_path); default_source_path = NULL; - default_source_index = 0; - default_sink_index = 0; - UnloadPulseAudioLibrary(); } @@ -1017,6 +1008,7 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) impl->WaitCaptureDevice = PULSEAUDIO_WaitCaptureDevice; impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice; impl->FlushCapture = PULSEAUDIO_FlushCapture; + impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle; impl->HasCaptureSupport = SDL_TRUE; diff --git a/src/audio/pulseaudio/SDL_pulseaudio.h b/src/audio/pulseaudio/SDL_pulseaudio.h index 6a0328e3fd828..cc5e67e2aa95b 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/src/audio/pulseaudio/SDL_pulseaudio.h @@ -29,8 +29,6 @@ struct SDL_PrivateAudioData { - char *device_name; - // pulseaudio structures pa_stream *stream; From 4280d4b359d2ee156752ea0da568e2743d823f3c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 17:04:14 -0700 Subject: [PATCH 136/725] Fixed warning C4210: nonstandard extension used: function given file scope Resurrected SDL_audio_c.h, we knew it would be back... --- VisualC-GDK/SDL/SDL.vcxproj | 1 + VisualC-GDK/SDL/SDL.vcxproj.filters | 3 +++ VisualC-WinRT/SDL-UWP.vcxproj | 1 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 3 +++ VisualC/SDL/SDL.vcxproj | 1 + VisualC/SDL/SDL.vcxproj.filters | 3 +++ Xcode/SDL/SDL.xcodeproj/project.pbxproj | 4 ++++ src/audio/SDL_audio_c.h | 27 +++++++++++++++++++++++++ src/events/SDL_events.c | 2 +- 9 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/audio/SDL_audio_c.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 565362dbd5b95..bb003d0f08311 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -367,6 +367,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 3ebac004e3ab8..bbdc75985c4d5 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -411,6 +411,9 @@ API Headers + + audio + audio diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index f6c11b5a518f0..372a283396838 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -93,6 +93,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index f6aee5712a03e..92e6f4a8d4e7b 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -177,6 +177,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 219e93ed345e7..a40d5acb57176 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -317,6 +317,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 5dd954cf213fe..f72a3a0fca882 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -402,6 +402,9 @@ API Headers + + audio + audio diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 2fb3aca92e3bd..279a74856b0ff 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -238,6 +238,7 @@ A7D8B76A23E2514300DCD162 /* SDL_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A86623E2513F00DCD162 /* SDL_wave.c */; }; A7D8B79423E2514400DCD162 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87123E2513F00DCD162 /* SDL_dummyaudio.h */; }; A7D8B79A23E2514400DCD162 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A87223E2513F00DCD162 /* SDL_dummyaudio.c */; }; + A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */; }; A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A87723E2513F00DCD162 /* SDL_audiodev_c.h */; }; A7D8B81823E2514400DCD162 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A88F23E2513F00DCD162 /* SDL_audiodev.c */; }; A7D8B85A23E2514400DCD162 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A89F23E2513F00DCD162 /* SDL_sysaudio.h */; }; @@ -746,6 +747,7 @@ A7D8A86623E2513F00DCD162 /* SDL_wave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_wave.c; sourceTree = ""; }; A7D8A87123E2513F00DCD162 /* SDL_dummyaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dummyaudio.h; sourceTree = ""; }; A7D8A87223E2513F00DCD162 /* SDL_dummyaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyaudio.c; sourceTree = ""; }; + A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = ""; }; A7D8A87723E2513F00DCD162 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = ""; }; A7D8A88F23E2513F00DCD162 /* SDL_audiodev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiodev.c; sourceTree = ""; }; A7D8A89F23E2513F00DCD162 /* SDL_sysaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysaudio.h; sourceTree = ""; }; @@ -1813,6 +1815,7 @@ A7D8A8B923E2513F00DCD162 /* coreaudio */, A7D8A8AF23E2513F00DCD162 /* disk */, A7D8A87023E2513F00DCD162 /* dummy */, + A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */, F32DDAC92AB795A30041EAA5 /* SDL_audio_channel_converters.h */, F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */, A7D8A8B823E2513F00DCD162 /* SDL_audio.c */, @@ -2068,6 +2071,7 @@ A7D8B61723E2514300DCD162 /* SDL_assert_c.h in Headers */, F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */, F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */, + A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */, A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */, F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */, F3F7D9A52933074E00816151 /* SDL_bits.h in Headers */, diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h new file mode 100644 index 0000000000000..949d9e6c6e2c9 --- /dev/null +++ b/src/audio/SDL_audio_c.h @@ -0,0 +1,27 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_audio_c_h_ +#define SDL_audio_c_h_ + +extern void SDL_UpdateAudio(void); + +#endif /* SDL_audio_c_h_ */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index ed40fd1e8d350..7bf48cad09590 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -24,6 +24,7 @@ #include "SDL_events_c.h" #include "../SDL_hints_c.h" +#include "../audio/SDL_audio_c.h" #include "../timer/SDL_timer_c.h" #ifndef SDL_JOYSTICK_DISABLED #include "../joystick/SDL_joystick_c.h" @@ -862,7 +863,6 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) } #ifndef SDL_AUDIO_DISABLED - extern void SDL_UpdateAudio(void); // this is internal-only, so it doesn't have a hint and is not a public API. SDL_UpdateAudio(); #endif From e57fef8f0b7270952aae8b204e998f6164be43cf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 18:42:48 -0700 Subject: [PATCH 137/725] Fixed audio device removed events for ALSA --- src/audio/SDL_audio.c | 15 +++++++++++++++ src/audio/SDL_sysaudio.h | 3 +++ src/audio/alsa/SDL_alsa_audio.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 5afe415edb898..73d85c61fddce 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1265,6 +1265,21 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle) return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleCallback, handle); } +static SDL_bool TestDeviceHandleStringCallback(SDL_AudioDevice *device, void *handle) +{ + if (handle && device->handle) { + if (SDL_strcmp((char *)handle, (char *)device->handle) == 0) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandleString(const char *handle) +{ + return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleStringCallback, (void *)handle); +} + char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) { SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 374616c2c456a..2c0ac0e10795f 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -97,6 +97,9 @@ extern int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, co // Find the SDL_AudioDevice associated with the handle supplied to SDL_AddAudioDevice. NULL if not found. DOES NOT LOCK THE DEVICE. extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle); +// Find the SDL_AudioDevice associated with the handle as a string supplied to SDL_AddAudioDevice. NULL if not found. DOES NOT LOCK THE DEVICE. +extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandleString(const char *handle); + // Find an SDL_AudioDevice, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata); diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 0cec9bf5e2005..3d2042d559090 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -877,7 +877,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de for (ALSA_Device *dev = unseen; dev; dev = next) { //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; - SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name)); + SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandleString(dev->name)); SDL_free(dev->name); SDL_free(dev); } From a774694be0e64179cf6c193430d57d31b5658ff9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 22:01:05 -0400 Subject: [PATCH 138/725] pulseaudio: Simplified default device change detection code. This reduces allocations, simplifies some code, and makes it quick to decide from the hotplug thread if there was _actually_ a device change. --- src/audio/pulseaudio/SDL_pulseaudio.c | 86 +++++++++++++++------------ 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 6aef52928b936..6dab000286305 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -54,10 +54,12 @@ static SDL_Thread *pulseaudio_hotplug_thread = NULL; static SDL_AtomicInt pulseaudio_hotplug_thread_active; // These are the OS identifiers (i.e. ALSA strings)...these are allocated in a callback -// when the default changes, and claimed/free'd by the hotplug thread when it alerts SDL +// when the default changes, and noticed by the hotplug thread when it alerts SDL // to the change. static char *default_sink_path = NULL; static char *default_source_path = NULL; +static Uint32 default_sink_hash = 0; +static Uint32 default_source_hash = 0; static const char *(*PULSEAUDIO_pa_get_library_version)(void); @@ -804,11 +806,28 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data) { //SDL_Log("PULSEAUDIO ServerInfoCallback!"); - SDL_free(default_sink_path); - default_sink_path = SDL_strdup(i->default_sink_name); - SDL_free(default_source_path); - default_source_path = SDL_strdup(i->default_source_name); + Uint32 hash; // just hash the strings so we can decide if this is different without having to manage a string copy. + + hash = SDL_HashString(i->default_sink_name, NULL); + if (hash != default_sink_hash) { + char *str = SDL_strdup(i->default_sink_name); + if (str) { + SDL_free(default_sink_path); + default_sink_path = str; + default_sink_hash = hash; + } + } + + hash = SDL_HashString(i->default_source_name, NULL); + if (hash != default_source_hash) { + char *str = SDL_strdup(i->default_source_name); + if (str) { + SDL_free(default_source_path); + default_source_path = str; + default_source_hash = hash; + } + } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } @@ -857,14 +876,12 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3 PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -static void CheckDefaultDevice(char **pnew_device) +static void CheckDefaultDevice(char *new_device_path, Uint32 *prev_hash, Uint32 new_hash) { - char *new_device = *pnew_device; - if (new_device) { - SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, new_device); + if (new_device_path && (*prev_hash != new_hash)) { + SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, new_device_path); if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later. - SDL_free(new_device); // done with this, free it. - *pnew_device = NULL; + *prev_hash = new_hash; SDL_DefaultAudioDeviceChanged(device); } } @@ -873,6 +890,8 @@ static void CheckDefaultDevice(char **pnew_device) // this runs as a thread while the Pulse target is initialized to catch hotplug events. static int SDLCALL HotplugThread(void *data) { + Uint32 prev_default_sink_hash = default_sink_hash; + Uint32 prev_default_source_hash = default_source_hash; pa_operation *op; SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); @@ -892,28 +911,26 @@ static int SDLCALL HotplugThread(void *data) } // Update default devices; don't hold the pulse lock during this, since it could deadlock vs a playing device that we're about to lock here. - char *new_default_sink = default_sink_path; - char *new_default_source = default_source_path; + char *current_default_sink = default_sink_path; + char *current_default_source = default_source_path; default_sink_path = default_source_path = NULL; // make sure we own these before releasing the lock. + const Uint32 current_default_sink_hash = default_sink_hash; + const Uint32 current_default_source_hash = default_source_hash; PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - CheckDefaultDevice(&new_default_sink); - CheckDefaultDevice(&new_default_source); + CheckDefaultDevice(current_default_sink, &prev_default_sink_hash, current_default_sink_hash); + CheckDefaultDevice(current_default_source, &prev_default_source_hash, current_default_source_hash); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - if (new_default_sink) { // couldn't find this device, try again later. - if (default_sink_path) { - SDL_free(new_default_sink); // uhoh, something else became default while we were unlocked. Dump ours. - } else { - default_sink_path = new_default_sink; // put string back to try again later. - } + if (default_sink_path) { + SDL_free(current_default_sink); // uhoh, something else became default while we were unlocked. Dump ours. + } else { + default_sink_path = current_default_sink; // put string back for later. } - if (new_default_source) { // couldn't find this device, try again later. - if (default_source_path) { - SDL_free(new_default_source); // uhoh, something else became default while we were unlocked. Dump ours. - } else { - default_source_path = new_default_source; // put string back to try again later. - } + if (default_source_path) { + SDL_free(current_default_source); // uhoh, something else became default while we were unlocked. Dump ours. + } else { + default_source_path = current_default_source; // put string back for later. } } @@ -936,17 +953,8 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, NULL)); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - if (default_sink_path) { - *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); - SDL_free(default_sink_path); - default_sink_path = NULL; - } - - if (default_source_path) { - *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); - SDL_free(default_source_path); - default_source_path = NULL; - } + *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); + *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); // ok, we have a sane list, let's set up hotplug notifications now... SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1); @@ -980,8 +988,10 @@ static void PULSEAUDIO_Deinitialize(void) SDL_free(default_sink_path); default_sink_path = NULL; + default_sink_hash = 0; SDL_free(default_source_path); default_source_path = NULL; + default_source_hash = 0; UnloadPulseAudioLibrary(); } From 5ba03d377ab44c77c437c398221e936c2590efc5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 18:50:32 -0700 Subject: [PATCH 139/725] Revert "Fixed audio device removed events for ALSA" This reverts commit e57fef8f0b7270952aae8b204e998f6164be43cf. We actually need to match on a unique handle --- src/audio/SDL_audio.c | 15 --------------- src/audio/SDL_sysaudio.h | 3 --- src/audio/alsa/SDL_alsa_audio.c | 2 +- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 73d85c61fddce..5afe415edb898 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1265,21 +1265,6 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle) return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleCallback, handle); } -static SDL_bool TestDeviceHandleStringCallback(SDL_AudioDevice *device, void *handle) -{ - if (handle && device->handle) { - if (SDL_strcmp((char *)handle, (char *)device->handle) == 0) { - return SDL_TRUE; - } - } - return SDL_FALSE; -} - -SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandleString(const char *handle) -{ - return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleStringCallback, (void *)handle); -} - char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) { SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 2c0ac0e10795f..374616c2c456a 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -97,9 +97,6 @@ extern int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, co // Find the SDL_AudioDevice associated with the handle supplied to SDL_AddAudioDevice. NULL if not found. DOES NOT LOCK THE DEVICE. extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle); -// Find the SDL_AudioDevice associated with the handle as a string supplied to SDL_AddAudioDevice. NULL if not found. DOES NOT LOCK THE DEVICE. -extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandleString(const char *handle); - // Find an SDL_AudioDevice, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata); diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 3d2042d559090..0cec9bf5e2005 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -877,7 +877,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de for (ALSA_Device *dev = unseen; dev; dev = next) { //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; - SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandleString(dev->name)); + SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name)); SDL_free(dev->name); SDL_free(dev); } From 0413e21e546f2b889df054ba6313900fbb6ff258 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 19:03:13 -0700 Subject: [PATCH 140/725] Fixed audio device removed events for ALSA We don't match dev->name by string, since we might use the same string for both capture and output devices. Instead use the device pointer itself as the handle. @icculus, are we guaranteed the device pointer is valid in ALSA_OpenDevice()? --- src/audio/alsa/SDL_alsa_audio.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 0cec9bf5e2005..6f05686f97a42 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -203,11 +203,19 @@ static int LoadALSALibrary(void) #endif // SDL_AUDIO_DRIVER_ALSA_DYNAMIC +typedef struct ALSA_Device +{ + char *name; + SDL_bool iscapture; + struct ALSA_Device *next; +} ALSA_Device; + static const char *get_audio_device(void *handle, const int channels) { SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3. - if (SDL_strcmp((const char *) handle, "default") == 0) { + ALSA_Device *dev = (ALSA_Device *)handle; + if (SDL_strcmp(dev->name, "default") == 0) { const char *device = SDL_getenv("AUDIODEV"); // Is there a standard variable name? if (device != NULL) { return device; @@ -219,7 +227,7 @@ static const char *get_audio_device(void *handle, const int channels) return "default"; } - return (const char *)handle; + return dev->name; } // !!! FIXME: is there a channel swizzler in alsalib instead? @@ -690,7 +698,6 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A { ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device)); char *desc; - char *handle = NULL; char *ptr; if (dev == NULL) { @@ -723,13 +730,11 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", iscapture ? "capture" : "output", name, desc); - handle = SDL_strdup(name); dev->name = SDL_strdup(name); - if (!handle || !dev->name) { + if (!dev->name) { if (hint) { free(desc); // This should NOT be SDL_free() } - SDL_free(handle); SDL_free(dev->name); SDL_free(dev); return; @@ -738,7 +743,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A // Note that spec is NULL, because we are required to open the device before // acquiring the mix format, making this information inaccessible at // enumeration time - SDL_AddAudioDevice(iscapture, desc, NULL, handle); + SDL_AddAudioDevice(iscapture, desc, NULL, dev); if (hint) { free(desc); // This should NOT be SDL_free() } @@ -877,7 +882,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de for (ALSA_Device *dev = unseen; dev; dev = next) { //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); next = dev->next; - SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name)); + SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev)); SDL_free(dev->name); SDL_free(dev); } @@ -949,11 +954,6 @@ static void ALSA_DeinitializeStart(void) hotplug_devices = NULL; } -static void ALSA_FreeDeviceHandle(SDL_AudioDevice *device) -{ - SDL_free(device->handle); -} - static void ALSA_Deinitialize(void) { UnloadALSALibrary(); @@ -976,7 +976,6 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl) impl->WaitCaptureDevice = ALSA_WaitDevice; impl->CaptureFromDevice = ALSA_CaptureFromDevice; impl->FlushCapture = ALSA_FlushCapture; - impl->FreeDeviceHandle = ALSA_FreeDeviceHandle; impl->HasCaptureSupport = SDL_TRUE; From b8cc51875acb604dba5afe8b2686aea096d905ef Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 23 Oct 2023 19:36:14 -0700 Subject: [PATCH 141/725] Fixed build --- src/audio/alsa/SDL_alsa_audio.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 6f05686f97a42..5d12e1751ff9b 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -687,13 +687,6 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) return 0; // We're ready to rock and roll. :-) } -typedef struct ALSA_Device -{ - char *name; - SDL_bool iscapture; - struct ALSA_Device *next; -} ALSA_Device; - static void add_device(const SDL_bool iscapture, const char *name, void *hint, ALSA_Device **pSeen) { ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device)); From 865dd04068698eaee066cfda56c91049125eeecb Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Oct 2023 23:59:03 -0400 Subject: [PATCH 142/725] pulseaudio: Don't use a hash for device change detection. Both strings are _right there_ for comparing, so we can just set a flag to note the device definitely changed. Also simplified string management further; hotplug thread now makes a copy of the string before releasing the lock if there was a change event, so when the lock releases further events don't see a NULL and assume it's a new device, causing a lot of work to ripple out and decide nothing has changed, until the system stabilizes again. Now, it just does the right thing once. --- src/audio/pulseaudio/SDL_pulseaudio.c | 80 +++++++++++++-------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 6dab000286305..0a4d231efc018 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -58,8 +58,8 @@ static SDL_AtomicInt pulseaudio_hotplug_thread_active; // to the change. static char *default_sink_path = NULL; static char *default_source_path = NULL; -static Uint32 default_sink_hash = 0; -static Uint32 default_source_hash = 0; +static SDL_bool default_sink_changed = SDL_FALSE; +static SDL_bool default_source_changed = SDL_FALSE; static const char *(*PULSEAUDIO_pa_get_library_version)(void); @@ -807,25 +807,21 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat { //SDL_Log("PULSEAUDIO ServerInfoCallback!"); - Uint32 hash; // just hash the strings so we can decide if this is different without having to manage a string copy. - - hash = SDL_HashString(i->default_sink_name, NULL); - if (hash != default_sink_hash) { + if (!default_sink_path || (SDL_strcmp(default_sink_path, i->default_sink_name) != 0)) { char *str = SDL_strdup(i->default_sink_name); if (str) { SDL_free(default_sink_path); default_sink_path = str; - default_sink_hash = hash; + default_sink_changed = SDL_TRUE; } } - hash = SDL_HashString(i->default_source_name, NULL); - if (hash != default_source_hash) { + if (!default_source_path || (SDL_strcmp(default_source_path, i->default_source_name) != 0)) { char *str = SDL_strdup(i->default_source_name); if (str) { SDL_free(default_source_path); default_source_path = str; - default_source_hash = hash; + default_source_changed = SDL_TRUE; } } @@ -876,22 +872,25 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3 PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -static void CheckDefaultDevice(char *new_device_path, Uint32 *prev_hash, Uint32 new_hash) +static SDL_bool CheckDefaultDevice(const SDL_bool changed, char *device_path) { - if (new_device_path && (*prev_hash != new_hash)) { - SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, new_device_path); - if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later. - *prev_hash = new_hash; - SDL_DefaultAudioDeviceChanged(device); - } + if (!changed) { + return SDL_FALSE; // nothing's happening, leave the flag marked as unchanged. + } else if (!device_path) { + return SDL_TRUE; // check again later, we don't have a device name... + } + + SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, device_path); + if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later. + SDL_DefaultAudioDeviceChanged(device); + return SDL_FALSE; // changing complete, set flag to unchanged for future tests. } + return SDL_TRUE; // couldn't find the changed device, leave it marked as changed to try again later. } // this runs as a thread while the Pulse target is initialized to catch hotplug events. static int SDLCALL HotplugThread(void *data) { - Uint32 prev_default_sink_hash = default_sink_hash; - Uint32 prev_default_source_hash = default_source_hash; pa_operation *op; SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); @@ -911,27 +910,23 @@ static int SDLCALL HotplugThread(void *data) } // Update default devices; don't hold the pulse lock during this, since it could deadlock vs a playing device that we're about to lock here. - char *current_default_sink = default_sink_path; - char *current_default_source = default_source_path; - default_sink_path = default_source_path = NULL; // make sure we own these before releasing the lock. - const Uint32 current_default_sink_hash = default_sink_hash; - const Uint32 current_default_source_hash = default_source_hash; + SDL_bool check_default_sink = default_sink_changed; + SDL_bool check_default_source = default_source_changed; + char *current_default_sink = check_default_sink ? SDL_strdup(default_sink_path) : NULL; + char *current_default_source = check_default_source ? SDL_strdup(default_source_path) : NULL; + default_sink_changed = default_source_changed = SDL_FALSE; PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - CheckDefaultDevice(current_default_sink, &prev_default_sink_hash, current_default_sink_hash); - CheckDefaultDevice(current_default_source, &prev_default_source_hash, current_default_source_hash); + check_default_sink = CheckDefaultDevice(check_default_sink, current_default_sink); + check_default_source = CheckDefaultDevice(check_default_source, current_default_source); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - if (default_sink_path) { - SDL_free(current_default_sink); // uhoh, something else became default while we were unlocked. Dump ours. - } else { - default_sink_path = current_default_sink; // put string back for later. - } + // free our copies (which will be NULL if nothing changed) + SDL_free(current_default_sink); + SDL_free(current_default_source); - if (default_source_path) { - SDL_free(current_default_source); // uhoh, something else became default while we were unlocked. Dump ours. - } else { - default_source_path = current_default_source; // put string back for later. - } + // set these to true if we didn't handle the change OR there was _another_ change while we were working unlocked. + default_sink_changed = (default_sink_changed || check_default_sink) ? SDL_TRUE : SDL_FALSE; + default_source_changed = (default_source_changed || check_default_source) ? SDL_TRUE : SDL_FALSE; } if (op) { @@ -953,8 +948,13 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, NULL)); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); - *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); + if (default_sink_path) { + *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); + } + + if (default_source_path) { + *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); + } // ok, we have a sane list, let's set up hotplug notifications now... SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1); @@ -988,10 +988,10 @@ static void PULSEAUDIO_Deinitialize(void) SDL_free(default_sink_path); default_sink_path = NULL; - default_sink_hash = 0; + default_sink_changed = SDL_FALSE; SDL_free(default_source_path); default_source_path = NULL; - default_source_hash = 0; + default_source_changed = SDL_FALSE; UnloadPulseAudioLibrary(); } From b16165a33fdd993d0801d9e5cef79182c3f51530 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Oct 2023 14:42:02 -0400 Subject: [PATCH 143/725] rwlock: SDL_UnlockRWLock was incorrectly tagged with SDL_RELEASE_SHARED. It needs to be SDL_RELEASE_GENERIC, because it releases both exclusive (writer) and shared (reader) locks. Without this fix, clang's `-Wthread-safety` tests generate incorrect warnings. Reference Issue #8096. --- include/SDL3/SDL_mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 19c6b5557c56a..23fb86c302905 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -433,7 +433,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_ * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_SHARED(rwlock); +extern DECLSPEC int SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); /** * Destroy a read/write lock created with SDL_CreateRWLock(). From 124a0050b6e9aeed7f44723577064f7550030ef3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 24 Oct 2023 14:22:41 -0700 Subject: [PATCH 144/725] Fixed warning: no previous prototype for function 'SDL_UpdateAudio' --- src/audio/SDL_audio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 5afe415edb898..47d4878436e7b 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -20,6 +20,7 @@ */ #include "SDL_internal.h" +#include "SDL_audio_c.h" #include "SDL_sysaudio.h" #include "../thread/SDL_systhread.h" #include "../SDL_utils_c.h" From 39a961ba41430788774f1b8c0e6d63f7308116e7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 24 Oct 2023 16:41:19 -0700 Subject: [PATCH 145/725] Added support for "%[]" sscanf syntax Fixes https://github.com/libsdl-org/SDL/issues/8423 --- src/stdlib/SDL_string.c | 71 ++++++++++++++++++++++++++++++++ test/testautomation_stdlib.c | 78 +++++++++++++++++++++++++++++++++++- 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index ca6600137258f..baa794301d44c 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1199,6 +1199,39 @@ int SDL_vsscanf(const char *text, const char *fmt, va_list ap) return vsscanf(text, fmt, ap); } #else +static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len) +{ + SDL_bool invert = SDL_FALSE; + SDL_bool result = SDL_FALSE; + + if (*set == '^') { + invert = SDL_TRUE; + ++set; + --set_len; + } + while (set_len > 0 && !result) { + if (set_len >= 3 && set[1] == '-') { + char low_char = SDL_min(set[0], set[2]); + char high_char = SDL_max(set[0], set[2]); + if (c >= low_char && c <= high_char) { + result = SDL_TRUE; + } + set += 3; + set_len -= 3; + } else { + if (c == *set) { + result = SDL_TRUE; + } + ++set; + --set_len; + } + } + if (invert) { + result = result ? SDL_FALSE : SDL_TRUE; + } + return result; +} + /* NOLINTNEXTLINE(readability-non-const-parameter) */ int SDL_vsscanf(const char *text, const char *fmt, va_list ap) { @@ -1472,6 +1505,44 @@ int SDL_vsscanf(const char *text, const char *fmt, va_list ap) } done = SDL_TRUE; break; + case '[': + { + const char *set = fmt + 1; + while (*fmt && *fmt != ']') { + ++fmt; + } + if (*fmt) { + size_t set_len = (fmt - set); + if (suppress) { + while (CharacterMatchesSet(*text, set, set_len)) { + ++text; + if (count) { + if (--count == 0) { + break; + } + } + } + } else { + SDL_bool had_match = SDL_FALSE; + char *valuep = va_arg(ap, char *); + while (CharacterMatchesSet(*text, set, set_len)) { + had_match = SDL_TRUE; + *valuep++ = *text++; + if (count) { + if (--count == 0) { + break; + } + } + } + *valuep = '\0'; + if (had_match) { + ++retval; + } + } + } + } + done = SDL_TRUE; + break; default: done = SDL_TRUE; break; diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index e9960f046e991..ce2493990e2c2 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -585,7 +585,7 @@ static int stdlib_sscanf(void *arg) long long_output, expected_long_output; long long long_long_output, expected_long_long_output; size_t size_output, expected_size_output; - char text[128]; + char text[128], text2[128]; expected_output = output = 123; expected_result = -1; @@ -649,6 +649,82 @@ static int stdlib_sscanf(void *arg) SDLTest_AssertCheck(expected_size_output == size_output, "Check output, expected: %zu, got: %zu", expected_size_output, size_output); SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc def", "%s", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc def\", \"%%s\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc,def", "%s", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%s\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc,def") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc,def", "%[cba]", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[cba]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc,def", "%[a-z]", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[z-a]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc,def", "%[^,]", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[^,]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 0; + text[0] = '\0'; + result = SDL_sscanf("abc,def", "%[A-Z]", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[A-Z]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "") == 0, "Check output, expected: \"\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 2; + text[0] = '\0'; + text2[0] = '\0'; + result = SDL_sscanf("abc,def", "%[abc],%[def]", text, text2); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[abc],%%[def]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(SDL_strcmp(text2, "def") == 0, "Check output, expected: \"def\", got: \"%s\"", text2); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 2; + text[0] = '\0'; + text2[0] = '\0'; + result = SDL_sscanf("abc,def", "%[abc]%*[,]%[def]", text, text2); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc,def\", \"%%[abc]%%*[,]%%[def]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(SDL_strcmp(text2, "def") == 0, "Check output, expected: \"def\", got: \"%s\"", text2); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 2; + text[0] = '\0'; + text2[0] = '\0'; + result = SDL_sscanf("abc def", "%[abc] %[def]", text, text2); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc def\", \"%%[abc] %%[def]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc") == 0, "Check output, expected: \"abc\", got: \"%s\"", text); + SDLTest_AssertCheck(SDL_strcmp(text2, "def") == 0, "Check output, expected: \"def\", got: \"%s\"", text2); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + + expected_result = 1; + text[0] = '\0'; + result = SDL_sscanf("abc123XYZ", "%[a-zA-Z0-9]", text); + SDLTest_AssertPass("Call to SDL_sscanf(\"abc123XYZ\", \"%%[a-zA-Z0-9]\", text)"); + SDLTest_AssertCheck(SDL_strcmp(text, "abc123XYZ") == 0, "Check output, expected: \"abc123XYZ\", got: \"%s\"", text); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + return TEST_COMPLETED; } From 6efe957159d6e06db9d9fb9aee6065e5e1cd3939 Mon Sep 17 00:00:00 2001 From: ds-sloth <72112344+ds-sloth@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:06:49 -0400 Subject: [PATCH 146/725] SDL_n3dsaudio.c: separate mixer locks from audio device locks (cherry picked from commit 62266dbd4fa79090025317a71473eb764b2e1abe) (SDL3 audio backends don't have the LockDevice interfaces, so this just ended up being a comment.) --- src/audio/n3ds/SDL_n3dsaudio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index efc26542aeb88..31be34c3f1698 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -32,6 +32,7 @@ static dspHookCookie dsp_hook; static SDL_AudioDevice *audio_device; +// fully local functions related to the wavebufs / DSP, not the same as the `device->lock` SDL_Mutex! static SDL_INLINE void contextLock(SDL_AudioDevice *device) { LightLock_Lock(&device->hidden->lock); From 07171be596ff9ac1320c5f38a251647516909345 Mon Sep 17 00:00:00 2001 From: ds-sloth <72112344+ds-sloth@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:08:30 -0400 Subject: [PATCH 147/725] SDL_n3dsaudio.h: use triple buffering (cherry picked from commit 070f57820f401cb962e743bb3a4d12e346d6ed4b) --- src/audio/n3ds/SDL_n3dsaudio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/n3ds/SDL_n3dsaudio.h b/src/audio/n3ds/SDL_n3dsaudio.h index eb47ab19ed58b..e0f6617f5da63 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.h +++ b/src/audio/n3ds/SDL_n3dsaudio.h @@ -24,7 +24,7 @@ #include <3ds.h> -#define NUM_BUFFERS 2 // -- Don't lower this! +#define NUM_BUFFERS 3 // -- Minimum 2! struct SDL_PrivateAudioData { From 1023d8ec84056ffcc15e58107b11b9eaec808a12 Mon Sep 17 00:00:00 2001 From: ds-sloth <72112344+ds-sloth@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:09:53 -0400 Subject: [PATCH 148/725] SDL_n3dsaudio.c - don't risk leaving current_priority uninitialized (cherry picked from commit 6623c87d0b7f6bae2ac16991aea53551899481b9) --- src/audio/n3ds/SDL_n3dsaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index 31be34c3f1698..c0bb1a2422369 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -253,7 +253,7 @@ static void N3DSAUDIO_CloseDevice(SDL_AudioDevice *device) static void N3DSAUDIO_ThreadInit(SDL_AudioDevice *device) { - s32 current_priority; + s32 current_priority = 0x30; svcGetThreadPriority(¤t_priority, CUR_THREAD_HANDLE); current_priority--; // 0x18 is reserved for video, 0x30 is the default for main thread From e4cd1d40595abb0b4d28be495b93e54db645adae Mon Sep 17 00:00:00 2001 From: ds-sloth <72112344+ds-sloth@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:11:41 -0400 Subject: [PATCH 149/725] n3ds systhread - prefer to put audio thread on system core (cherry picked from commit 301ee21f33c7e2cef4a0c484640fb028378a2fc5) --- src/thread/n3ds/SDL_systhread.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/thread/n3ds/SDL_systhread.c b/src/thread/n3ds/SDL_systhread.c index 1f74ae37eb08a..4c7803a8ff646 100644 --- a/src/thread/n3ds/SDL_systhread.c +++ b/src/thread/n3ds/SDL_systhread.c @@ -49,15 +49,22 @@ static void ThreadEntry(void *arg) int SDL_SYS_CreateThread(SDL_Thread *thread) { - s32 priority; + s32 priority = 0x30; + int cpu = -1; size_t stack_size = GetStackSize(thread->stacksize); + svcGetThreadPriority(&priority, CUR_THREAD_HANDLE); + /* prefer putting audio thread on system core */ + if (thread->name && SDL_strcmp(thread->name, "SDLAudioP") == 0 && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) { + cpu = 1; + } + thread->handle = threadCreate(ThreadEntry, thread, stack_size, priority, - -1, + cpu, false); if (thread->handle == NULL) { From 6827b3331d01192bdb9af9d4d4e02b9a7173a2d9 Mon Sep 17 00:00:00 2001 From: ds-sloth <72112344+ds-sloth@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:12:14 -0400 Subject: [PATCH 150/725] n3ds systhread - use 80kb thread stack size as default, remove hard cap (cherry picked from commit 3823ba1ded857a8af52d765b2d3ae6641b15dfe1) --- src/thread/n3ds/SDL_systhread.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/thread/n3ds/SDL_systhread.c b/src/thread/n3ds/SDL_systhread.c index 4c7803a8ff646..8e92e8dcdb788 100644 --- a/src/thread/n3ds/SDL_systhread.c +++ b/src/thread/n3ds/SDL_systhread.c @@ -26,9 +26,8 @@ #include "../SDL_systhread.h" -/* N3DS has very limited RAM (128MB), so we put a limit on thread stack size. */ -#define N3DS_THREAD_STACK_SIZE_MAX (16 * 1024) -#define N3DS_THREAD_STACK_SIZE_DEFAULT (4 * 1024) +/* N3DS has very limited RAM (128MB), so we set a low default thread stack size. */ +#define N3DS_THREAD_STACK_SIZE_DEFAULT (80 * 1024) #define N3DS_THREAD_PRIORITY_LOW 0x3F /**< Minimum priority */ #define N3DS_THREAD_PRIORITY_MEDIUM 0x2F /**< Slightly higher than main thread (0x30) */ @@ -80,14 +79,6 @@ static size_t GetStackSize(size_t requested_size) return N3DS_THREAD_STACK_SIZE_DEFAULT; } - if (requested_size > N3DS_THREAD_STACK_SIZE_MAX) { - SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, - "Requested a thread size of %zu," - " falling back to the maximum supported of %zu\n", - requested_size, - N3DS_THREAD_STACK_SIZE_MAX); - requested_size = N3DS_THREAD_STACK_SIZE_MAX; - } return requested_size; } From b61706373c564e443f2a11875e58f2e9b505b0e2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Oct 2023 23:54:32 -0400 Subject: [PATCH 151/725] n3ds: Check that audio thread name starts with "SDLAudioP" The string has a number after it, so a basic SDL_strcmp() will never match. Reference PR #8346. (cherry picked from commit cba6090398f581415938aa53c232142c85d23009) --- src/thread/n3ds/SDL_systhread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thread/n3ds/SDL_systhread.c b/src/thread/n3ds/SDL_systhread.c index 8e92e8dcdb788..348c037230893 100644 --- a/src/thread/n3ds/SDL_systhread.c +++ b/src/thread/n3ds/SDL_systhread.c @@ -55,7 +55,7 @@ int SDL_SYS_CreateThread(SDL_Thread *thread) svcGetThreadPriority(&priority, CUR_THREAD_HANDLE); /* prefer putting audio thread on system core */ - if (thread->name && SDL_strcmp(thread->name, "SDLAudioP") == 0 && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) { + if (thread->name && (SDL_strncmp(thread->name, "SDLAudioP", 9) == 0) && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) { cpu = 1; } From f52b330ed84c477a94094302aa6a3baaca87019d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 25 Oct 2023 09:00:26 -0700 Subject: [PATCH 152/725] Added support for the HP HyperX Clutch Gladiate controller --- .../app/src/main/java/org/libsdl/app/HIDDeviceManager.java | 1 + src/hidapi/libusb/hid.c | 1 + src/joystick/controller_list.h | 1 + src/joystick/hidapi/SDL_hidapijoystick.c | 1 + 4 files changed, 4 insertions(+) diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index f79bf1862ce17..42e669471f1df 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -273,6 +273,7 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa final int XB1_IFACE_SUBCLASS = 71; final int XB1_IFACE_PROTOCOL = 208; final int[] SUPPORTED_VENDORS = { + 0x03f0, // HP 0x044f, // Thrustmaster 0x045e, // Microsoft 0x0738, // Mad Catz diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index 880f8d61b8bf8..e15bf319c0978 100644 --- a/src/hidapi/libusb/hid.c +++ b/src/hidapi/libusb/hid.c @@ -867,6 +867,7 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de static const int xb1_iface_subclass = 71; static const int xb1_iface_protocol = 208; static const int supported_vendors[] = { + 0x03f0, /* HP */ 0x044f, /* Thrustmaster */ 0x045e, /* Microsoft */ 0x0738, /* Mad Catz */ diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 8d77eb89c5306..ffb5a46bde5a9 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -296,6 +296,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x24c6, 0xfafd ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 3 { MAKE_CONTROLLER_ID( 0x24c6, 0xfafe ), k_eControllerType_XBox360Controller, NULL }, // Rock Candy Gamepad for Xbox 360 + { MAKE_CONTROLLER_ID( 0x03f0, 0x0495 ), k_eControllerType_XBoxOneController, NULL }, // HP HyperX Clutch Gladiate { MAKE_CONTROLLER_ID( 0x044f, 0xd012 ), k_eControllerType_XBoxOneController, NULL }, // ThrustMaster eSwap PRO Controller Xbox { MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad { MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad (Firmware 2015) diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 7ee6abd5f8f57..39cadbaf83e26 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -260,6 +260,7 @@ static SDL_GamepadType SDL_GetJoystickGameControllerProtocol(const char *name, U interface_protocol == XBONE_IFACE_PROTOCOL) { static const int SUPPORTED_VENDORS[] = { + 0x03f0, /* HP */ 0x044f, /* Thrustmaster */ 0x045e, /* Microsoft */ 0x0738, /* Mad Catz */ From ace0c2c29742b5e641c33523acc45b0cc1d3891c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Oct 2023 13:02:50 -0400 Subject: [PATCH 153/725] mutex: Fixed bug where generic SDL_TryLockMutex would incorrectly block. Fixes #8433. --- src/thread/generic/SDL_sysmutex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index a735db973d3e7..8d4a3702d1eb3 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -118,7 +118,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) We set the locking thread id after we obtain the lock so unlocks from other threads will fail. */ - retval = SDL_WaitSemaphore(mutex->sem); + retval = SDL_TryWaitSemaphore(mutex->sem); if (retval == 0) { mutex->owner = this_thread; mutex->recursive = 0; From 23ceae94c958418b6584a804c34b94eee2774d60 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 25 Oct 2023 14:50:07 -0700 Subject: [PATCH 154/725] Fixed Xbox 360 Controller support using libusb on Linux --- src/hidapi/libusb/hid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index e15bf319c0978..3cdb891020bbe 100644 --- a/src/hidapi/libusb/hid.c +++ b/src/hidapi/libusb/hid.c @@ -123,6 +123,7 @@ struct hid_device_ { /* Quirks */ int skip_output_report_id; + int no_skip_output_report_id; int no_output_reports_on_intr_ep; /* List of received input reports. */ @@ -1347,6 +1348,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa /* Initialize XBox 360 controllers */ if (is_xbox360(desc.idVendor, intf_desc)) { + dev->no_skip_output_report_id = 1; init_xbox360(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc); } @@ -1572,7 +1574,7 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t report_number = data[0]; - if (report_number == 0x0 || dev->skip_output_report_id) { + if ((!dev->no_skip_output_report_id && report_number == 0x0) || dev->skip_output_report_id) { data++; length--; skipped_report_id = 1; From a9aa15c792c4add1936fb4bc098db0da306127bb Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 26 Oct 2023 01:03:40 +0300 Subject: [PATCH 155/725] CI: change FreeBSD CI runner to cross-platform-actions. --- .../{vmactions.yml => cpactions.yml} | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) rename .github/workflows/{vmactions.yml => cpactions.yml} (86%) diff --git a/.github/workflows/vmactions.yml b/.github/workflows/cpactions.yml similarity index 86% rename from .github/workflows/vmactions.yml rename to .github/workflows/cpactions.yml index cdcf340b4bc60..b4ebb38d99d72 100644 --- a/.github/workflows/vmactions.yml +++ b/.github/workflows/cpactions.yml @@ -1,4 +1,4 @@ -name: Build (VM Actions) +name: Build (C/P Actions) on: [push, pull_request] @@ -8,18 +8,19 @@ concurrency: jobs: freebsd: - runs-on: macos-12 + runs-on: ubuntu-latest name: FreeBSD timeout-minutes: 30 steps: - uses: actions/checkout@v3 - name: Build - uses: vmactions/freebsd-vm@v0 + uses: cross-platform-actions/action@v0.19.1 with: - mem: 8192 - usesh: true - prepare: | - pkg install -y \ + operating_system: freebsd + version: '13.2' + run: | + sudo pkg update + sudo pkg install -y \ cmake \ ninja \ pkgconf \ @@ -46,11 +47,8 @@ jobs: dbus \ zh-fcitx \ ibus \ - libsamplerate \ libudev-devd - - run: | - cmake -S . -B build -GNinja \ + cmake -S . -B build -GNinja \ -Wdeprecated -Wdev -Werror \ -DCMAKE_BUILD_TYPE=Release \ -DSDL_HIDAPI_LIBUSB=OFF \ From 082ef41566362281d954c8f2d35f1cc171e83d58 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 25 Oct 2023 19:26:40 -0400 Subject: [PATCH 156/725] alsa: Fix crash from invalid handle pointer ALSA expects handles to be of type ALSA_Device, and passing the handle for the default device as a plain string causes a crash as it attempts to deference the string contents itself as a pointer to a string. Create immutable static ALSA_Device structs for the default devices and pass those as the handles. They are not placed in the hotplug list, and the audio layer doesn't attempt to free ALSA handles, so there is no need to worry about them being erroneously freed. --- src/audio/alsa/SDL_alsa_audio.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 5d12e1751ff9b..46ba1dc797267 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -210,6 +210,18 @@ typedef struct ALSA_Device struct ALSA_Device *next; } ALSA_Device; +static const ALSA_Device default_output_handle = { + "default", + SDL_FALSE, + NULL +}; + +static const ALSA_Device default_capture_handle = { + "default", + SDL_TRUE, + NULL +}; + static const char *get_audio_device(void *handle, const int channels) { SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3. @@ -911,10 +923,10 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE; ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. if (has_default_output) { - *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, SDL_strdup("default")); + *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, (void*)&default_output_handle); } if (has_default_capture) { - *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, SDL_strdup("default")); + *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, (void*)&default_capture_handle); } #if SDL_ALSA_HOTPLUG_THREAD From 899eb0d04216fcef77b0c9f2fad5acfd4d35234c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Oct 2023 10:00:26 -0400 Subject: [PATCH 157/725] thread: Locking mutexes and rwlocks are now void functions. Almost nothing checks these return values, and there's no reason a valid lock should fail to operate. The cases where a lock isn't valid (it's a bogus pointer, it was previously destroyed, a thread is unlocking a lock it doesn't own, etc) are undefined behavior and always were, and should be treated as an application bug. Reference Issue #8096. --- docs/README-migration.md | 2 + include/SDL3/SDL_mutex.h | 56 +++++---- src/SDL_properties.c | 66 +++++------ src/audio/SDL_audiocvt.c | 12 +- src/dynapi/SDL_dynapi_procs.h | 10 +- src/thread/generic/SDL_sysmutex.c | 135 +++++++++------------- src/thread/generic/SDL_sysrwlock.c | 122 +++++++++----------- src/thread/generic/SDL_sysrwlock_c.h | 10 +- src/thread/n3ds/SDL_sysmutex.c | 40 ++----- src/thread/ngage/SDL_sysmutex.cpp | 28 ++--- src/thread/psp/SDL_sysmutex.c | 101 ++++++----------- src/thread/pthread/SDL_sysmutex.c | 150 +++++++++++-------------- src/thread/pthread/SDL_sysrwlock.c | 53 ++++----- src/thread/stdcpp/SDL_sysmutex.cpp | 59 +++------- src/thread/stdcpp/SDL_sysrwlock.cpp | 90 ++++++--------- src/thread/vita/SDL_sysmutex.c | 89 +++++---------- src/thread/windows/SDL_sysmutex.c | 81 +++++-------- src/thread/windows/SDL_sysmutex_c.h | 4 +- src/thread/windows/SDL_sysrwlock_srw.c | 88 ++++++--------- test/testlock.c | 11 +- test/testrwlock.c | 23 ++-- 21 files changed, 490 insertions(+), 740 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index ae1693de7c9b0..aa1b044f1209a 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -707,6 +707,8 @@ The following functions have been renamed: ## SDL_mutex.h +SDL_LockMutex and SDL_UnlockMutex now return void; if the mutex is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the mutex is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior. + The following functions have been renamed: * SDL_CondBroadcast() => SDL_BroadcastCondition() * SDL_CondSignal() => SDL_SignalCondition() diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 23fb86c302905..7dd150259f67c 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -169,13 +169,15 @@ extern DECLSPEC SDL_Mutex *SDLCALL SDL_CreateMutex(void); * unlock it the same number of times before it is actually made available for * other threads in the system (this is known as a "recursive mutex"). * + * This function does not fail; if mutex is NULL, it will return immediately + * having locked nothing. If the mutex is valid, this function will always + * block until it can lock the mutex, and return with it locked. + * * \param mutex the mutex to lock - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); +extern DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); /** * Try to lock a mutex without blocking. @@ -186,9 +188,13 @@ extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); * This technique is useful if you need exclusive access to a resource but * don't want to wait for it, and will return to it to try again later. * + * This function does not fail; if mutex is NULL, it will return 0 immediately + * having locked nothing. If the mutex is valid, this function will always + * either lock the mutex and return 0, or return SDL_MUTEX_TIMEOUT and lock + * nothing. + * * \param mutex the mutex to try to lock - * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for - * more information. + * \returns 0 or `SDL_MUTEX_TIMEDOUT` * * \since This function is available since SDL 3.0.0. * @@ -210,12 +216,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0 * thread, and doing so results in undefined behavior. * * \param mutex the mutex to unlock. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex); +extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex); /** * Destroy a mutex created with SDL_CreateMutex(). @@ -321,15 +325,17 @@ extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void); * lock before requesting a read-only lock. (But, of course, if you have the * write lock, you don't need further locks to read in any case.) * + * This function does not fail; if rwlock is NULL, it will return immediately + * having locked nothing. If the rwlock is valid, this function will always + * block until it can lock the mutex, and return with it locked. + * * \param rwlock the read/write lock to lock - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_UnlockRWLock */ -extern DECLSPEC int SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock); +extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock); /** * Lock the read/write lock for _write_ operations. @@ -348,15 +354,17 @@ extern DECLSPEC int SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQ * read-only lock. Doing so results in undefined behavior. Unlock the * read-only lock before requesting a write lock. * + * This function does not fail; if rwlock is NULL, it will return immediately + * having locked nothing. If the rwlock is valid, this function will always + * block until it can lock the mutex, and return with it locked. + * * \param rwlock the read/write lock to lock - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_UnlockRWLock */ -extern DECLSPEC int SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock); +extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock); /** * Try to lock a read/write lock _for reading_ without blocking. @@ -370,9 +378,13 @@ extern DECLSPEC int SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQ * Trying to lock for read-only access can succeed if other threads are * holding read-only locks, as this won't prevent access. * + * This function does not fail; if rwlock is NULL, it will return 0 immediately + * having locked nothing. If rwlock is valid, this function will always + * either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock + * nothing. + * * \param rwlock the rwlock to try to lock - * \returns 0, `SDL_RWLOCK_TIMEDOUT`, or -1 on error; call SDL_GetError() for - * more information. + * \returns 0 or `SDL_RWLOCK_TIMEDOUT` * * \since This function is available since SDL 3.0.0. * @@ -400,9 +412,13 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_ * read-only lock. Doing so results in undefined behavior. Unlock the * read-only lock before requesting a write lock. * + * This function does not fail; if rwlock is NULL, it will return 0 immediately + * having locked nothing. If rwlock is valid, this function will always + * either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock + * nothing. + * * \param rwlock the rwlock to try to lock - * \returns 0, `SDL_RWLOCK_TIMEDOUT`, or -1 on error; call SDL_GetError() for - * more information. + * \returns 0 or `SDL_RWLOCK_TIMEDOUT` * * \since This function is available since SDL 3.0.0. * @@ -428,12 +444,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_ * thread, and doing so results in undefined behavior. * * \param rwlock the rwlock to unlock. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); +extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); /** * Destroy a read/write lock created with SDL_CreateRWLock(). diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 22613752d3d97..0b8d795347811 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -123,17 +123,16 @@ SDL_PropertiesID SDL_CreateProperties(void) goto error; } - if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) { + SDL_LockRWLockForWriting(SDL_properties_lock); + ++SDL_last_properties_id; + if (SDL_last_properties_id == 0) { ++SDL_last_properties_id; - if (SDL_last_properties_id == 0) { - ++SDL_last_properties_id; - } - props = SDL_last_properties_id; - if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { - inserted = SDL_TRUE; - } - SDL_UnlockRWLock(SDL_properties_lock); } + props = SDL_last_properties_id; + if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { + inserted = SDL_TRUE; + } + SDL_UnlockRWLock(SDL_properties_lock); if (inserted) { /* All done! */ @@ -152,15 +151,17 @@ int SDL_LockProperties(SDL_PropertiesID props) if (!props) { return SDL_InvalidParamError("props"); } - if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { - SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); - } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + if (!properties) { - SDL_InvalidParamError("props"); - return -1; + return SDL_InvalidParamError("props"); } - return SDL_LockMutex(properties->lock); + + SDL_LockMutex(properties->lock); + return 0; } void SDL_UnlockProperties(SDL_PropertiesID props) @@ -170,13 +171,15 @@ void SDL_UnlockProperties(SDL_PropertiesID props) if (!props) { return; } - if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { - SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); - } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + if (!properties) { return; } + SDL_UnlockMutex(properties->lock); } @@ -193,10 +196,10 @@ int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void return SDL_InvalidParamError("name"); } - if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { - SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); - } + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + if (!properties) { return SDL_InvalidParamError("props"); } @@ -242,10 +245,10 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) return NULL; } - if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) { - SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); - } + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + if (!properties) { SDL_InvalidParamError("props"); return NULL; @@ -280,8 +283,7 @@ void SDL_DestroyProperties(SDL_PropertiesID props) return; } - if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) { - SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props); - SDL_UnlockRWLock(SDL_properties_lock); - } + SDL_LockRWLockForWriting(SDL_properties_lock); + SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props); + SDL_UnlockRWLock(SDL_properties_lock); } diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 7681e76cb9cd4..b64ca480dc848 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -476,12 +476,20 @@ int SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallba int SDL_LockAudioStream(SDL_AudioStream *stream) { - return stream ? SDL_LockMutex(stream->lock) : SDL_InvalidParamError("stream"); + if (!stream) { + return SDL_InvalidParamError("stream"); + } + SDL_LockMutex(stream->lock); + return 0; } int SDL_UnlockAudioStream(SDL_AudioStream *stream) { - return stream ? SDL_UnlockMutex(stream->lock) : SDL_InvalidParamError("stream"); + if (!stream) { + return SDL_InvalidParamError("stream"); + } + SDL_UnlockMutex(stream->lock); + return 0; } int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec) diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index b8ac62c583b07..ac41615e9de1f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -519,9 +519,9 @@ SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, SDL_bool c),(a,b SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(void *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return) SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),) -SDL_DYNAPI_PROC(int,SDL_LockMutex,(SDL_Mutex *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LockRWLockForReading,(SDL_RWLock *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LockRWLockForWriting,(SDL_RWLock *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_LockMutex,(SDL_Mutex *a),(a),) +SDL_DYNAPI_PROC(void,SDL_LockRWLockForReading,(SDL_RWLock *a),(a),) +SDL_DYNAPI_PROC(void,SDL_LockRWLockForWriting,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(int,SDL_LockSurface,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(int,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return) @@ -706,8 +706,8 @@ SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForWriting,(SDL_RWLock *a),(a),return) SDL_DYNAPI_PROC(int,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return) SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),) -SDL_DYNAPI_PROC(int,SDL_UnlockMutex,(SDL_Mutex *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_UnlockRWLock,(SDL_RWLock *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_UnlockMutex,(SDL_Mutex *a),(a),) +SDL_DYNAPI_PROC(void,SDL_UnlockRWLock,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),) SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),) diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index 8d4a3702d1eb3..579d028ee3efa 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* An implementation of mutexes using semaphores */ +// An implementation of mutexes using semaphores #include "SDL_systhread_c.h" @@ -31,13 +31,9 @@ struct SDL_Mutex SDL_Semaphore *sem; }; -/* Create a mutex */ SDL_Mutex *SDL_CreateMutex(void) { - SDL_Mutex *mutex; - - /* Allocate mutex memory */ - mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex)); + SDL_Mutex *mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex)); #ifndef SDL_THREADS_DISABLED if (mutex) { @@ -52,12 +48,11 @@ SDL_Mutex *SDL_CreateMutex(void) } else { SDL_OutOfMemory(); } -#endif /* !SDL_THREADS_DISABLED */ +#endif // !SDL_THREADS_DISABLED return mutex; } -/* Free the mutex */ void SDL_DestroyMutex(SDL_Mutex *mutex) { if (mutex) { @@ -68,94 +63,72 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -/* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SDL_threadID this_thread; - - if (mutex == NULL) { - return 0; - } - - this_thread = SDL_ThreadID(); - if (mutex->owner == this_thread) { - ++mutex->recursive; - } else { - /* The order of operations is important. - We set the locking thread id after we obtain the lock - so unlocks from other threads will fail. - */ - SDL_WaitSemaphore(mutex->sem); - mutex->owner = this_thread; - mutex->recursive = 0; +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + SDL_threadID this_thread = SDL_ThreadID(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + SDL_WaitSemaphore(mutex->sem); + mutex->owner = this_thread; + mutex->recursive = 0; + } } - - return 0; #endif /* SDL_THREADS_DISABLED */ } -/* try Lock the mutex */ int SDL_TryLockMutex(SDL_Mutex *mutex) { -#ifdef SDL_THREADS_DISABLED - return 0; -#else int retval = 0; - SDL_threadID this_thread; - - if (mutex == NULL) { - return 0; - } - - this_thread = SDL_ThreadID(); - if (mutex->owner == this_thread) { - ++mutex->recursive; - } else { - /* The order of operations is important. - We set the locking thread id after we obtain the lock - so unlocks from other threads will fail. - */ - retval = SDL_TryWaitSemaphore(mutex->sem); - if (retval == 0) { - mutex->owner = this_thread; - mutex->recursive = 0; +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + SDL_threadID this_thread = SDL_ThreadID(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + retval = SDL_TryWaitSemaphore(mutex->sem); + if (retval == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } } } - +#endif // SDL_THREADS_DISABLED return retval; -#endif /* SDL_THREADS_DISABLED */ } -/* Unlock the mutex */ -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - if (mutex == NULL) { - return 0; - } - - /* If we don't own the mutex, we can't unlock it */ - if (SDL_ThreadID() != mutex->owner) { - return SDL_SetError("mutex not owned by this thread"); - } +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + // If we don't own the mutex, we can't unlock it + if (SDL_ThreadID() != mutex->owner) { + SDL_assert(!"Tried to unlock a mutex we don't own!"); + return; // (undefined behavior!) SDL_SetError("mutex not owned by this thread"); + } - if (mutex->recursive) { - --mutex->recursive; - } else { - /* The order of operations is important. - First reset the owner so another thread doesn't lock - the mutex and set the ownership before we reset it, - then release the lock semaphore. - */ - mutex->owner = 0; - SDL_PostSemaphore(mutex->sem); + if (mutex->recursive) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + SDL_PostSemaphore(mutex->sem); + } } - return 0; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED } diff --git a/src/thread/generic/SDL_sysrwlock.c b/src/thread/generic/SDL_sysrwlock.c index d88bee15d380c..a38b81d6ac76f 100644 --- a/src/thread/generic/SDL_sysrwlock.c +++ b/src/thread/generic/SDL_sysrwlock.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* An implementation of rwlocks using mutexes, condition variables, and atomics. */ +// An implementation of rwlocks using mutexes, condition variables, and atomics. #include "SDL_systhread_c.h" @@ -30,7 +30,7 @@ * will be chosen at runtime), the function names need to be * suffixed */ -/* !!! FIXME: this is quite a tapdance with macros and the build system, maybe we can simplify how we do this. --ryan. */ +// !!! FIXME: this is quite a tapdance with macros and the build system, maybe we can simplify how we do this. --ryan. #ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX #define SDL_CreateRWLock_generic SDL_CreateRWLock #define SDL_DestroyRWLock_generic SDL_DestroyRWLock @@ -95,63 +95,48 @@ void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock) } } -int SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { #ifndef SDL_THREADS_DISABLED - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } else if (SDL_LockMutex(rwlock->lock) == -1) { - return -1; + if (rwlock) { + // !!! FIXME: these don't have to be atomic, we always gate them behind a mutex. + SDL_LockMutex(rwlock->lock); + SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer! + SDL_AtomicAdd(&rwlock->reader_count, 1); + SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock. } - - SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); /* shouldn't be able to grab lock if there's a writer! */ - - SDL_AtomicAdd(&rwlock->reader_count, 1); - SDL_UnlockMutex(rwlock->lock); /* other readers can attempt to share the lock. */ #endif - - return 0; } -int SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { #ifndef SDL_THREADS_DISABLED - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } else if (SDL_LockMutex(rwlock->lock) == -1) { - return -1; - } + if (rwlock) { + SDL_LockMutex(rwlock->lock); + while (SDL_AtomicGet(&rwlock->reader_count) > 0) { // while something is holding the shared lock, keep waiting. + SDL_WaitCondition(rwlock->condition, rwlock->lock); // release the lock and wait for readers holding the shared lock to release it, regrab the lock. + } - while (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* while something is holding the shared lock, keep waiting. */ - SDL_WaitCondition(rwlock->condition, rwlock->lock); /* release the lock and wait for readers holding the shared lock to release it, regrab the lock. */ + // we hold the lock! + SDL_AtomicAdd(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! } - - /* we hold the lock! */ - SDL_AtomicAdd(&rwlock->writer_count, 1); /* we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! */ #endif - - return 0; } int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock) { #ifndef SDL_THREADS_DISABLED - int rc; - - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } - - rc = SDL_TryLockMutex(rwlock->lock); - if (rc != 0) { - /* !!! FIXME: there is a small window where a reader has to lock the mutex, and if we hit that, we will return SDL_RWLOCK_TIMEDOUT even though we could have shared the lock. */ - return rc; + if (rwlock) { + const int rc = SDL_TryLockMutex(rwlock->lock); + if (rc != 0) { + // !!! FIXME: there is a small window where a reader has to lock the mutex, and if we hit that, we will return SDL_RWLOCK_TIMEDOUT even though we could have shared the lock. + return rc; + } + + SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer! + SDL_AtomicAdd(&rwlock->reader_count, 1); + SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock. } - - SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); /* shouldn't be able to grab lock if there's a writer! */ - - SDL_AtomicAdd(&rwlock->reader_count, 1); - SDL_UnlockMutex(rwlock->lock); /* other readers can attempt to share the lock. */ #endif return 0; @@ -160,46 +145,41 @@ int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock) int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock) { #ifndef SDL_THREADS_DISABLED - int rc; - - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } else if ((rc = SDL_TryLockMutex(rwlock->lock)) != 0) { - return rc; - } - - if (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* a reader is using the shared lock, treat it as unavailable. */ - SDL_UnlockMutex(rwlock->lock); - return SDL_RWLOCK_TIMEDOUT; + if (rwlock) { + const int rc = SDL_TryLockMutex(rwlock->lock); + if (rc != 0) { + return rc; + } + + if (SDL_AtomicGet(&rwlock->reader_count) > 0) { // a reader is using the shared lock, treat it as unavailable. + SDL_UnlockMutex(rwlock->lock); + return SDL_RWLOCK_TIMEDOUT; + } + + // we hold the lock! + SDL_AtomicAdd(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! } - - /* we hold the lock! */ - SDL_AtomicAdd(&rwlock->writer_count, 1); /* we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! */ #endif return 0; } -int SDL_UnlockRWLock_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { #ifndef SDL_THREADS_DISABLED - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } + if (rwlock) { + SDL_LockMutex(rwlock->lock); // recursive lock for writers, readers grab lock to make sure things are sane. - SDL_LockMutex(rwlock->lock); /* recursive lock for writers, readers grab lock to make sure things are sane. */ + if (SDL_AtomicGet(&rwlock->reader_count) > 0) { // we're a reader + SDL_AtomicAdd(&rwlock->reader_count, -1); + SDL_BroadcastCondition(rwlock->condition); // alert any pending writers to attempt to try to grab the lock again. + } else if (SDL_AtomicGet(&rwlock->writer_count) > 0) { // we're a writer + SDL_AtomicAdd(&rwlock->writer_count, -1); + SDL_UnlockMutex(rwlock->lock); // recursive unlock. + } - if (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* we're a reader */ - SDL_AtomicAdd(&rwlock->reader_count, -1); - SDL_BroadcastCondition(rwlock->condition); /* alert any pending writers to attempt to try to grab the lock again. */ - } else if (SDL_AtomicGet(&rwlock->writer_count) > 0) { /* we're a writer */ - SDL_AtomicAdd(&rwlock->writer_count, -1); - SDL_UnlockMutex(rwlock->lock); /* recursive unlock. */ + SDL_UnlockMutex(rwlock->lock); } - - SDL_UnlockMutex(rwlock->lock); #endif - - return 0; } diff --git a/src/thread/generic/SDL_sysrwlock_c.h b/src/thread/generic/SDL_sysrwlock_c.h index 8247f8ebe684c..9083cc89c84e8 100644 --- a/src/thread/generic/SDL_sysrwlock_c.h +++ b/src/thread/generic/SDL_sysrwlock_c.h @@ -27,12 +27,12 @@ SDL_RWLock *SDL_CreateRWLock_generic(void); void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock); -int SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock); -int SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock); +void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock); +void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock); int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock); int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock); -int SDL_UnlockRWLock_generic(SDL_RWLock *rwlock); +void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock); -#endif /* SDL_THREAD_GENERIC_RWLOCK_SUFFIX */ +#endif // SDL_THREAD_GENERIC_RWLOCK_SUFFIX -#endif /* SDL_sysrwlock_c_h_ */ +#endif // SDL_sysrwlock_c_h_ diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 0995ad11f4a33..47e848582da2c 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -22,17 +22,13 @@ #ifdef SDL_THREAD_N3DS -/* An implementation of mutexes using libctru's RecursiveLock */ +// An implementation of mutexes using libctru's RecursiveLock #include "SDL_sysmutex_c.h" -/* Create a mutex */ SDL_Mutex *SDL_CreateMutex(void) { - SDL_Mutex *mutex; - - /* Allocate mutex memory */ - mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); + SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); if (mutex) { RecursiveLock_Init(&mutex->lock); } else { @@ -41,7 +37,6 @@ SDL_Mutex *SDL_CreateMutex(void) return mutex; } -/* Free the mutex */ void SDL_DestroyMutex(SDL_Mutex *mutex) { if (mutex) { @@ -49,38 +44,23 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -/* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + RecursiveLock_Lock(&mutex->lock); } - - RecursiveLock_Lock(&mutex->lock); - - return 0; } -/* try Lock the mutex */ int SDL_TryLockMutex(SDL_Mutex *mutex) { - if (mutex == NULL) { - return 0; - } - - return RecursiveLock_TryLock(&mutex->lock); + return (mutex == NULL) ? 0 : RecursiveLock_TryLock(&mutex->lock); } -/* Unlock the mutex */ -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + RecursiveLock_Unlock(&mutex->lock); } - - RecursiveLock_Unlock(&mutex->lock); - - return 0; } -#endif /* SDL_THREAD_N3DS */ +#endif // SDL_THREAD_N3DS diff --git a/src/thread/ngage/SDL_sysmutex.cpp b/src/thread/ngage/SDL_sysmutex.cpp index 9cc47d424d903..4d5e3b08cda40 100644 --- a/src/thread/ngage/SDL_sysmutex.cpp +++ b/src/thread/ngage/SDL_sysmutex.cpp @@ -67,17 +67,13 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Wait(); } - - RMutex rmutex; - rmutex.SetHandle(mutex->handle); - rmutex.Wait(); - - return 0; } /* Try to lock the mutex */ @@ -95,16 +91,12 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) #endif /* Unlock the mutex */ -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Signal(); } - - RMutex rmutex; - rmutex.SetHandle(mutex->handle); - rmutex.Signal(); - - return 0; } diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 8aaa96224d9fb..f6701bb123e10 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -22,7 +22,7 @@ #ifdef SDL_THREAD_PSP -/* An implementation of mutexes using semaphores */ +// An implementation of mutexes using semaphores #include "SDL_systhread_c.h" @@ -36,17 +36,11 @@ struct SDL_Mutex SceLwMutexWorkarea lock; }; -/* Create a mutex */ SDL_Mutex *SDL_CreateMutex(void) { - SDL_Mutex *mutex = NULL; - SceInt32 res = 0; - - /* Allocate mutex memory */ - mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); + SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); if (mutex) { - - res = sceKernelCreateLwMutex( + const SceInt32 res = sceKernelCreateLwMutex( &mutex->lock, "SDL mutex", SCE_KERNEL_MUTEX_ATTR_RECURSIVE, @@ -54,6 +48,8 @@ SDL_Mutex *SDL_CreateMutex(void) NULL); if (res < 0) { + SDL_free(mutex); + mutex = NULL; SDL_SetError("Error trying to create mutex: %lx", res); } } else { @@ -62,7 +58,6 @@ SDL_Mutex *SDL_CreateMutex(void) return mutex; } -/* Free the mutex */ void SDL_DestroyMutex(SDL_Mutex *mutex) { if (mutex) { @@ -71,75 +66,43 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -/* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - - if (mutex == NULL) { - return 0; - } - - res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); - if (res != SCE_KERNEL_ERROR_OK) { - return SDL_SetError("Error trying to lock mutex: %lx", res); +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + const SceInt32 res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); + SDL_assert(res == SCE_KERNEL_ERROR_OK); // assume we're in a lot of trouble if this assert fails. } - - return 0; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED } -/* Try to lock the mutex */ int SDL_TryLockMutex(SDL_Mutex *mutex) { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - - if (mutex == NULL) { - return 0; - } - - res = sceKernelTryLockLwMutex(&mutex->lock, 1); - switch (res) { - case SCE_KERNEL_ERROR_OK: - return 0; - break; - case SCE_KERNEL_ERROR_WAIT_TIMEOUT: - return SDL_MUTEX_TIMEDOUT; - break; - default: - return SDL_SetError("Error trying to lock mutex: %lx", res); - break; + int retval = 0; +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + const SceInt32 res = sceKernelTryLockLwMutex(&mutex->lock, 1); + if (res == SCE_KERNEL_ERROR_OK) { + retval = 0; + } else if (res == SCE_KERNEL_ERROR_WAIT_TIMEOUT) { + retval = SDL_MUTEX_TIMEDOUT; + } else { + SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails. + retval = SDL_MUTEX_TIMEDOUT; + } } - - return -1; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED + return retval; } -/* Unlock the mutex */ -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - - if (mutex == NULL) { - return 0; +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + const SceInt32 res = sceKernelUnlockLwMutex(&mutex->lock, 1); + SDL_assert(res == 0); // assume we're in a lot of trouble if this assert fails. } - - res = sceKernelUnlockLwMutex(&mutex->lock, 1); - if (res != 0) { - return SDL_SetError("Error trying to unlock mutex: %lx", res); - } - - return 0; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED } -#endif /* SDL_THREAD_PSP */ +#endif // SDL_THREAD_PSP diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index 5e3dd696e13c5..4b921e1a48171 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -30,7 +30,7 @@ SDL_Mutex *SDL_CreateMutex(void) SDL_Mutex *mutex; pthread_mutexattr_t attr; - /* Allocate the structure */ + // Allocate the structure mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex)); if (mutex) { pthread_mutexattr_init(&attr); @@ -39,7 +39,7 @@ SDL_Mutex *SDL_CreateMutex(void) #elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP) pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); #else - /* No extra attributes necessary */ + // No extra attributes necessary #endif if (pthread_mutex_init(&mutex->id, &attr) != 0) { SDL_SetError("pthread_mutex_init() failed"); @@ -60,116 +60,96 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -/* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { + if (mutex != NULL) { #ifdef FAKE_RECURSIVE_MUTEX - pthread_t this_thread; -#endif - - if (mutex == NULL) { - return 0; - } - -#ifdef FAKE_RECURSIVE_MUTEX - this_thread = pthread_self(); - if (mutex->owner == this_thread) { - ++mutex->recursive; - } else { - /* The order of operations is important. - We set the locking thread id after we obtain the lock - so unlocks from other threads will fail. - */ - if (pthread_mutex_lock(&mutex->id) == 0) { + pthread_t this_thread = pthread_self(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + const int rc = pthread_mutex_lock(&mutex->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. mutex->owner = this_thread; mutex->recursive = 0; - } else { - return SDL_SetError("pthread_mutex_lock() failed"); } - } #else - if (pthread_mutex_lock(&mutex->id) != 0) { - return SDL_SetError("pthread_mutex_lock() failed"); - } + const int rc = pthread_mutex_lock(&mutex->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. #endif - return 0; + } } int SDL_TryLockMutex(SDL_Mutex *mutex) { - int retval; - int result; -#ifdef FAKE_RECURSIVE_MUTEX - pthread_t this_thread; -#endif - - if (mutex == NULL) { - return 0; - } + int retval = 0; - retval = 0; + if (mutex != NULL) { #ifdef FAKE_RECURSIVE_MUTEX - this_thread = pthread_self(); - if (mutex->owner == this_thread) { - ++mutex->recursive; - } else { - /* The order of operations is important. - We set the locking thread id after we obtain the lock - so unlocks from other threads will fail. - */ - result = pthread_mutex_trylock(&mutex->id); - if (result == 0) { - mutex->owner = this_thread; - mutex->recursive = 0; - } else if (result == EBUSY) { - retval = SDL_MUTEX_TIMEDOUT; + pthread_t this_thread = pthread_self(); + if (mutex->owner == this_thread) { + ++mutex->recursive; } else { - retval = SDL_SetError("pthread_mutex_trylock() failed"); + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + const int result = pthread_mutex_trylock(&mutex->id); + if (result == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } else if (result == EBUSY) { + retval = SDL_MUTEX_TIMEDOUT; + } else { + SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails. + retval = SDL_MUTEX_TIMEDOUT; + } } - } #else - result = pthread_mutex_trylock(&mutex->id); - if (result != 0) { - if (result == EBUSY) { - retval = SDL_MUTEX_TIMEDOUT; - } else { - retval = SDL_SetError("pthread_mutex_trylock() failed"); + const int result = pthread_mutex_trylock(&mutex->id); + if (result != 0) { + if (result == EBUSY) { + retval = SDL_MUTEX_TIMEDOUT; + } else { + SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails. + retval = SDL_MUTEX_TIMEDOUT; + } } - } #endif + } + return retval; } -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (mutex == NULL) { - return 0; - } - + if (mutex != NULL) { #ifdef FAKE_RECURSIVE_MUTEX - /* We can only unlock the mutex if we own it */ - if (pthread_self() == mutex->owner) { - if (mutex->recursive) { - --mutex->recursive; + // We can only unlock the mutex if we own it + if (pthread_self() == mutex->owner) { + if (mutex->recursive) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + pthread_mutex_unlock(&mutex->id); + } } else { - /* The order of operations is important. - First reset the owner so another thread doesn't lock - the mutex and set the ownership before we reset it, - then release the lock semaphore. - */ - mutex->owner = 0; - pthread_mutex_unlock(&mutex->id); + return SDL_SetError("mutex not owned by this thread"); } - } else { - return SDL_SetError("mutex not owned by this thread"); - } #else - if (pthread_mutex_unlock(&mutex->id) != 0) { - return SDL_SetError("pthread_mutex_unlock() failed"); + const int rc = pthread_mutex_unlock(&mutex->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. +#endif // FAKE_RECURSIVE_MUTEX } -#endif /* FAKE_RECURSIVE_MUTEX */ - - return 0; } diff --git a/src/thread/pthread/SDL_sysrwlock.c b/src/thread/pthread/SDL_sysrwlock.c index 3624d369e91d0..485264e85e432 100644 --- a/src/thread/pthread/SDL_sysrwlock.c +++ b/src/thread/pthread/SDL_sysrwlock.c @@ -55,42 +55,36 @@ void SDL_DestroyRWLock(SDL_RWLock *rwlock) } } -int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); - } else if (pthread_rwlock_rdlock(&rwlock->id) != 0) { - return SDL_SetError("pthread_rwlock_rdlock() failed"); + if (rwlock) { + const int rc = pthread_rwlock_rdlock(&rwlock->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. } - return 0; } -int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); - } else if (pthread_rwlock_wrlock(&rwlock->id) != 0) { - return SDL_SetError("pthread_rwlock_wrlock() failed"); + if (rwlock) { + const int rc = pthread_rwlock_wrlock(&rwlock->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. } - return 0; } int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) { int retval = 0; - if (rwlock == NULL) { - retval = SDL_InvalidParamError("rwlock"); - } else { + if (rwlock) { const int result = pthread_rwlock_tryrdlock(&rwlock->id); if (result != 0) { - if (result == EBUSY) { - retval = SDL_RWLOCK_TIMEDOUT; - } else { - retval = SDL_SetError("pthread_rwlock_tryrdlock() failed"); + retval = SDL_RWLOCK_TIMEDOUT; + if (result != EBUSY) { + SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails. } } } + return retval; } @@ -98,15 +92,12 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) { int retval = 0; - if (rwlock == NULL) { - retval = SDL_InvalidParamError("rwlock"); - } else { + if (rwlock) { const int result = pthread_rwlock_trywrlock(&rwlock->id); if (result != 0) { - if (result == EBUSY) { - retval = SDL_RWLOCK_TIMEDOUT; - } else { - retval = SDL_SetError("pthread_rwlock_tryrdlock() failed"); + retval = SDL_RWLOCK_TIMEDOUT; + if (result != EBUSY) { + SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails. } } } @@ -114,13 +105,11 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) return retval; } -int SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); - } else if (pthread_rwlock_unlock(&rwlock->id) != 0) { - return SDL_SetError("pthread_rwlock_unlock() failed"); + if (rwlock) { + const int rc = pthread_rwlock_unlock(&rwlock->id); + SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails. } - return 0; } diff --git a/src/thread/stdcpp/SDL_sysmutex.cpp b/src/thread/stdcpp/SDL_sysmutex.cpp index 01181f09f5c58..3619c4139817c 100644 --- a/src/thread/stdcpp/SDL_sysmutex.cpp +++ b/src/thread/stdcpp/SDL_sysmutex.cpp @@ -27,74 +27,51 @@ extern "C" { #include #include "SDL_sysmutex_c.h" -#include +#include -/* Create a mutex */ -extern "C" SDL_Mutex * -SDL_CreateMutex(void) +extern "C" SDL_Mutex * SDL_CreateMutex(void) { - /* Allocate and initialize the mutex */ + // Allocate and initialize the mutex try { SDL_Mutex *mutex = new SDL_Mutex; return mutex; } catch (std::system_error &ex) { SDL_SetError("unable to create a C++ mutex: code=%d; %s", ex.code(), ex.what()); - return NULL; } catch (std::bad_alloc &) { SDL_OutOfMemory(); - return NULL; } + return NULL; } -/* Free the mutex */ -extern "C" void -SDL_DestroyMutex(SDL_Mutex *mutex) +extern "C" void SDL_DestroyMutex(SDL_Mutex *mutex) { if (mutex != NULL) { delete mutex; } } -/* Lock the mutex */ -extern "C" int -SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +extern "C" void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (mutex == NULL) { - return 0; - } - - try { - mutex->cpp_mutex.lock(); - return 0; - } catch (std::system_error &ex) { - return SDL_SetError("unable to lock a C++ mutex: code=%d; %s", ex.code(), ex.what()); + if (mutex != NULL) { + try { + mutex->cpp_mutex.lock(); + } catch (std::system_error &ex) { + SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails. + //return SDL_SetError("unable to lock a C++ mutex: code=%d; %s", ex.code(), ex.what()); + } } } -/* TryLock the mutex */ -int SDL_TryLockMutex(SDL_Mutex *mutex) +extern "C" int SDL_TryLockMutex(SDL_Mutex *mutex) { - int retval = 0; - - if (mutex == NULL) { - return 0; - } - - if (mutex->cpp_mutex.try_lock() == false) { - retval = SDL_MUTEX_TIMEDOUT; - } - return retval; + return ((mutex == NULL) || mutex->cpp_mutex.try_lock()) ? 0 : SDL_MUTEX_TIMEDOUT; } /* Unlock the mutex */ -extern "C" int -SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +extern "C" void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + mutex->cpp_mutex.unlock(); } - - mutex->cpp_mutex.unlock(); - return 0; } diff --git a/src/thread/stdcpp/SDL_sysrwlock.cpp b/src/thread/stdcpp/SDL_sysrwlock.cpp index 72673cab0601c..e85f879a9c4ca 100644 --- a/src/thread/stdcpp/SDL_sysrwlock.cpp +++ b/src/thread/stdcpp/SDL_sysrwlock.cpp @@ -30,10 +30,8 @@ struct SDL_RWLock SDL_threadID write_owner; }; -/* Create a rwlock */ extern "C" SDL_RWLock *SDL_CreateRWLock(void) { - /* Allocate and initialize the rwlock */ try { SDL_RWLock *rwlock = new SDL_RWLock; return rwlock; @@ -46,7 +44,6 @@ extern "C" SDL_RWLock *SDL_CreateRWLock(void) } } -/* Free the rwlock */ extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock) { if (rwlock != NULL) { @@ -54,77 +51,64 @@ extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock) } } -/* Lock the rwlock */ -extern "C" int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +extern "C" void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } - - try { - rwlock->cpp_mutex.lock_shared(); - return 0; - } catch (std::system_error &ex) { - return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what()); + if (rwlock) { + try { + rwlock->cpp_mutex.lock_shared(); + } catch (std::system_error &ex) { + SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails. + //return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what()); + } } } -/* Lock the rwlock for writing */ -extern "C" int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +extern "C" void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } - - try { - rwlock->cpp_mutex.lock(); - rwlock->write_owner = SDL_ThreadID(); - return 0; - } catch (std::system_error &ex) { - return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what()); + if (rwlock) { + try { + rwlock->cpp_mutex.lock(); + rwlock->write_owner = SDL_ThreadID(); + } catch (std::system_error &ex) { + SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails. + //return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what()); + } } } -/* TryLock the rwlock for reading */ -int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) +extern "C" int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) { int retval = 0; - - if (!rwlock) { - retval = SDL_InvalidParamError("rwlock"); - } else if (rwlock->cpp_mutex.try_lock_shared() == false) { - retval = SDL_RWLOCK_TIMEDOUT; + if (rwlock) { + if (rwlock->cpp_mutex.try_lock_shared() == false) { + retval = SDL_RWLOCK_TIMEDOUT; + } } return retval; } -/* TryLock the rwlock for writing */ -int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) +extern "C" int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) { int retval = 0; - - if (!rwlock) { - retval = SDL_InvalidParamError("rwlock"); - } else if (rwlock->cpp_mutex.try_lock() == false) { - retval = SDL_RWLOCK_TIMEDOUT; - } else { - rwlock->write_owner = SDL_ThreadID(); + if (rwlock) { + if (rwlock->cpp_mutex.try_lock() == false) { + retval = SDL_RWLOCK_TIMEDOUT; + } else { + rwlock->write_owner = SDL_ThreadID(); + } } return retval; } -/* Unlock the rwlock */ -extern "C" int -SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +extern "C" void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (!rwlock) { - return SDL_InvalidParamError("rwlock"); - } else if (rwlock->write_owner == SDL_ThreadID()) { - rwlock->write_owner = 0; - rwlock->cpp_mutex.unlock(); - } else { - rwlock->cpp_mutex.unlock_shared(); + if (rwlock) { + if (rwlock->write_owner == SDL_ThreadID()) { + rwlock->write_owner = 0; + rwlock->cpp_mutex.unlock(); + } else { + rwlock->cpp_mutex.unlock_shared(); + } } - return 0; } diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index 5e5ee47f9fa3a..1bc27780e8413 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -32,24 +32,20 @@ struct SDL_Mutex SceKernelLwMutexWork lock; }; -/* Create a mutex */ SDL_Mutex *SDL_CreateMutex(void) { - SDL_Mutex *mutex = NULL; - SceInt32 res = 0; - - /* Allocate mutex memory */ - mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); + SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); if (mutex != NULL) { - - res = sceKernelCreateLwMutex( - &mutex->lock, - "SDL mutex", - SCE_KERNEL_MUTEX_ATTR_RECURSIVE, - 0, - NULL); + const SceInt32 res = sceKernelCreateLwMutex( + &mutex->lock, + "SDL mutex", + SCE_KERNEL_MUTEX_ATTR_RECURSIVE, + 0, + NULL); if (res < 0) { + SDL_free(mutex); + mutex = NULL; SDL_SetError("Error trying to create mutex: %x", res); } } else { @@ -58,7 +54,6 @@ SDL_Mutex *SDL_CreateMutex(void) return mutex; } -/* Free the mutex */ void SDL_DestroyMutex(SDL_Mutex *mutex) { if (mutex != NULL) { @@ -67,28 +62,16 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -/* Lock the mutex */ -int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - - if (mutex == NULL) { - return 0; - } - - res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); - if (res != SCE_KERNEL_OK) { - return SDL_SetError("Error trying to lock mutex: %x", res); +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + const SceInt32 res = sceKernelLockLwMutex(&mutex->lock, 1, NULL); + SDL_assert(res == SCE_KERNEL_OK); // assume we're in a lot of trouble if this assert fails. } - - return 0; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED } -/* Try to lock the mutex */ int SDL_TryLockMutex(SDL_Mutex *mutex) { #ifdef SDL_THREADS_DISABLED @@ -102,40 +85,24 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) res = sceKernelTryLockLwMutex(&mutex->lock, 1); switch (res) { - case SCE_KERNEL_OK: - return 0; - break; - case SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN: - return SDL_MUTEX_TIMEDOUT; - break; - default: - return SDL_SetError("Error trying to lock mutex: %x", res); - break; + case SCE_KERNEL_OK: return 0; + case SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN: return SDL_MUTEX_TIMEDOUT; + default: break; } - return -1; -#endif /* SDL_THREADS_DISABLED */ + SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails. + return SDL_MUTEX_TIMEDOUT; +#endif // SDL_THREADS_DISABLED } -/* Unlock the mutex */ -int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { -#ifdef SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - - if (mutex == NULL) { - return 0; - } - - res = sceKernelUnlockLwMutex(&mutex->lock, 1); - if (res != 0) { - return SDL_SetError("Error trying to unlock mutex: %x", res); +#ifndef SDL_THREADS_DISABLED + if (mutex != NULL) { + const SceInt32 res = sceKernelUnlockLwMutex(&mutex->lock, 1); + SDL_assert(res == SCE_KERNEL_OK); // assume we're in a lot of trouble if this assert fails. } - - return 0; -#endif /* SDL_THREADS_DISABLED */ +#endif // SDL_THREADS_DISABLED } -#endif /* SDL_THREAD_VITA */ +#endif // SDL_THREAD_VITA diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index 16cc81f93b1ea..d70aa1be16e6c 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -76,12 +76,11 @@ static void SDL_DestroyMutex_srw(SDL_Mutex *mutex) SDL_free(mutex); } -static int SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; - DWORD this_thread; + const DWORD this_thread = GetCurrentThreadId(); - this_thread = GetCurrentThreadId(); if (mutex->owner == this_thread) { ++mutex->count; } else { @@ -94,16 +93,14 @@ static int SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* mutex->owner = this_thread; mutex->count = 1; } - return 0; } static int SDL_TryLockMutex_srw(SDL_Mutex *_mutex) { SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; - DWORD this_thread; + const DWORD this_thread = GetCurrentThreadId(); int retval = 0; - this_thread = GetCurrentThreadId(); if (mutex->owner == this_thread) { ++mutex->count; } else { @@ -118,7 +115,7 @@ static int SDL_TryLockMutex_srw(SDL_Mutex *_mutex) return retval; } -static int SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; @@ -128,10 +125,8 @@ static int SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS pReleaseSRWLockExclusive(&mutex->srw); } } else { - return SDL_SetError("mutex not owned by this thread"); + SDL_assert(!"mutex not owned by this thread"); // undefined behavior...! } - - return 0; } static const SDL_mutex_impl_t SDL_mutex_impl_srw = { @@ -147,16 +142,12 @@ static const SDL_mutex_impl_t SDL_mutex_impl_srw = { * Fallback Mutex implementation using Critical Sections (before Win 7) */ -/* Create a mutex */ static SDL_Mutex *SDL_CreateMutex_cs(void) { - SDL_mutex_cs *mutex; - - /* Allocate mutex memory */ - mutex = (SDL_mutex_cs *)SDL_malloc(sizeof(*mutex)); + SDL_mutex_cs *mutex = (SDL_mutex_cs *)SDL_malloc(sizeof(*mutex)); if (mutex != NULL) { - /* Initialize */ - /* On SMP systems, a non-zero spin count generally helps performance */ + // Initialize + // On SMP systems, a non-zero spin count generally helps performance #ifdef __WINRT__ InitializeCriticalSectionEx(&mutex->cs, 2000, 0); #else @@ -168,43 +159,29 @@ static SDL_Mutex *SDL_CreateMutex_cs(void) return (SDL_Mutex *)mutex; } -/* Free the mutex */ static void SDL_DestroyMutex_cs(SDL_Mutex *mutex_) { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; - DeleteCriticalSection(&mutex->cs); SDL_free(mutex); } -/* Lock the mutex */ -static int SDL_LockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_LockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; - EnterCriticalSection(&mutex->cs); - return 0; } -/* TryLock the mutex */ static int SDL_TryLockMutex_cs(SDL_Mutex *mutex_) { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; - int retval = 0; - - if (TryEnterCriticalSection(&mutex->cs) == 0) { - retval = SDL_MUTEX_TIMEDOUT; - } - return retval; + return (TryEnterCriticalSection(&mutex->cs) == 0) ? SDL_MUTEX_TIMEDOUT : 0; } -/* Unlock the mutex */ -static int SDL_UnlockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_UnlockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; - LeaveCriticalSection(&mutex->cs); - return 0; } static const SDL_mutex_impl_t SDL_mutex_impl_cs = { @@ -223,22 +200,22 @@ static const SDL_mutex_impl_t SDL_mutex_impl_cs = { SDL_Mutex *SDL_CreateMutex(void) { if (SDL_mutex_impl_active.Create == NULL) { - /* Default to fallback implementation */ + // Default to fallback implementation const SDL_mutex_impl_t *impl = &SDL_mutex_impl_cs; if (!SDL_GetHintBoolean(SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS, SDL_FALSE)) { #ifdef __WINRT__ - /* Link statically on this platform */ + // Link statically on this platform impl = &SDL_mutex_impl_srw; #else - /* Try faster implementation for Windows 7 and newer */ + // Try faster implementation for Windows 7 and newer HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll")); if (kernel32) { - /* Requires Vista: */ + // Requires Vista: pInitializeSRWLock = (pfnInitializeSRWLock)GetProcAddress(kernel32, "InitializeSRWLock"); pReleaseSRWLockExclusive = (pfnReleaseSRWLockExclusive)GetProcAddress(kernel32, "ReleaseSRWLockExclusive"); pAcquireSRWLockExclusive = (pfnAcquireSRWLockExclusive)GetProcAddress(kernel32, "AcquireSRWLockExclusive"); - /* Requires 7: */ + // Requires 7: pTryAcquireSRWLockExclusive = (pfnTryAcquireSRWLockExclusive)GetProcAddress(kernel32, "TryAcquireSRWLockExclusive"); if (pInitializeSRWLock && pReleaseSRWLockExclusive && pAcquireSRWLockExclusive && pTryAcquireSRWLockExclusive) { impl = &SDL_mutex_impl_srw; @@ -247,7 +224,7 @@ SDL_Mutex *SDL_CreateMutex(void) #endif } - /* Copy instead of using pointer to save one level of indirection */ + // Copy instead of using pointer to save one level of indirection SDL_copyp(&SDL_mutex_impl_active, impl); } return SDL_mutex_impl_active.Create(); @@ -260,31 +237,23 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) } } -int SDL_LockMutex(SDL_Mutex *mutex) +void SDL_LockMutex(SDL_Mutex *mutex) { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + SDL_mutex_impl_active.Lock(mutex); } - - return SDL_mutex_impl_active.Lock(mutex); } int SDL_TryLockMutex(SDL_Mutex *mutex) { - if (mutex == NULL) { - return 0; - } - - return SDL_mutex_impl_active.TryLock(mutex); + return mutex ? SDL_mutex_impl_active.TryLock(mutex) : 0; } -int SDL_UnlockMutex(SDL_Mutex *mutex) +void SDL_UnlockMutex(SDL_Mutex *mutex) { - if (mutex == NULL) { - return 0; + if (mutex != NULL) { + SDL_mutex_impl_active.Unlock(mutex); } - - return SDL_mutex_impl_active.Unlock(mutex); } -#endif /* SDL_THREAD_WINDOWS */ +#endif // SDL_THREAD_WINDOWS diff --git a/src/thread/windows/SDL_sysmutex_c.h b/src/thread/windows/SDL_sysmutex_c.h index 5a04e143e4313..d495ffe49bb3b 100644 --- a/src/thread/windows/SDL_sysmutex_c.h +++ b/src/thread/windows/SDL_sysmutex_c.h @@ -23,9 +23,9 @@ #include "../../core/windows/SDL_windows.h" typedef SDL_Mutex *(*pfnSDL_CreateMutex)(void); -typedef int (*pfnSDL_LockMutex)(SDL_Mutex *); +typedef void (*pfnSDL_LockMutex)(SDL_Mutex *); typedef int (*pfnSDL_TryLockMutex)(SDL_Mutex *); -typedef int (*pfnSDL_UnlockMutex)(SDL_Mutex *); +typedef void (*pfnSDL_UnlockMutex)(SDL_Mutex *); typedef void (*pfnSDL_DestroyMutex)(SDL_Mutex *); typedef enum diff --git a/src/thread/windows/SDL_sysrwlock_srw.c b/src/thread/windows/SDL_sysrwlock_srw.c index bec3cb07df9a6..c22eecae8e358 100644 --- a/src/thread/windows/SDL_sysrwlock_srw.c +++ b/src/thread/windows/SDL_sysrwlock_srw.c @@ -57,11 +57,11 @@ static pfnTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive = NULL; typedef SDL_RWLock *(*pfnSDL_CreateRWLock)(void); typedef void (*pfnSDL_DestroyRWLock)(SDL_RWLock *); -typedef int (*pfnSDL_LockRWLockForReading)(SDL_RWLock *); -typedef int (*pfnSDL_LockRWLockForWriting)(SDL_RWLock *); +typedef void (*pfnSDL_LockRWLockForReading)(SDL_RWLock *); +typedef void (*pfnSDL_LockRWLockForWriting)(SDL_RWLock *); typedef int (*pfnSDL_TryLockRWLockForReading)(SDL_RWLock *); typedef int (*pfnSDL_TryLockRWLockForWriting)(SDL_RWLock *); -typedef int (*pfnSDL_UnlockRWLock)(SDL_RWLock *); +typedef void (*pfnSDL_UnlockRWLock)(SDL_RWLock *); typedef struct SDL_rwlock_impl_t { @@ -104,35 +104,28 @@ static void SDL_DestroyRWLock_srw(SDL_RWLock *_rwlock) } } -static int SDL_LockRWLockForReading_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_LockRWLockForReading_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); + if (rwlock != NULL) { + pAcquireSRWLockShared(&rwlock->srw); } - pAcquireSRWLockShared(&rwlock->srw); - return 0; } -static int SDL_LockRWLockForWriting_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_LockRWLockForWriting_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); + if (rwlock != NULL) { + pAcquireSRWLockExclusive(&rwlock->srw); + rwlock->write_owner = SDL_ThreadID(); } - pAcquireSRWLockExclusive(&rwlock->srw); - rwlock->write_owner = SDL_ThreadID(); - return 0; } static int SDL_TryLockRWLockForReading_srw(SDL_RWLock *_rwlock) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; int retval = 0; - - if (rwlock == NULL) { - retval = SDL_InvalidParamError("rwlock"); - } else { + if (rwlock != NULL) { retval = pTryAcquireSRWLockShared(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT; } return retval; @@ -142,27 +135,23 @@ static int SDL_TryLockRWLockForWriting_srw(SDL_RWLock *_rwlock) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; int retval = 0; - - if (rwlock == NULL) { - retval = SDL_InvalidParamError("rwlock"); - } else { + if (rwlock != NULL) { retval = pTryAcquireSRWLockExclusive(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT; } return retval; } -static int SDL_UnlockRWLock_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +static void SDL_UnlockRWLock_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; - if (rwlock == NULL) { - return SDL_InvalidParamError("rwlock"); - } else if (rwlock->write_owner == SDL_ThreadID()) { - rwlock->write_owner = 0; - pReleaseSRWLockExclusive(&rwlock->srw); - } else { - pReleaseSRWLockShared(&rwlock->srw); + if (rwlock != NULL) { + if (rwlock->write_owner == SDL_ThreadID()) { + rwlock->write_owner = 0; + pReleaseSRWLockExclusive(&rwlock->srw); + } else { + pReleaseSRWLockShared(&rwlock->srw); + } } - return 0; } static const SDL_rwlock_impl_t SDL_rwlock_impl_srw = { @@ -234,47 +223,34 @@ void SDL_DestroyRWLock(SDL_RWLock *rwlock) } } -int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return 0; + if (rwlock != NULL) { + SDL_rwlock_impl_active.LockForReading(rwlock); } - - return SDL_rwlock_impl_active.LockForReading(rwlock); } -int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return 0; + if (rwlock != NULL) { + SDL_rwlock_impl_active.LockForWriting(rwlock); } - - return SDL_rwlock_impl_active.LockForWriting(rwlock); } int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) { - if (rwlock == NULL) { - return 0; - } - - return SDL_rwlock_impl_active.TryLockForReading(rwlock); + return rwlock ? SDL_rwlock_impl_active.TryLockForReading(rwlock) : 0; } int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) { - if (rwlock == NULL) { - return 0; - } - - return SDL_rwlock_impl_active.TryLockForWriting(rwlock); + return rwlock ? SDL_rwlock_impl_active.TryLockForWriting(rwlock) : 0; } -int SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes { - if (rwlock == NULL) { - return 0; + if (rwlock != NULL) { + SDL_rwlock_impl_active.Unlock(rwlock); } - - return SDL_rwlock_impl_active.Unlock(rwlock); } + diff --git a/test/testlock.c b/test/testlock.c index e0413d87d9aff..edf259ad4656c 100644 --- a/test/testlock.c +++ b/test/testlock.c @@ -80,17 +80,12 @@ Run(void *data) SDL_Log("Thread %lu: starting up", SDL_ThreadID()); while (!SDL_AtomicGet(&doterminate)) { SDL_Log("Thread %lu: ready to work\n", SDL_ThreadID()); - if (SDL_LockMutex(mutex) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError()); - exit(1); - } + SDL_LockMutex(mutex); SDL_Log("Thread %lu: start work!\n", SDL_ThreadID()); SDL_Delay(1 * worktime); SDL_Log("Thread %lu: work done!\n", SDL_ThreadID()); - if (SDL_UnlockMutex(mutex) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError()); - exit(1); - } + SDL_UnlockMutex(mutex); + /* If this sleep isn't done, then threads may starve */ SDL_Delay(10); } diff --git a/test/testrwlock.c b/test/testrwlock.c index cada79e5592c4..7952a2ef74aa0 100644 --- a/test/testrwlock.c +++ b/test/testrwlock.c @@ -33,22 +33,21 @@ static void DoWork(const int workticks) /* "Work" */ const SDL_threadID tid = SDL_ThreadID(); const SDL_bool is_reader = tid != mainthread; const char *typestr = is_reader ? "Reader" : "Writer"; - int rc; SDL_Log("%s Thread %lu: ready to work\n", typestr, (unsigned long) tid); - rc = is_reader ? SDL_LockRWLockForReading(rwlock) : SDL_LockRWLockForWriting(rwlock); - if (rc < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s Thread %lu: Couldn't lock rwlock: %s", typestr, (unsigned long) tid, SDL_GetError()); + if (is_reader) { + SDL_LockRWLockForReading(rwlock); } else { - SDL_Log("%s Thread %lu: start work!\n", typestr, (unsigned long) tid); - SDL_Delay(workticks); - SDL_Log("%s Thread %lu: work done!\n", typestr, (unsigned long) tid); - if (SDL_UnlockRWLock(rwlock) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s Thread %lu: Couldn't unlock rwlock: %s", typestr, (unsigned long) tid, SDL_GetError()); - } - /* If this sleep isn't done, then threads may starve */ - SDL_Delay(10); + SDL_LockRWLockForWriting(rwlock); } + + SDL_Log("%s Thread %lu: start work!\n", typestr, (unsigned long) tid); + SDL_Delay(workticks); + SDL_Log("%s Thread %lu: work done!\n", typestr, (unsigned long) tid); + SDL_UnlockRWLock(rwlock); + + /* If this sleep isn't done, then threads may starve */ + SDL_Delay(10); } static int SDLCALL From 82f48be3ef24f281f3aaa9a64a9665251a328f75 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 26 Oct 2023 12:58:14 +0000 Subject: [PATCH 158/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_mutex.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 7dd150259f67c..a87fce87707dc 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -378,10 +378,10 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_AC * Trying to lock for read-only access can succeed if other threads are * holding read-only locks, as this won't prevent access. * - * This function does not fail; if rwlock is NULL, it will return 0 immediately - * having locked nothing. If rwlock is valid, this function will always - * either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock - * nothing. + * This function does not fail; if rwlock is NULL, it will return 0 + * immediately having locked nothing. If rwlock is valid, this function will + * always either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT + * and lock nothing. * * \param rwlock the rwlock to try to lock * \returns 0 or `SDL_RWLOCK_TIMEDOUT` @@ -412,10 +412,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_ * read-only lock. Doing so results in undefined behavior. Unlock the * read-only lock before requesting a write lock. * - * This function does not fail; if rwlock is NULL, it will return 0 immediately - * having locked nothing. If rwlock is valid, this function will always - * either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock - * nothing. + * This function does not fail; if rwlock is NULL, it will return 0 + * immediately having locked nothing. If rwlock is valid, this function will + * always either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT + * and lock nothing. * * \param rwlock the rwlock to try to lock * \returns 0 or `SDL_RWLOCK_TIMEDOUT` From e6116d399a144b4f0f6c8e1ad7bef206718ce9b3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 26 Oct 2023 14:21:53 -0400 Subject: [PATCH 159/725] mutex: Removed SDL_MUTEX_MAXWAIT. Fixes #8436. --- docs/README-migration.md | 2 ++ include/SDL3/SDL_mutex.h | 11 +++-------- src/thread/SDL_thread.c | 4 ++-- src/thread/n3ds/SDL_syssem.c | 2 +- src/thread/ngage/SDL_syssem.cpp | 2 +- src/thread/ps2/SDL_syssem.c | 2 +- src/thread/psp/SDL_syssem.c | 2 +- src/thread/vita/SDL_syssem.c | 2 +- src/timer/SDL_timer.c | 2 +- 9 files changed, 13 insertions(+), 16 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index aa1b044f1209a..85949df581554 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -707,6 +707,8 @@ The following functions have been renamed: ## SDL_mutex.h +SDL_MUTEX_MAXWAIT has been removed; it suggested there was a maximum timeout one could outlive, instead of an infinite wait. Instead, pass a -1 to functions that accepted this symbol. + SDL_LockMutex and SDL_UnlockMutex now return void; if the mutex is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the mutex is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior. The following functions have been renamed: diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index a87fce87707dc..559fda79e6f64 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -121,11 +121,6 @@ extern "C" { */ #define SDL_MUTEX_TIMEDOUT 1 -/** - * This is the timeout value which corresponds to never time out. - */ -#define SDL_MUTEX_MAXWAIT -1 - /** * \name Mutex functions @@ -535,7 +530,7 @@ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); * semaphore value. * * This function is the equivalent of calling SDL_WaitSemaphoreTimeout() with - * a time length of `SDL_MUTEX_MAXWAIT`. + * a time length of -1. * * \param sem the semaphore wait on * \returns 0 on success or a negative error code on failure; call @@ -722,7 +717,7 @@ extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); * behavior. * * This function is the equivalent of calling SDL_WaitConditionTimeout() with - * a time length of `SDL_MUTEX_MAXWAIT`. + * a time length of -1. * * \param cond the condition variable to wait on * \param mutex the mutex used to coordinate thread access @@ -755,7 +750,7 @@ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mu * \param cond the condition variable to wait on * \param mutex the mutex used to coordinate thread access * \param timeoutMS the maximum time to wait, in milliseconds, or - * `SDL_MUTEX_MAXWAIT` to wait indefinitely + * -1 to wait indefinitely * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if * the condition is not signaled in the allotted time, or a negative * error code on failure; call SDL_GetError() for more information. diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index e062a96f918cb..7328316e63134 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -472,7 +472,7 @@ void SDL_DetachThread(SDL_Thread *thread) int SDL_WaitSemaphore(SDL_Semaphore *sem) { - return SDL_WaitSemaphoreTimeoutNS(sem, SDL_MUTEX_MAXWAIT); + return SDL_WaitSemaphoreTimeoutNS(sem, -1); } int SDL_TryWaitSemaphore(SDL_Semaphore *sem) @@ -494,7 +494,7 @@ int SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 timeoutMS) int SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mutex) { - return SDL_WaitConditionTimeoutNS(cond, mutex, SDL_MUTEX_MAXWAIT); + return SDL_WaitConditionTimeoutNS(cond, mutex, -1); } int SDL_WaitConditionTimeout(SDL_Condition *cond, SDL_Mutex *mutex, Sint32 timeoutMS) diff --git a/src/thread/n3ds/SDL_syssem.c b/src/thread/n3ds/SDL_syssem.c index 1c197f553ad63..261609b27846a 100644 --- a/src/thread/n3ds/SDL_syssem.c +++ b/src/thread/n3ds/SDL_syssem.c @@ -67,7 +67,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) return SDL_InvalidParamError("sem"); } - if (timeoutNS == SDL_MUTEX_MAXWAIT) { + if (timeoutNS == -1) { // -1 == wait indefinitely. LightSemaphore_Acquire(&sem->semaphore, 1); return 0; } diff --git a/src/thread/ngage/SDL_syssem.cpp b/src/thread/ngage/SDL_syssem.cpp index 8b15be46e2805..e7306e8a16a1b 100644 --- a/src/thread/ngage/SDL_syssem.cpp +++ b/src/thread/ngage/SDL_syssem.cpp @@ -114,7 +114,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) return SDL_MUTEX_TIMEOUT; } - if (timeoutNS == SDL_MUTEX_MAXWAIT) { + if (timeoutNS == -1) { // -1 == wait indefinitely. WaitAll(sem); return 0; } diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index 3878d09ed4642..587bf494172b2 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -96,7 +96,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) return 0; } - if (timeoutNS != SDL_MUTEX_MAXWAIT) { + if (timeoutNS != -1) { // -1 == wait indefinitely. SetTimerAlarm(&alarm, MSec2TimerBusClock(SDL_NS_TO_MS(timeoutNS)), &usercb, (void *)GetThreadId()); } diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index d65c9f1ace4dd..f54e53ccfe34f 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -70,7 +70,7 @@ void SDL_DestroySemaphore(SDL_Semaphore *sem) } /* TODO: This routine is a bit overloaded. - * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass + * If the timeout is 0 then just poll the semaphore; if it's -1, pass * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * is specified, convert it to microseconds. */ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) diff --git a/src/thread/vita/SDL_syssem.c b/src/thread/vita/SDL_syssem.c index 784f88ed48ebc..105b18d247ba3 100644 --- a/src/thread/vita/SDL_syssem.c +++ b/src/thread/vita/SDL_syssem.c @@ -71,7 +71,7 @@ void SDL_DestroySemaphore(SDL_Semaphore *sem) } /* TODO: This routine is a bit overloaded. - * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass + * If the timeout is 0 then just poll the semaphore; if it's -1, pass * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * is specified, convert it to microseconds. */ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index 0052ff60f537f..67296bbb8440b 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -141,7 +141,7 @@ static int SDLCALL SDL_TimerThread(void *_data) } /* Initial delay if there are no timers */ - delay = (Uint64)SDL_MUTEX_MAXWAIT; + delay = (Uint64)-1; tick = SDL_GetTicksNS(); From 2e9eb1073d1ff3d942330aac42f25e5f998f0df8 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 26 Oct 2023 18:23:13 +0000 Subject: [PATCH 160/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_mutex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 559fda79e6f64..6f13eb05d65a5 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -749,8 +749,8 @@ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mu * * \param cond the condition variable to wait on * \param mutex the mutex used to coordinate thread access - * \param timeoutMS the maximum time to wait, in milliseconds, or - * -1 to wait indefinitely + * \param timeoutMS the maximum time to wait, in milliseconds, or -1 to wait + * indefinitely * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if * the condition is not signaled in the allotted time, or a negative * error code on failure; call SDL_GetError() for more information. From 8b6da3c7017935932357a0decee84dc6167ace17 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 26 Oct 2023 17:07:40 -0700 Subject: [PATCH 161/725] Fixed making the EGL context current when resuming on Android Make sure that we don't have the context cached as current on the current thread. --- src/video/android/SDL_androidevents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index 31704c68bfb28..8d3679106ecbf 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -45,6 +45,7 @@ static void android_egl_context_restore(SDL_Window *window) if (window) { SDL_Event event; SDL_WindowData *data = window->driverdata; + SDL_GL_MakeCurrent(window, NULL); if (SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context) < 0) { /* The context is no longer valid, create a new one */ data->egl_context = (EGLContext)SDL_GL_CreateContext(window); From c45b5121ced97ba6bd6af54acd241339fd69c7ed Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 26 Oct 2023 22:57:34 -0400 Subject: [PATCH 162/725] audio: Fixed potential race condition. We need to check if the device is ready to close before releasing the lock, in case other things are messing with the list of logical devices. --- src/audio/SDL_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 47d4878436e7b..456ce44fbbb6c 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1353,9 +1353,12 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); + const SDL_bool close_physical = (device->logical_devices == NULL); // no more logical devices? Close the physical device, too. + // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. - if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. + + if (close_physical) { ClosePhysicalAudioDevice(device); } From 9bec57309c2b624c7010ebbcea245528296fac44 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 26 Oct 2023 22:59:02 -0400 Subject: [PATCH 163/725] wasapi: Proxy default device change handling to management thread. This does a ton of work that can deadlock, because several crucial WASAPI things that we want to do in response to this will block until the notification callback has returned, so we can't call them from the handler directly, or we'll be waiting until the thing that called us returns. --- src/audio/directsound/SDL_directsound.c | 2 +- src/audio/wasapi/SDL_wasapi_win32.c | 13 ++++++++++++- src/core/windows/SDL_immdevice.c | 12 ++++++++++-- src/core/windows/SDL_immdevice.h | 4 +++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index 432e740f80c95..74fc522be491a 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -647,7 +647,7 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl) } #ifdef HAVE_MMDEVICEAPI_H - SupportsIMMDevice = !(SDL_IMMDevice_Init() < 0); + SupportsIMMDevice = !(SDL_IMMDevice_Init(NULL) < 0); #endif impl->DetectDevices = DSOUND_DetectDevices; diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 19dfbd4d9bbc5..b69515451859f 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -48,11 +48,22 @@ static SDL_bool immdevice_initialized = SDL_FALSE; // Some GUIDs we need to know without linking to libraries that aren't available before Vista. static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } }; +static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) +{ + SDL_DefaultAudioDeviceChanged((SDL_AudioDevice *) userdata); + return 0; +} + +static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) +{ + WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, new_default_device, NULL); // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. +} + int WASAPI_PlatformInit(void) { if (FAILED(WIN_CoInitialize())) { return SDL_SetError("CoInitialize() failed"); - } else if (SDL_IMMDevice_Init() < 0) { + } else if (SDL_IMMDevice_Init(WASAPI_DefaultAudioDeviceChanged) < 0) { return -1; // Error string is set by SDL_IMMDevice_Init } diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 780eff40ddd99..583c71ff2ef48 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -37,6 +37,7 @@ static const ERole SDL_IMMDevice_role = eConsole; /* !!! FIXME: should this be e /* This is global to the WASAPI target, to handle hotplug and default device lookup. */ static IMMDeviceEnumerator *enumerator = NULL; +static SDL_IMMDevice_DefaultAudioDeviceChanged devchangecallback = NULL; /* PropVariantInit() is an inline function/macro in PropIdl.h that calls the C runtime's memset() directly. Use ours instead, to avoid dependency. */ #ifdef PropVariantInit @@ -204,7 +205,9 @@ static ULONG STDMETHODCALLTYPE SDLMMNotificationClient_Release(IMMNotificationCl static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDefaultDeviceChanged(IMMNotificationClient *iclient, EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) { if (role == SDL_IMMDevice_role) { - SDL_DefaultAudioDeviceChanged(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); + if (devchangecallback) { + devchangecallback(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); + } } return S_OK; } @@ -273,7 +276,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = { static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } }; -int SDL_IMMDevice_Init(void) +int SDL_IMMDevice_Init(SDL_IMMDevice_DefaultAudioDeviceChanged devchanged) { HRESULT ret; @@ -291,6 +294,9 @@ int SDL_IMMDevice_Init(void) WIN_CoUninitialize(); return WIN_SetErrorFromHRESULT("IMMDevice CoCreateInstance(MMDeviceEnumerator)", ret); } + + devchangecallback = devchanged ? devchanged : SDL_DefaultAudioDeviceChanged; + return 0; } @@ -302,6 +308,8 @@ void SDL_IMMDevice_Quit(void) enumerator = NULL; } + devchangecallback = NULL; + WIN_CoUninitialize(); } diff --git a/src/core/windows/SDL_immdevice.h b/src/core/windows/SDL_immdevice.h index a190a7cf84289..0b64d2f5566d4 100644 --- a/src/core/windows/SDL_immdevice.h +++ b/src/core/windows/SDL_immdevice.h @@ -28,7 +28,9 @@ typedef struct SDL_AudioDevice SDL_AudioDevice; // this is defined in src/audio/SDL_sysaudio.h -int SDL_IMMDevice_Init(void); +typedef void (*SDL_IMMDevice_DefaultAudioDeviceChanged)(SDL_AudioDevice *new_default_device); + +int SDL_IMMDevice_Init(SDL_IMMDevice_DefaultAudioDeviceChanged devchanged); void SDL_IMMDevice_Quit(void); int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture); void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); From 85923049a6a6b500848dd3b258b267aab74c05c6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 26 Oct 2023 23:09:11 -0400 Subject: [PATCH 164/725] wasapi: Patched to compile. --- src/audio/wasapi/SDL_wasapi_win32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index b69515451859f..3021a6fb042c6 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -56,7 +56,8 @@ static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) { - WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, new_default_device, NULL); // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. + // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. + WASAPI_ProxyToManagementThread(mgmtthrtask_DefaultAudioDeviceChanged, new_default_device, NULL); } int WASAPI_PlatformInit(void) From ce3be02b48b60f4db6638c384792004f14ae7980 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 27 Oct 2023 01:27:22 -0400 Subject: [PATCH 165/725] wasapi: If device is marked as a zombie, don't try to resuscitate it. --- src/audio/SDL_audio.c | 1 + src/audio/wasapi/SDL_wasapi.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 456ce44fbbb6c..410b5c368c5e5 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -514,6 +514,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. // on non-default devices, dump everything. + // (by "dump" we mean send a REMOVED event; the zombie will keep consuming audio data for these logical devices until explicitly closed.) for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { if (!is_default_device || !logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index f68fb0f694e61..ffbeeec343c42 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -397,6 +397,8 @@ static SDL_bool RecoverWasapiIfLost(SDL_AudioDevice *device) WASAPI_DisconnectDevice(device); SDL_assert(SDL_AtomicGet(&device->shutdown)); // so we don't come back through here. return SDL_FALSE; // already failed. + } else if (SDL_AtomicGet(&device->zombie)) { + return SDL_FALSE; // we're already dead, so just leave and let the Zombie implementations take over. } else if (!device->hidden->client) { return SDL_TRUE; // still waiting for activation. } From 468c386686010c127ba2f06ef251682a294614e8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 27 Oct 2023 01:28:51 -0400 Subject: [PATCH 166/725] wasapi: Handle disconnect notifications from the management thread, too. These are also pretty heavyweight, don't do them from the notification thread, which can deadlock everything. --- src/audio/wasapi/SDL_wasapi_win32.c | 15 ++++++++++++++- src/core/windows/SDL_immdevice.c | 25 +++++++++++++++++-------- src/core/windows/SDL_immdevice.h | 8 ++++++-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 3021a6fb042c6..db8397c416675 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -48,6 +48,18 @@ static SDL_bool immdevice_initialized = SDL_FALSE; // Some GUIDs we need to know without linking to libraries that aren't available before Vista. static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } }; +static int mgmtthrtask_AudioDeviceDisconnected(void *userdata) +{ + SDL_AudioDeviceDisconnected((SDL_AudioDevice *)userdata); + return 0; +} + +static void WASAPI_AudioDeviceDisconnected(SDL_AudioDevice *device) +{ + // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. + WASAPI_ProxyToManagementThread(mgmtthrtask_AudioDeviceDisconnected, device, NULL); +} + static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) { SDL_DefaultAudioDeviceChanged((SDL_AudioDevice *) userdata); @@ -62,9 +74,10 @@ static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device int WASAPI_PlatformInit(void) { + const SDL_IMMDevice_callbacks callbacks = { WASAPI_AudioDeviceDisconnected, WASAPI_DefaultAudioDeviceChanged }; if (FAILED(WIN_CoInitialize())) { return SDL_SetError("CoInitialize() failed"); - } else if (SDL_IMMDevice_Init(WASAPI_DefaultAudioDeviceChanged) < 0) { + } else if (SDL_IMMDevice_Init(&callbacks) < 0) { return -1; // Error string is set by SDL_IMMDevice_Init } diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 583c71ff2ef48..3ed2d5f2dc888 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -37,7 +37,7 @@ static const ERole SDL_IMMDevice_role = eConsole; /* !!! FIXME: should this be e /* This is global to the WASAPI target, to handle hotplug and default device lookup. */ static IMMDeviceEnumerator *enumerator = NULL; -static SDL_IMMDevice_DefaultAudioDeviceChanged devchangecallback = NULL; +static SDL_IMMDevice_callbacks immcallbacks; /* PropVariantInit() is an inline function/macro in PropIdl.h that calls the C runtime's memset() directly. Use ours instead, to avoid dependency. */ #ifdef PropVariantInit @@ -205,9 +205,7 @@ static ULONG STDMETHODCALLTYPE SDLMMNotificationClient_Release(IMMNotificationCl static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDefaultDeviceChanged(IMMNotificationClient *iclient, EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) { if (role == SDL_IMMDevice_role) { - if (devchangecallback) { - devchangecallback(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); - } + immcallbacks.default_audio_device_changed(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); } return S_OK; } @@ -247,7 +245,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM SDL_free(utf8dev); } } else { - SDL_AudioDeviceDisconnected(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); + immcallbacks.audio_device_disconnected(SDL_IMMDevice_FindByDevID(pwstrDeviceId)); } } IMMEndpoint_Release(endpoint); @@ -276,7 +274,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = { static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } }; -int SDL_IMMDevice_Init(SDL_IMMDevice_DefaultAudioDeviceChanged devchanged) +int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks) { HRESULT ret; @@ -295,7 +293,18 @@ int SDL_IMMDevice_Init(SDL_IMMDevice_DefaultAudioDeviceChanged devchanged) return WIN_SetErrorFromHRESULT("IMMDevice CoCreateInstance(MMDeviceEnumerator)", ret); } - devchangecallback = devchanged ? devchanged : SDL_DefaultAudioDeviceChanged; + if (callbacks) { + SDL_copyp(&immcallbacks, callbacks); + } else { + SDL_zero(immcallbacks); + } + + if (!immcallbacks.audio_device_disconnected) { + immcallbacks.audio_device_disconnected = SDL_AudioDeviceDisconnected; + } + if (!immcallbacks.default_audio_device_changed) { + immcallbacks.default_audio_device_changed = SDL_DefaultAudioDeviceChanged; + } return 0; } @@ -308,7 +317,7 @@ void SDL_IMMDevice_Quit(void) enumerator = NULL; } - devchangecallback = NULL; + SDL_zero(immcallbacks); WIN_CoUninitialize(); } diff --git a/src/core/windows/SDL_immdevice.h b/src/core/windows/SDL_immdevice.h index 0b64d2f5566d4..5ed0c5ddc8b64 100644 --- a/src/core/windows/SDL_immdevice.h +++ b/src/core/windows/SDL_immdevice.h @@ -28,9 +28,13 @@ typedef struct SDL_AudioDevice SDL_AudioDevice; // this is defined in src/audio/SDL_sysaudio.h -typedef void (*SDL_IMMDevice_DefaultAudioDeviceChanged)(SDL_AudioDevice *new_default_device); +typedef struct SDL_IMMDevice_callbacks +{ + void (*audio_device_disconnected)(SDL_AudioDevice *device); + void (*default_audio_device_changed)(SDL_AudioDevice *new_default_device); +} SDL_IMMDevice_callbacks; -int SDL_IMMDevice_Init(SDL_IMMDevice_DefaultAudioDeviceChanged devchanged); +int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks); void SDL_IMMDevice_Quit(void); int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture); void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); From 5fa7b291d426f36e8f05e70435b838c402a92433 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 27 Oct 2023 01:30:13 -0400 Subject: [PATCH 167/725] wasapi: Fixed memory leak if new audio devices fail to add. --- src/core/windows/SDL_immdevice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 3ed2d5f2dc888..12ce1c5d2e1d5 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -155,6 +155,10 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt); device = SDL_AddAudioDevice(iscapture, devname, &spec, handle); + if (!device) { + SDL_free(handle->immdevice_id); + SDL_free(handle); + } } return device; From f63e9a8a3fecc34f1e2110974f3171b91b56e761 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 27 Oct 2023 01:30:27 -0400 Subject: [PATCH 168/725] wasapi: Handle disconnected devices that get reconnected. The device ID strings don't change between connects, so we need to move the old device object out of the way if it still exists as a zombie, and let the reconnected device get itself a fresh object. --- src/core/windows/SDL_immdevice.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 12ce1c5d2e1d5..629f4a181c02e 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -133,6 +133,18 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * // see if we already have this one first. SDL_AudioDevice *device = SDL_IMMDevice_FindByDevID(devid); + if (device) { + if (SDL_AtomicGet(&device->zombie)) { + // whoa, it came back! This can happen if you unplug and replug USB headphones while we're still keeping the SDL object alive. + // Kill this device's IMMDevice id; the device will go away when the app closes it, or maybe a new default device is chosen + // (possibly this reconnected device), so we just want to make sure IMMDevice doesn't try to find the old device by the existing ID string. + SDL_IMMDevice_HandleData *handle = (SDL_IMMDevice_HandleData *) device->handle; + SDL_free(handle->immdevice_id); + handle->immdevice_id = NULL; + device = NULL; // add a new device, below. + } + } + if (!device) { // handle is freed by SDL_IMMDevice_FreeDeviceHandle! SDL_IMMDevice_HandleData *handle = SDL_malloc(sizeof(SDL_IMMDevice_HandleData)); From 343da852a637a2a63df817a51a4b48105267ed44 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 27 Oct 2023 10:10:09 -0700 Subject: [PATCH 169/725] Don't try to use the Wayland messagebox if we're not in Wayland Also cleaned up some potential file handle leaks when querying the zenity version --- src/video/wayland/SDL_waylandmessagebox.c | 34 +++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/video/wayland/SDL_waylandmessagebox.c b/src/video/wayland/SDL_waylandmessagebox.c index a7d96cbbc27ae..790be39e87fd7 100644 --- a/src/video/wayland/SDL_waylandmessagebox.c +++ b/src/video/wayland/SDL_waylandmessagebox.c @@ -36,7 +36,8 @@ #define MAX_BUTTONS 8 /* Maximum number of buttons supported */ -static int run_zenity(const char **args, int fd_pipe[2]) { +static int run_zenity(const char **args, int fd_pipe[2]) +{ int status; pid_t pid1; @@ -47,6 +48,7 @@ static int run_zenity(const char **args, int fd_pipe[2]) { if (dup2(fd_pipe[1], STDOUT_FILENO) == -1) { _exit(128); } + close(fd_pipe[1]); /* const casting argv is fine: * https://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html -> rational @@ -56,7 +58,6 @@ static int run_zenity(const char **args, int fd_pipe[2]) { } else if (pid1 < 0) { /* fork() failed */ return SDL_SetError("fork() failed: %s", strerror(errno)); } else { /* parent process */ - close(fd_pipe[1]); /* no writing to the pipe */ if (waitpid(pid1, &status, 0) != pid1) { return SDL_SetError("Waiting on zenity failed: %s", strerror(errno)); } @@ -73,7 +74,8 @@ static int run_zenity(const char **args, int fd_pipe[2]) { } } -static int get_zenity_version(int *major, int *minor) { +static int get_zenity_version(int *major, int *minor) +{ int fd_pipe[2]; /* fd_pipe[0]: read end of pipe, fd_pipe[1]: write end of pipe */ const char *argv[] = { "zenity", "--version", NULL }; @@ -87,6 +89,7 @@ static int get_zenity_version(int *major, int *minor) { char *version_ptr = NULL, *end_ptr = NULL; int tmp; + close(fd_pipe[1]); outputfp = fdopen(fd_pipe[0], "r"); if (outputfp == NULL) { close(fd_pipe[0]); @@ -109,12 +112,16 @@ static int get_zenity_version(int *major, int *minor) { } *major = tmp; - version_ptr = end_ptr + 1; /* skip the dot */ - tmp = (int) SDL_strtol(version_ptr, &end_ptr, 10); - if (tmp == 0 && end_ptr == version_ptr) { - return SDL_SetError("failed to get zenity minor version number"); + if (*end_ptr == '.') { + version_ptr = end_ptr + 1; /* skip the dot */ + tmp = (int) SDL_strtol(version_ptr, &end_ptr, 10); + if (tmp == 0 && end_ptr == version_ptr) { + return SDL_SetError("failed to get zenity minor version number"); + } + *minor = tmp; + } else { + *minor = 0; } - *minor = tmp; return 0; /* success */ } @@ -124,7 +131,8 @@ static int get_zenity_version(int *major, int *minor) { return -1; /* run_zenity should've called SDL_SetError() */ } -int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { +int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ int fd_pipe[2]; /* fd_pipe[0]: read end of pipe, fd_pipe[1]: write end of pipe */ int zenity_major = 0, zenity_minor = 0, output_len = 0; int argc = 5, i; @@ -132,6 +140,14 @@ int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *button "zenity", "--question", "--switch", "--no-wrap", "--no-markup" }; + /* Are we trying to connect to or are currently in a Wayland session? */ + if (!SDL_getenv("WAYLAND_DISPLAY")) { + const char *session = SDL_getenv("XDG_SESSION_TYPE"); + if (session && SDL_strcasecmp(session, "wayland") != 0) { + return SDL_SetError("Not on a wayland display"); + } + } + if (messageboxdata->numbuttons > MAX_BUTTONS) { return SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS); } From 552bee47cb23267b90dee422de0b6fdf20fb8453 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 27 Oct 2023 10:11:00 -0700 Subject: [PATCH 170/725] Clear any previous errors if we successfully show a message box --- src/video/SDL_video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index d68c887004766..eec3e0dd87978 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -4945,6 +4945,8 @@ int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) if (!*error) { SDL_SetError("No message system available"); } + } else { + SDL_ClearError(); } (void)SDL_AtomicDecRef(&SDL_messagebox_count); From 6127ac08714f423b523c0bf6c2210a782b2f571a Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 2 Oct 2023 11:00:06 +0200 Subject: [PATCH 171/725] Use SDL_DISABLE_ALLOCA instead of HAVE_ALLOCA in SDL_stdinc.h --- CMakeLists.txt | 27 ++++++- VisualC-GDK/SDL/SDL.vcxproj | 5 ++ VisualC-GDK/SDL/SDL.vcxproj.filters | 3 + VisualC-WinRT/SDL-UWP.vcxproj | 5 ++ VisualC-WinRT/SDL-UWP.vcxproj.filters | 3 + VisualC/SDL/SDL.vcxproj | 5 ++ VisualC/SDL/SDL.vcxproj.filters | 3 + cmake/sdlcompilers.cmake | 26 +++---- include/SDL3/SDL_stdinc.h | 40 ++++++----- include/build_config/SDL_build_config.h.cmake | 3 +- .../build_config/SDL_build_config_android.h | 1 - .../SDL_build_config_emscripten.h | 1 - include/build_config/SDL_build_config_ios.h | 1 - include/build_config/SDL_build_config_macos.h | 1 - .../build_config/SDL_build_config_windows.h | 1 - .../build_config/SDL_build_config_wingdk.h | 1 - include/build_config/SDL_build_config_winrt.h | 1 - include/build_config/SDL_build_config_xbox.h | 1 - src/stdlib/SDL_mslibc.c | 72 +++++++++++++++++++ src/stdlib/SDL_mslibc_x64.asm | 29 ++++++++ 20 files changed, 185 insertions(+), 44 deletions(-) create mode 100644 src/stdlib/SDL_mslibc_x64.asm diff --git a/CMakeLists.txt b/CMakeLists.txt index 0baea19031b73..6edba99fb69a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -486,6 +486,18 @@ sdl_glob_sources( "${SDL3_SOURCE_DIR}/src/video/*.c" "${SDL3_SOURCE_DIR}/src/video/yuv2rgb/*.c" ) +if(MSVC AND TARGET SDL3-shared) + if(SDL_CPU_X64) + enable_language(ASM_MASM) + set(asm_src "${SDL3_SOURCE_DIR}/src/stdlib/SDL_mslibc_x64.asm") + target_compile_options(SDL3-shared PRIVATE "$<$:/nologo>") + set_property(SOURCE "${asm_src}" PROPERTY LANGUAGE "ASM_MASM") + target_sources(SDL3-shared PRIVATE "${asm_src}") + elseif(SDL_CPU_ARM32 OR DL_CPU_ARM64) + # FIXME: ARM assembler (armasm.exe/armasm64.exe) is NOT ASM_MASM, and does currently not work with CMake + # (https://gitlab.kitware.com/cmake/cmake/-/issues/18912) + endif() +endif() if(USE_INTELCC) # warning #39: division by zero @@ -985,12 +997,21 @@ if(NOT HAVE_ARMNEON) set(SDL_DISABLE_NEON 1) endif() +set(SDL_DISABLE_ALLOCA 0) +check_include_file("alloca.h" "HAVE_ALLOCA_H") +if(MSVC) + check_include_file("malloc.h" "HAVE_MALLOC") + check_symbol_exists("_alloca" "malloc.h" _ALLOCA_IN_MALLOC_H) + if(NOT HAVE_ALLOCA_H AND NOT _ALLOCA_IN_MALLOC_H) + set(SDL_DISABLE_ALLOCA 1) + endif() +endif() + # TODO: Can't deactivate on FreeBSD? w/o LIBC, SDL_stdinc.h can't define anything. if(SDL_LIBC) set(available_headers) set(HAVE_LIBC TRUE) set(headers_to_check - alloca.h ctype.h float.h iconv.h @@ -1022,7 +1043,7 @@ if(SDL_LIBC) endforeach() set(symbols_to_check - abs acos acosf alloca asin asinf atan atan2 atan2f atanf atof atoi + abs acos acosf asin asinf atan atan2 atan2f atanf atof atoi bcopy bsearch calloc ceil ceilf copysign copysignf cos cosf _Exit exp expf @@ -1717,7 +1738,7 @@ elseif(WINDOWS) if(TARGET SDL3-shared AND MSVC AND NOT SDL_LIBC) # Prevent codegen that would use the VC runtime libraries. - target_compile_options(SDL3-shared PRIVATE "/GS-" "/Gs1048576") + target_compile_options(SDL3-shared PRIVATE $<$:/GS-> $<$:/Gs1048576>) if(SDL_CPU_X86) target_compile_options(SDL3-shared PRIVATE "/arch:SSE") endif() diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index bb003d0f08311..70b625b37f42a 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -59,6 +59,7 @@ + @@ -729,6 +730,9 @@ + + NotUsing + @@ -793,5 +797,6 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index bbdc75985c4d5..a530ef1bfa18d 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -1388,6 +1388,9 @@ stdlib + + stdlib + core\gdk diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 372a283396838..21c5e7ebba226 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -413,6 +413,9 @@ + + NotUsing + @@ -668,6 +671,7 @@ + @@ -867,5 +871,6 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 92e6f4a8d4e7b..430babceb1239 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -875,6 +875,9 @@ Source Files + + stdlib + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index a40d5acb57176..84e774521acc5 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -43,6 +43,7 @@ + @@ -609,6 +610,9 @@ + + NotUsing + @@ -669,5 +673,6 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index f72a3a0fca882..23fa7b2e3ffd4 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1375,6 +1375,9 @@ stdlib + + stdlib + diff --git a/cmake/sdlcompilers.cmake b/cmake/sdlcompilers.cmake index 40bb3b6dcd573..5fd3081b45680 100644 --- a/cmake/sdlcompilers.cmake +++ b/cmake/sdlcompilers.cmake @@ -49,12 +49,12 @@ function(SDL_AddCommonCompilerFlags TARGET) check_c_compiler_flag(-Wundef HAVE_GCC_WUNDEF) if(HAVE_GCC_WUNDEF) - target_compile_options(${TARGET} PRIVATE "-Wundef") + target_compile_options(${TARGET} PRIVATE "$<$:-Wundef>") endif() check_c_compiler_flag(-fno-strict-aliasing HAVE_GCC_NO_STRICT_ALIASING) if(HAVE_GCC_NO_STRICT_ALIASING) - target_compile_options(${TARGET} PRIVATE "-fno-strict-aliasing") + target_compile_options(${TARGET} PRIVATE "$<$:-fno-strict-aliasing>") endif() check_c_compiler_flag(-Wdocumentation HAVE_GCC_WDOCUMENTATION) @@ -62,10 +62,10 @@ function(SDL_AddCommonCompilerFlags TARGET) if(SDL_WERROR) check_c_compiler_flag(-Werror=documentation HAVE_GCC_WERROR_DOCUMENTATION) if(HAVE_GCC_WERROR_DOCUMENTATION) - target_compile_options(${TARGET} PRIVATE "-Werror=documentation") + target_compile_options(${TARGET} PRIVATE "$<$:-Werror=documentation>") endif() endif() - target_compile_options(${TARGET} PRIVATE "-Wdocumentation") + target_compile_options(${TARGET} PRIVATE "$<$:-Wdocumentation>") endif() check_c_compiler_flag(-Wdocumentation-unknown-command HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND) @@ -73,30 +73,30 @@ function(SDL_AddCommonCompilerFlags TARGET) if(SDL_WERROR) check_c_compiler_flag(-Werror=documentation-unknown-command HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND) if(HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND) - target_compile_options(${TARGET} PRIVATE "-Werror=documentation-unknown-command") + target_compile_options(${TARGET} PRIVATE "$<$:-Werror=documentation-unknown-command>") endif() endif() - target_compile_options(${TARGET} PRIVATE "-Wdocumentation-unknown-command") + target_compile_options(${TARGET} PRIVATE "$<$:-Wdocumentation-unknown-command>") endif() check_c_compiler_flag(-fcomment-block-commands=threadsafety HAVE_GCC_COMMENT_BLOCK_COMMANDS) if(HAVE_GCC_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "-fcomment-block-commands=threadsafety") + target_compile_options(${TARGET} PRIVATE "$<$:-fcomment-block-commands=threadsafety>") else() check_c_compiler_flag(/clang:-fcomment-block-commands=threadsafety HAVE_CLANG_COMMENT_BLOCK_COMMANDS) if(HAVE_CLANG_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "/clang:-fcomment-block-commands=threadsafety") + target_compile_options(${TARGET} PRIVATE "$<$:/clang:-fcomment-block-commands=threadsafety>") endif() endif() check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW) if(HAVE_GCC_WSHADOW) - target_compile_options(${TARGET} PRIVATE "-Wshadow") + target_compile_options(${TARGET} PRIVATE "$<$:-Wshadow>") endif() check_c_compiler_flag(-Wunused-local-typedefs HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS) if(HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS) - target_compile_options(${TARGET} PRIVATE "-Wno-unused-local-typedefs") + target_compile_options(${TARGET} PRIVATE "$<$:-Wno-unused-local-typedefs>") endif() endif() @@ -109,7 +109,7 @@ function(SDL_AddCommonCompilerFlags TARGET) elseif(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QNX) check_c_compiler_flag(-Werror HAVE_WERROR) if(HAVE_WERROR) - target_compile_options(${TARGET} PRIVATE "-Werror") + target_compile_options(${TARGET} PRIVATE "$<$:-Werror>") endif() endif() endif() @@ -117,12 +117,12 @@ function(SDL_AddCommonCompilerFlags TARGET) if(USE_CLANG) check_c_compiler_flag("-fcolor-diagnostics" COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS) if(COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS) - target_compile_options(${TARGET} PRIVATE "-fcolor-diagnostics") + target_compile_options(${TARGET} PRIVATE "$<$:-fcolor-diagnostics>") endif() else() check_c_compiler_flag("-fdiagnostics-color=always" COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS) if(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS) - target_compile_options(${TARGET} PRIVATE "-fdiagnostics-color=always") + target_compile_options(${TARGET} PRIVATE "$<$:-fdiagnostics-color=always>") endif() endif() endfunction() diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 3643bb60f0c91..a3d63325c3f24 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -37,26 +37,28 @@ #include #include -#ifndef alloca -# ifdef HAVE_ALLOCA_H -# include -# elif defined(__GNUC__) -# define alloca __builtin_alloca -# elif defined(_MSC_VER) -# include -# define alloca _alloca -# elif defined(__WATCOMC__) -# include -# elif defined(__BORLANDC__) -# include -# elif defined(__DMC__) -# include -# elif defined(__AIX__) -#pragma alloca -# elif defined(__MRC__) +#ifndef SDL_DISABLE_ALLOCA +# ifndef alloca +# ifdef HAVE_ALLOCA_H +# include +# elif defined(__GNUC__) +# define alloca __builtin_alloca +# elif defined(_MSC_VER) +# include +# define alloca _alloca +# elif defined(__WATCOMC__) +# include +# elif defined(__BORLANDC__) +# include +# elif defined(__DMC__) +# include +# elif defined(__AIX__) +# pragma alloca +# elif defined(__MRC__) void *alloca(unsigned); -# else +# else char *alloca(); +# endif # endif #endif @@ -379,7 +381,7 @@ SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int)); extern "C" { #endif -#ifdef HAVE_ALLOCA +#ifndef SDL_DISABLE_ALLOCA #define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count)) #define SDL_stack_free(data) #else diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 017e06b06410d..35b5e58579f45 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -42,6 +42,8 @@ #cmakedefine HAVE_GCC_ATOMICS @HAVE_GCC_ATOMICS@ #cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET @HAVE_GCC_SYNC_LOCK_TEST_AND_SET@ +#cmakedefine SDL_DISABLE_ALLOCA + /* Comment this if you want to build without any C library requirements */ #cmakedefine HAVE_LIBC 1 #ifdef HAVE_LIBC @@ -74,7 +76,6 @@ #cmakedefine HAVE_CALLOC 1 #cmakedefine HAVE_REALLOC 1 #cmakedefine HAVE_FREE 1 -#cmakedefine HAVE_ALLOCA 1 #ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ #cmakedefine HAVE_GETENV 1 #cmakedefine HAVE_SETENV 1 diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h index 1f8c3ef8f2752..99a7ab7deca2e 100644 --- a/include/build_config/SDL_build_config_android.h +++ b/include/build_config/SDL_build_config_android.h @@ -57,7 +57,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_GETENV 1 #define HAVE_SETENV 1 #define HAVE_PUTENV 1 diff --git a/include/build_config/SDL_build_config_emscripten.h b/include/build_config/SDL_build_config_emscripten.h index 2503e98dfc7ed..afa4e16e11c7e 100644 --- a/include/build_config/SDL_build_config_emscripten.h +++ b/include/build_config/SDL_build_config_emscripten.h @@ -60,7 +60,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_GETENV 1 #define HAVE_SETENV 1 #define HAVE_PUTENV 1 diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index c180ef84908d6..96391f848f57c 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -49,7 +49,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_GETENV 1 #define HAVE_SETENV 1 #define HAVE_PUTENV 1 diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index ed3f83a645579..43400d3f6ef4c 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -54,7 +54,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_GETENV 1 #define HAVE_SETENV 1 #define HAVE_PUTENV 1 diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index 8a29bab171bbe..4d7242e5b5d34 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -131,7 +131,6 @@ typedef unsigned int uintptr_t; #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_QSORT 1 #define HAVE_BSEARCH 1 #define HAVE_ABS 1 diff --git a/include/build_config/SDL_build_config_wingdk.h b/include/build_config/SDL_build_config_wingdk.h index 47adef5068e1a..8d587e555f1e7 100644 --- a/include/build_config/SDL_build_config_wingdk.h +++ b/include/build_config/SDL_build_config_wingdk.h @@ -77,7 +77,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_QSORT 1 #define HAVE_BSEARCH 1 #define HAVE_ABS 1 diff --git a/include/build_config/SDL_build_config_winrt.h b/include/build_config/SDL_build_config_winrt.h index 73d4671459299..bc65ffea2ffdd 100644 --- a/include/build_config/SDL_build_config_winrt.h +++ b/include/build_config/SDL_build_config_winrt.h @@ -75,7 +75,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_QSORT 1 #define HAVE_BSEARCH 1 #define HAVE_ABS 1 diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 622a8bc4adfe9..08def0c0146c4 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -77,7 +77,6 @@ #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_ALLOCA 1 #define HAVE_QSORT 1 #define HAVE_BSEARCH 1 #define HAVE_ABS 1 diff --git a/src/stdlib/SDL_mslibc.c b/src/stdlib/SDL_mslibc.c index 1118427549946..184b7e2d1cf8b 100644 --- a/src/stdlib/SDL_mslibc.c +++ b/src/stdlib/SDL_mslibc.c @@ -696,8 +696,80 @@ void __declspec(naked) _aullshr() /* *INDENT-ON* */ } +void __declspec(naked) _chkstk(void) +{ + __asm { + push ecx + mov ecx,esp ; lea ecx,dword ptr [esp]+4 + add ecx,4 + sub ecx,eax + sbb eax,eax + not eax + and ecx,eax + mov eax,esp + and eax,0xfffff000 +L1: + cmp ecx,eax + jb short L2 + mov eax,ecx + pop ecx + xchg esp,eax + mov eax,dword ptr [eax] + mov dword ptr [esp],eax + ret +L2: + sub eax,0x1000 + test dword ptr [eax],eax + jmp short L1 + } +} + +void __declspec(naked) _alloca_probe_8(void) +{ + /* *INDENT-OFF* */ + __asm { + push ecx + mov ecx,esp ; lea ecx,dword ptr [esp]+8 + add ecx,8 + sub ecx,eax + and ecx,0x7 + add eax,ecx + sbb ecx,ecx + or eax,ecx + pop ecx + jmp _chkstk + } + /* *INDENT-ON* */ +} + +void __declspec(naked) _alloca_probe_16(void) +{ + /* *INDENT-OFF* */ + __asm { + push ecx + mov ecx,esp ; lea ecx,dword ptr [esp]+8 + add ecx,8 + sub ecx,eax + and ecx,0xf + add eax,ecx + sbb ecx,ecx + or eax,ecx + pop ecx + jmp _chkstk + } + /* *INDENT-ON* */ +} + #endif /* _M_IX86 */ +#ifdef _M_ARM64 + +void __chkstk(void); +void __chkstk() { +} + +#endif + #endif /* MSC_VER */ #ifdef __ICL diff --git a/src/stdlib/SDL_mslibc_x64.asm b/src/stdlib/SDL_mslibc_x64.asm new file mode 100644 index 0000000000000..1590d88ae7aec --- /dev/null +++ b/src/stdlib/SDL_mslibc_x64.asm @@ -0,0 +1,29 @@ +include ksamd64.inc + +text SEGMENT EXECUTE + +public __chkstk + +__chkstk: + sub rsp,010h + mov QWORD PTR [rsp],r10 + mov QWORD PTR [rsp+08h],r11 + xor r11,r11 + lea r10,[rsp+018h] + sub r10,rax + cmovb r10,r11 + mov r11,QWORD PTR gs:[TeStackLimit] + cmp r10,r11 + jae chkstk_finish + and r10w,0f000h +chkstk_loop: + lea r11,[r11-PAGE_SIZE] + mov BYTE PTR [r11],0h + cmp r10,r11 + jne chkstk_loop +chkstk_finish: + mov r10,QWORD PTR [rsp] + mov r11,QWORD PTR [rsp+08h] + add rsp,010h + ret +end From 0e87b71d08c75af8c4b02808038825d3b16bf854 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 29 Oct 2023 14:12:38 -0400 Subject: [PATCH 172/725] wayland: Check the relative pointer handle before destroying If the relative protocol is unsupported, this will always be null and the destroy function won't be called. --- src/video/wayland/SDL_waylandevents.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 203e6a41e6483..9326cd55c2ace 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -2989,8 +2989,10 @@ int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input) w->locked_pointer = NULL; } - zwp_relative_pointer_v1_destroy(input->relative_pointer); - input->relative_pointer = NULL; + if (input->relative_pointer) { + zwp_relative_pointer_v1_destroy(input->relative_pointer); + input->relative_pointer = NULL; + } d->relative_mouse_mode = 0; From 875e45e70b4086ca8cdff405231fc616f06cda7e Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 29 Oct 2023 14:23:14 -0400 Subject: [PATCH 173/725] wayland: Sanity check pointers and protocols before confining --- src/video/wayland/SDL_waylandevents.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 9326cd55c2ace..14d7c4380cb3f 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -2902,6 +2902,10 @@ static void lock_pointer_to_window(SDL_Window *window, SDL_VideoData *d = input->display; struct zwp_locked_pointer_v1 *locked_pointer; + if (!d->pointer_constraints || !input->pointer) { + return; + } + if (w->locked_pointer) { return; } From 9cb259e865584c3d7d6927c04949a5b6e36829ae Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 30 Oct 2023 13:08:10 -0400 Subject: [PATCH 174/725] audio: Never SDL_PushEvent from anywhere but SDL_UpdateAudio(). Fixes some corner-case deadlocks. --- src/audio/SDL_audio.c | 84 ++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 410b5c368c5e5..dd1cd2dbf0bce 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1916,6 +1916,13 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) return; // this is already the default. } + // Queue up events to push to the queue next time it pumps (presumably + // in a safer thread). + // !!! FIXME: this duplicates some code we could probably refactor. + SDL_PendingAudioDeviceEvent pending; + pending.next = NULL; + SDL_PendingAudioDeviceEvent *pending_tail = &pending; + SDL_LockMutex(new_default_device->lock); SDL_AudioDevice *current_default_device = ObtainPhysicalAudioDevice(current_devid); @@ -1966,7 +1973,6 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (needs_migration) { const SDL_bool spec_changed = !AUDIO_SPECS_EQUAL(current_default_device->spec, new_default_device->spec); - const SDL_bool post_fmt_event = (spec_changed && SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)) ? SDL_TRUE : SDL_FALSE; SDL_LogicalAudioDevice *next = NULL; for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = next) { next = logdev->next; @@ -1995,15 +2001,18 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) RefPhysicalAudioDevice(new_default_device); UnrefPhysicalAudioDevice(current_default_device); - // Post an event for each logical device we moved. - if (post_fmt_event) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; - event.common.timestamp = 0; - event.adevice.iscapture = iscapture ? 1 : 0; - event.adevice.which = logdev->instance_id; - SDL_PushEvent(&event); + SDL_PendingAudioDeviceEvent *p; + + // Queue an event for each logical device we moved. + if (spec_changed) { + p = (SDL_PendingAudioDeviceEvent *)SDL_malloc(sizeof(SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; + p->devid = logdev->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } } } @@ -2027,6 +2036,15 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (current_default_device && SDL_AtomicGet(¤t_default_device->zombie)) { UnrefPhysicalAudioDevice(current_default_device); } + + if (pending.next) { + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); + current_audio.pending_events_tail->next = pending.next; + current_audio.pending_events_tail = pending_tail; + SDL_UnlockRWLock(current_audio.device_hash_lock); + } } int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) @@ -2070,17 +2088,43 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL } // Post an event for the physical device, and each logical device on this physical device. - if (!kill_device && SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)) { - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; - event.common.timestamp = 0; - event.adevice.iscapture = device->iscapture ? 1 : 0; - event.adevice.which = device->instance_id; - SDL_PushEvent(&event); + if (!kill_device) { + // Queue up events to push to the queue next time it pumps (presumably + // in a safer thread). + // !!! FIXME: this duplicates some code we could probably refactor. + SDL_PendingAudioDeviceEvent pending; + pending.next = NULL; + SDL_PendingAudioDeviceEvent *pending_tail = &pending; + + SDL_PendingAudioDeviceEvent *p; + + p = (SDL_PendingAudioDeviceEvent *)SDL_malloc(sizeof(SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; + p->devid = device->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - event.adevice.which = logdev->instance_id; - SDL_PushEvent(&event); + p = (SDL_PendingAudioDeviceEvent *)SDL_malloc(sizeof(SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; + p->devid = logdev->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } + } + + if (pending.next) { + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); + current_audio.pending_events_tail->next = pending.next; + current_audio.pending_events_tail = pending_tail; + SDL_UnlockRWLock(current_audio.device_hash_lock); } } From dcc8805c21ebb6ef763d9ebfee047a547ccb016d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 30 Oct 2023 13:09:56 -0400 Subject: [PATCH 175/725] testaudio: Fixed compiler warning on Visual Studio. --- test/testaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testaudio.c b/test/testaudio.c index a1bafa04e37cf..e77901c94e72c 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -359,8 +359,8 @@ static void DrawOneThing(SDL_Renderer *renderer, Thing *thing) if (thing->scale != 1.0f) { const float centerx = thing->rect.x + (thing->rect.w / 2); const float centery = thing->rect.y + (thing->rect.h / 2); - const int w = thing->texture ? thing->texture->w : 128; - const int h = thing->texture ? thing->texture->h : 128; + const int w = thing->texture ? (int) thing->texture->w : 128; + const int h = thing->texture ? (int) thing->texture->h : 128; dst.w = w * thing->scale; dst.h = h * thing->scale; dst.x = centerx - (dst.w / 2); From 4aacc4b92ee4abc2e9d71fb1b696761b125bb606 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 30 Oct 2023 19:50:35 +0100 Subject: [PATCH 176/725] cmake: file(RELATIVE_PATH) needs 2 absolute paths --- cmake/sdltargets.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/sdltargets.cmake b/cmake/sdltargets.cmake index 46496239e586b..d4fe913753c15 100644 --- a/cmake/sdltargets.cmake +++ b/cmake/sdltargets.cmake @@ -332,6 +332,9 @@ function(configure_sdl3_pc) endif() # Calculate prefix relative to location of sdl3.pc + if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}") + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_PREFIX}") + endif() file(RELATIVE_PATH SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/${SDL_PKGCONFIG_INSTALLDIR}" "${CMAKE_INSTALL_PREFIX}") string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") From f18120c83cc623224a694677837ea4d78cd5b94f Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 30 Oct 2023 19:59:28 +0100 Subject: [PATCH 177/725] cmake: check -fobjc-arc compiler flag on Apple platforms --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6edba99fb69a5..c9cd8b35592eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2973,6 +2973,10 @@ if(ANDROID) endif() if(APPLE) + check_c_compiler_flag(-fobjc-arc COMPILER_SUPPORTS_-fobjc-arc) + if(NOT COMPILER_SUPPORTS_-fobjc-arc) + message(FATAL_ERROR "Compiler does not support -fobjc-arc: this is required on Apple platforms") + endif() sdl_compile_options(PRIVATE "-fobjc-arc") endif() From 5d95cbde37c749183ae5de97008bee99cb7f40a5 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 30 Oct 2023 20:43:22 +0100 Subject: [PATCH 178/725] cmake: reset check state before testing -fobjc-arc --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9cd8b35592eb..3bfd22464056b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2973,8 +2973,10 @@ if(ANDROID) endif() if(APPLE) - check_c_compiler_flag(-fobjc-arc COMPILER_SUPPORTS_-fobjc-arc) - if(NOT COMPILER_SUPPORTS_-fobjc-arc) + cmake_push_check_state(RESET) + check_c_compiler_flag(-fobjc-arc COMPILER_SUPPORTS_FOBJC_ARC) + cmake_pop_check_state() + if(NOT COMPILER_SUPPORTS_FOBJC_ARC) message(FATAL_ERROR "Compiler does not support -fobjc-arc: this is required on Apple platforms") endif() sdl_compile_options(PRIVATE "-fobjc-arc") From 24e3328cca752ed4eb7ccfeee962eda4d3bc9974 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 31 Oct 2023 10:50:37 -0400 Subject: [PATCH 179/725] audio: Don't reset device ID counter on subsystem init/quit. Otherwise you risk a buggy app holding an obsolete device ID that now refers to a different device after reinit. --- src/audio/SDL_audio.c | 9 +++++---- src/audio/SDL_sysaudio.h | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index dd1cd2dbf0bce..46e7449e39541 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -275,16 +275,16 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device); SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_CAPTURE < SDL_AUDIO_DEVICE_DEFAULT_OUTPUT); +static SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_bool islogical) { /* Assign an instance id! Start at 2, in case there are things from the SDL2 era that still think 1 is a special value. - There's no reasonable scenario where this rolls over, but just in case, we wrap it in a loop. Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, etc. */ // The bottom two bits of the instance id tells you if it's an output device (1<<0), and if it's a physical device (1<<1). const SDL_AudioDeviceID flags = (iscapture ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); - const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(¤t_audio.last_device_instance_id) + 1)) << 2) | flags; + const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(&last_device_instance_id) + 1)) << 2) | flags; SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) ); return instance_id; } @@ -669,6 +669,9 @@ int SDL_InitAudio(const char *driver_name) SDL_QuitAudio(); // shutdown driver if already running. } + // make sure device IDs start at 2 (because of SDL2 legacy interface), but don't reset the counter on each init, in case the app is holding an old device ID somewhere. + SDL_AtomicCAS(&last_device_instance_id, 0, 2); + SDL_ChooseAudioConverters(); SDL_SetupAudioResampler(); @@ -719,7 +722,6 @@ int SDL_InitAudio(const char *driver_name) tried_to_init = SDL_TRUE; SDL_zero(current_audio); current_audio.pending_events_tail = ¤t_audio.pending_events; - SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. current_audio.device_hash_lock = device_hash_lock; current_audio.device_hash = device_hash; if (bootstrap[i]->init(¤t_audio.impl)) { @@ -744,7 +746,6 @@ int SDL_InitAudio(const char *driver_name) tried_to_init = SDL_TRUE; SDL_zero(current_audio); current_audio.pending_events_tail = ¤t_audio.pending_events; - SDL_AtomicSet(¤t_audio.last_device_instance_id, 2); // start past 1 because of SDL2's legacy interface. current_audio.device_hash_lock = device_hash_lock; current_audio.device_hash = device_hash; if (bootstrap[i]->init(¤t_audio.impl)) { diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 374616c2c456a..7969207692e32 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -175,7 +175,6 @@ typedef struct SDL_AudioDriver // !!! FIXME: most (all?) of these don't have to be atomic. SDL_AtomicInt output_device_count; SDL_AtomicInt capture_device_count; - SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs. } SDL_AudioDriver; From 40fb76196c3f40c3dbfc36e00e30bf9e30ac3de0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 31 Oct 2023 10:52:50 -0400 Subject: [PATCH 180/725] audio: Don't let simplified audio streams bind to new devices. This can happen if you close the stream's underlying device directly, which removes the binding but doesn't destroy the object. In this case, the stream remains valid until destroyed, but still should not be able to be bound to a new device. --- src/audio/SDL_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 46e7449e39541..9c6afb39e7c50 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1689,6 +1689,8 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); if (stream->bound_device) { retval = SDL_SetError("Stream #%d is already bound to a device", i); + } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. + retval = SDL_SetError("Cannot change binding on a stream created with SDL_OpenAudioDeviceStream"); } } From 0e614d9179ddfa1904e0ce06a22b825a3aba016e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Nov 2023 00:10:25 -0400 Subject: [PATCH 181/725] audio: Massive reworking on thread locking. This cleans up a ton of race conditions, and starts moving towards something we can use with Clang's -Wthread-safety (but that has a ways to go still). --- src/audio/SDL_audio.c | 629 +++++++++++++++++++++++------------------- 1 file changed, 345 insertions(+), 284 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 9c6afb39e7c50..a46f4efa53903 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -289,6 +289,134 @@ static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_boo return instance_id; } +static void ObtainPhysicalAudioDeviceObj(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXMEL SDL_ACQUIRE +{ + if (device) { + RefPhysicalAudioDevice(device); + SDL_LockMutex(device->lock); + } +} + +static void ReleaseAudioDevice(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_RELEASE +{ + if (device) { + SDL_UnlockMutex(device->lock); + UnrefPhysicalAudioDevice(device); + } +} + +// If found, this locks _the physical device_ this logical device is associated with, before returning. +static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_AudioDevice **device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_ACQUIRE +{ + SDL_assert(device != NULL); + + *device = NULL; + + if (!SDL_GetCurrentAudioDriver()) { + SDL_SetError("Audio subsystem is not initialized"); + return NULL; + } + + SDL_LogicalAudioDevice *logdev = NULL; + + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + if (islogical) { // don't bother looking if it's not a logical device id value. + SDL_LockRWLockForReading(current_audio.device_hash_lock); + SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); + if (logdev) { + *device = logdev->physical_device; + RefPhysicalAudioDevice(*device); // reference it, in case the logical device migrates to a new default. + } + SDL_UnlockRWLock(current_audio.device_hash_lock); + } + + if (!logdev) { + SDL_SetError("Invalid audio device instance ID"); + } else { + SDL_assert(*device != NULL); + SDL_LockMutex((*device)->lock); + } + + return logdev; +} + + +/* this finds the physical device associated with `devid` and locks it for use. + Note that a logical device instance id will return its associated physical device! */ +static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE +{ + SDL_AudioDevice *device = NULL; + + // bit #1 of devid is set for physical devices and unset for logical. + const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + if (islogical) { + ObtainLogicalAudioDevice(devid, &device); + } else if (!SDL_GetCurrentAudioDriver()) { // (the `islogical` path, above, checks this in ObtainLogicalAudioDevice.) + SDL_SetError("Audio subsystem is not initialized"); + } else { + SDL_LockRWLockForReading(current_audio.device_hash_lock); + SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device); + SDL_UnlockRWLock(current_audio.device_hash_lock); + + if (!device) { + SDL_SetError("Invalid audio device instance ID"); + } else { + ObtainPhysicalAudioDeviceObj(device); + } + } + + return device; +} + +static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE +{ + const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) ? SDL_TRUE : SDL_FALSE; + if (!wants_default) { + return ObtainPhysicalAudioDevice(devid); + } + + const SDL_AudioDeviceID orig_devid = devid; + + while (SDL_TRUE) { + SDL_LockRWLockForReading(current_audio.device_hash_lock); + if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { + devid = current_audio.default_output_device_id; + } else if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { + devid = current_audio.default_capture_device_id; + } + SDL_UnlockRWLock(current_audio.device_hash_lock); + + if (devid == 0) { + SDL_SetError("No default audio device available"); + break; + } + + SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); + if (!device) { + break; + } + + // make sure the default didn't change while we were waiting for the lock... + SDL_bool got_it = SDL_FALSE; + SDL_LockRWLockForReading(current_audio.device_hash_lock); + if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) && (devid == current_audio.default_output_device_id)) { + got_it = SDL_TRUE; + } else if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) && (devid == current_audio.default_capture_device_id)) { + got_it = SDL_TRUE; + } + SDL_UnlockRWLock(current_audio.device_hash_lock); + + if (got_it) { + return device; + } + + ReleaseAudioDevice(device); // let it go and try again. + } + + return NULL; +} + // this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device! // It also will not unref the physical device, since we might be shutting down; SDL_CloseAudioDevice handles the unref. static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) @@ -334,11 +462,11 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) } // Destroy any logical devices that still exist... - SDL_LockMutex(device->lock); + SDL_LockMutex(device->lock); // don't use ObtainPhysicalAudioDeviceObj because we don't want to change refcounts while destroying. while (device->logical_devices != NULL) { DestroyLogicalAudioDevice(device->logical_devices); } - SDL_UnlockMutex(device->lock); + SDL_UnlockMutex(device->lock); // don't use ReleaseAudioDevice because we don't want to change refcounts while destroying. // it's safe to not hold the lock for this (we can't anyhow, or the audio thread won't quit), because we shouldn't be in the device list at this point. ClosePhysicalAudioDevice(device); @@ -483,27 +611,6 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) return; } - SDL_LockMutex(device->lock); - - if (!SDL_AtomicCAS(&device->zombie, 0, 1)) { - SDL_UnlockMutex(device->lock); - return; // already disconnected this device, don't do it twice. - } - - // Swap in "Zombie" versions of the usual platform interfaces, so the device will keep - // making progress until the app closes it. Otherwise, streams might continue to - // accumulate waste data that never drains, apps that depend on audio callbacks to - // progress will freeze, etc. - device->WaitDevice = ZombieWaitDevice; - device->GetDeviceBuf = ZombieGetDeviceBuf; - device->PlayDevice = ZombiePlayDevice; - device->WaitCaptureDevice = ZombieWaitDevice; - device->CaptureFromDevice = ZombieCaptureFromDevice; - device->FlushCapture = ZombieFlushCapture; - - const SDL_AudioDeviceID devid = device->instance_id; - const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)) ? SDL_TRUE : SDL_FALSE; - // Save off removal info in a list so we can send events for each, next // time the event queue pumps, in case something tries to close a device // from an event filter, as this would risk deadlocks and other disasters @@ -512,45 +619,64 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) pending.next = NULL; SDL_PendingAudioDeviceEvent *pending_tail = &pending; - // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. - // on non-default devices, dump everything. - // (by "dump" we mean send a REMOVED event; the zombie will keep consuming audio data for these logical devices until explicitly closed.) - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - if (!is_default_device || !logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. - SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); - if (p) { // if this failed, no event for you, but you have deeper problems anyhow. - p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; - p->devid = logdev->instance_id; - p->next = NULL; - pending_tail->next = p; - pending_tail = p; + ObtainPhysicalAudioDeviceObj(device); + + SDL_LockRWLockForReading(current_audio.device_hash_lock); + const SDL_AudioDeviceID devid = device->instance_id; + const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)) ? SDL_TRUE : SDL_FALSE; + SDL_UnlockRWLock(current_audio.device_hash_lock); + + const SDL_bool first_disconnect = SDL_AtomicCAS(&device->zombie, 0, 1); + if (first_disconnect) { // if already disconnected this device, don't do it twice. + // Swap in "Zombie" versions of the usual platform interfaces, so the device will keep + // making progress until the app closes it. Otherwise, streams might continue to + // accumulate waste data that never drains, apps that depend on audio callbacks to + // progress will freeze, etc. + device->WaitDevice = ZombieWaitDevice; + device->GetDeviceBuf = ZombieGetDeviceBuf; + device->PlayDevice = ZombiePlayDevice; + device->WaitCaptureDevice = ZombieWaitDevice; + device->CaptureFromDevice = ZombieCaptureFromDevice; + device->FlushCapture = ZombieFlushCapture; + + // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. + // on non-default devices, dump everything. + // (by "dump" we mean send a REMOVED event; the zombie will keep consuming audio data for these logical devices until explicitly closed.) + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + if (!is_default_device || !logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. + SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; + p->devid = logdev->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } } } - } - SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); - if (p) { // if this failed, no event for you, but you have deeper problems anyhow. - p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; - p->devid = device->instance_id; - p->next = NULL; - pending_tail->next = p; - pending_tail = p; + SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); + if (p) { // if this failed, no event for you, but you have deeper problems anyhow. + p->type = SDL_EVENT_AUDIO_DEVICE_REMOVED; + p->devid = device->instance_id; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } } - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); - if (pending.next) { // NULL if event is disabled or disaster struck. - SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail != NULL); - SDL_assert(current_audio.pending_events_tail->next == NULL); - current_audio.pending_events_tail->next = pending.next; - current_audio.pending_events_tail = pending_tail; - SDL_UnlockRWLock(current_audio.device_hash_lock); - } + if (first_disconnect) { + if (pending.next) { // NULL if event is disabled or disaster struck. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); + current_audio.pending_events_tail->next = pending.next; + current_audio.pending_events_tail = pending_tail; + SDL_UnlockRWLock(current_audio.device_hash_lock); + } - // Is this a non-default device? We can unref it now. - // Otherwise, we'll unref it when a new default device is chosen. - if (!is_default_device) { UnrefPhysicalAudioDevice(device); } } @@ -622,9 +748,10 @@ static void CompleteAudioEntryPoints(void) #undef FILL_STUB } -static SDL_AudioDeviceID GetFirstAddedAudioDeviceID(const SDL_bool iscapture) +static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) { - SDL_AudioDeviceID retval = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_OUTPUT; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. + SDL_AudioDeviceID highest = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_OUTPUT; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. + SDL_AudioDevice *retval = NULL; // (Device IDs increase as new devices are added, so the first device added has the lowest SDL_AudioDeviceID value.) SDL_LockRWLockForReading(current_audio.device_hash_lock); @@ -633,16 +760,17 @@ static SDL_AudioDeviceID GetFirstAddedAudioDeviceID(const SDL_bool iscapture) const void *value; void *iter = NULL; while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { - const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) value; + const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; // bit #1 of devid is set for physical devices and unset for logical. const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; - if (isphysical && (devid < retval)) { - retval = devid; + if (isphysical && (devid < highest)) { + highest = devid; + retval = (SDL_AudioDevice *) value; } } SDL_UnlockRWLock(current_audio.device_hash_lock); - return (retval == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) ? 0 : retval; + return retval; } static Uint32 HashAudioDeviceID(const void *key, void *data) @@ -779,20 +907,23 @@ int SDL_InitAudio(const char *driver_name) SDL_AudioDevice *default_capture = NULL; current_audio.impl.DetectDevices(&default_output, &default_capture); - // these are only set if default_* is non-NULL, in case the backend just called SDL_DefaultAudioDeviceChanged directly during DetectDevices. + // If no default was _ever_ specified, just take the first device we see, if any. + if (!default_output) { + default_output = GetFirstAddedAudioDevice(/*iscapture=*/SDL_FALSE); + } + + if (!default_capture) { + default_capture = GetFirstAddedAudioDevice(/*iscapture=*/SDL_TRUE); + } + if (default_output) { current_audio.default_output_device_id = default_output->instance_id; + RefPhysicalAudioDevice(default_output); // extra ref on default devices. } + if (default_capture) { current_audio.default_capture_device_id = default_capture->instance_id; - } - - // If no default was _ever_ specified, just take the first device we see, if any. - if (!current_audio.default_output_device_id) { - current_audio.default_output_device_id = GetFirstAddedAudioDeviceID(/*iscapture=*/SDL_FALSE); - } - if (!current_audio.default_capture_device_id) { - current_audio.default_capture_device_id = GetFirstAddedAudioDeviceID(/*iscapture=*/SDL_TRUE); + RefPhysicalAudioDevice(default_capture); // extra ref on default devices. } return 0; @@ -1171,62 +1302,6 @@ SDL_AudioDeviceID *SDL_GetAudioCaptureDevices(int *count) return GetAudioDevices(count, SDL_TRUE); } -// If found, this locks _the physical device_ this logical device is associated with, before returning. -static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid) -{ - if (!SDL_GetCurrentAudioDriver()) { - SDL_SetError("Audio subsystem is not initialized"); - return NULL; - } - - SDL_LogicalAudioDevice *logdev = NULL; - - // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; - if (islogical) { // don't bother looking if it's not a logical device id value. - SDL_LockRWLockForReading(current_audio.device_hash_lock); - SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); - SDL_UnlockRWLock(current_audio.device_hash_lock); - } - - if (!logdev) { - SDL_SetError("Invalid audio device instance ID"); - } else { - SDL_LockMutex(logdev->physical_device->lock); - } - - return logdev; -} - -/* this finds the physical device associated with `devid` and locks it for use. - Note that a logical device instance id will return its associated physical device! */ -static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) -{ - SDL_AudioDevice *device = NULL; - - // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; - if (islogical) { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); - if (logdev) { - device = logdev->physical_device; - } - } else if (!SDL_GetCurrentAudioDriver()) { // (the `islogical` path, above, checks this in ObtainLogicalAudioDevice.) - SDL_SetError("Audio subsystem is not initialized"); - } else { - SDL_LockRWLockForReading(current_audio.device_hash_lock); - SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device); - SDL_UnlockRWLock(current_audio.device_hash_lock); - - if (!device) { - SDL_SetError("Invalid audio device instance ID"); - } else { - SDL_LockMutex(device->lock); // caller must unlock. - } - } - - return device; -} SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata) { @@ -1270,17 +1345,15 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle) char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) { + char *retval = NULL; SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); - if (!device) { - return NULL; - } - - char *retval = SDL_strdup(device->name); - if (!retval) { - SDL_OutOfMemory(); + if (device) { + retval = SDL_strdup(device->name); + if (!retval) { + SDL_OutOfMemory(); + } } - - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); return retval; } @@ -1291,31 +1364,18 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * return SDL_InvalidParamError("spec"); } - SDL_bool wants_default = SDL_FALSE; - if (devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { - devid = current_audio.default_output_device_id; - wants_default = SDL_TRUE; - } else if (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { - devid = current_audio.default_capture_device_id; - wants_default = SDL_TRUE; - } - - if ((devid == 0) && wants_default) { - return SDL_SetError("No default audio device available"); - } - - SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); - if (!device) { - return -1; - } - - SDL_copyp(spec, &device->spec); - if (sample_frames) { - *sample_frames = device->sample_frames; + int retval = -1; + SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); // !!! FIXME: this needs an ObtainBlahDefaultAllowed to catch default device changes. + if (device) { + SDL_copyp(spec, &device->spec); + if (sample_frames) { + *sample_frames = device->sample_frames; + } + retval = 0; } - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); - return 0; + return retval; } // this expects the device lock to be held. !!! FIXME: no it doesn't...? @@ -1350,20 +1410,21 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); + SDL_bool close_physical = SDL_FALSE; + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); if (logdev) { - SDL_AudioDevice *device = logdev->physical_device; DestroyLogicalAudioDevice(logdev); + close_physical = (device->logical_devices == NULL); // no more logical devices? Close the physical device, too. + } - const SDL_bool close_physical = (device->logical_devices == NULL); // no more logical devices? Close the physical device, too. - - // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. - SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. + // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. + ReleaseAudioDevice(device); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. + if (device) { if (close_physical) { ClosePhysicalAudioDevice(device); } - UnrefPhysicalAudioDevice(device); // one reference for each logical device. } } @@ -1514,30 +1575,17 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp return 0; } - SDL_bool wants_default = SDL_FALSE; - if (devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { - devid = current_audio.default_output_device_id; - wants_default = SDL_TRUE; - } else if (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { - devid = current_audio.default_capture_device_id; - wants_default = SDL_TRUE; - } - - if ((devid == 0) && wants_default) { - SDL_SetError("No default audio device available"); - return 0; - } + SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) ? SDL_TRUE : SDL_FALSE; // this will let you use a logical device to make a new logical device on the parent physical device. Could be useful? SDL_AudioDevice *device = NULL; - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool islogical = (wants_default || (devid & (1<<1))) ? SDL_FALSE : SDL_TRUE; if (!islogical) { - device = ObtainPhysicalAudioDevice(devid); + device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); } else { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); // this locks the physical device, too. + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); if (logdev) { wants_default = logdev->opened_as_default; // was the original logical device meant to be a default? Make this one, too. - device = logdev->physical_device; } } @@ -1565,7 +1613,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp device->logical_devices = logdev; UpdateAudioStreamFormatsPhysical(device); } - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); if (retval) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); @@ -1583,13 +1631,13 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp static int SetLogicalAudioDevicePauseState(SDL_AudioDeviceID devid, int value) { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); - if (!logdev) { - return -1; // ObtainLogicalAudioDevice will have set an error. + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); + if (logdev) { + SDL_AtomicSet(&logdev->paused, value); } - SDL_AtomicSet(&logdev->paused, value); - SDL_UnlockMutex(logdev->physical_device->lock); - return 0; + ReleaseAudioDevice(device); + return logdev ? 0 : -1; // ObtainLogicalAudioDevice will have set an error. } int SDL_PauseAudioDevice(SDL_AudioDeviceID devid) @@ -1604,23 +1652,22 @@ int SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid) SDL_bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid) { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); SDL_bool retval = SDL_FALSE; - if (logdev) { - if (SDL_AtomicGet(&logdev->paused)) { - retval = SDL_TRUE; - } - SDL_UnlockMutex(logdev->physical_device->lock); + if (logdev && SDL_AtomicGet(&logdev->paused)) { + retval = SDL_TRUE; } + ReleaseAudioDevice(device); return retval; } int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallback callback, void *userdata) { - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid); + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); int retval = 0; if (logdev) { - SDL_AudioDevice *device = logdev->physical_device; if (callback && !device->postmix_buffer) { device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); if (device->postmix_buffer == NULL) { @@ -1644,15 +1691,17 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac } UpdateAudioStreamFormatsPhysical(device); - SDL_UnlockMutex(device->lock); } + ReleaseAudioDevice(device); return retval; } int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams) { const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; - SDL_LogicalAudioDevice *logdev; + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = NULL; + int retval = 0; if (num_streams == 0) { return 0; // nothing to do @@ -1662,49 +1711,49 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int return SDL_InvalidParamError("streams"); } else if (!islogical) { return SDL_SetError("Audio streams are bound to device ids from SDL_OpenAudioDevice, not raw physical devices"); - } else if ((logdev = ObtainLogicalAudioDevice(devid)) == NULL) { - return -1; // ObtainLogicalAudioDevice set the error message. - } else if (logdev->simplified) { - SDL_UnlockMutex(logdev->physical_device->lock); - return SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream"); } - // !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet. - // !!! FIXME: Actually, why do we allow there to be an invalid format, again? + logdev = ObtainLogicalAudioDevice(devid, &device); + if (!logdev) { + retval = -1; // ObtainLogicalAudioDevice set the error string. + } else if (logdev->simplified) { + retval = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream"); + } else { - // make sure start of list is sane. - SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL)); + // !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet. + // !!! FIXME: Actually, why do we allow there to be an invalid format, again? - SDL_AudioDevice *device = logdev->physical_device; - const SDL_bool iscapture = device->iscapture; - int retval = 0; + // make sure start of list is sane. + SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL)); - // lock all the streams upfront, so we can verify they aren't bound elsewhere and add them all in one block, as this is intended to add everything or nothing. - for (int i = 0; i < num_streams; i++) { - SDL_AudioStream *stream = streams[i]; - if (stream == NULL) { - retval = SDL_SetError("Stream #%d is NULL", i); - } else { - SDL_LockMutex(stream->lock); - SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); - if (stream->bound_device) { - retval = SDL_SetError("Stream #%d is already bound to a device", i); - } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. - retval = SDL_SetError("Cannot change binding on a stream created with SDL_OpenAudioDeviceStream"); + // lock all the streams upfront, so we can verify they aren't bound elsewhere and add them all in one block, as this is intended to add everything or nothing. + for (int i = 0; i < num_streams; i++) { + SDL_AudioStream *stream = streams[i]; + if (stream == NULL) { + retval = SDL_SetError("Stream #%d is NULL", i); + } else { + SDL_LockMutex(stream->lock); + SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); + if (stream->bound_device) { + retval = SDL_SetError("Stream #%d is already bound to a device", i); + } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. + retval = SDL_SetError("Cannot change binding on a stream created with SDL_OpenAudioDeviceStream"); + } } - } - if (retval != 0) { - int j; - for (j = 0; j <= i; j++) { - SDL_UnlockMutex(streams[j]->lock); + if (retval != 0) { + int j; + for (j = 0; j <= i; j++) { + SDL_UnlockMutex(streams[j]->lock); + } + break; } - break; } } if (retval == 0) { // Now that everything is verified, chain everything together. + const SDL_bool iscapture = device->iscapture; for (int i = 0; i < num_streams; i++) { SDL_AudioStream *stream = streams[i]; @@ -1729,7 +1778,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int UpdateAudioStreamFormatsPhysical(device); - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); return retval; } @@ -1739,6 +1788,7 @@ int SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream) return SDL_BindAudioStreams(devid, &stream, 1); } +// !!! FIXME: this and BindAudioStreams are mutex nightmares. :/ void SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams) { /* to prevent deadlock when holding both locks, we _must_ lock the device first, and the stream second, as that is the order the audio thread will do it. @@ -1831,51 +1881,51 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au return NULL; // error string should already be set. } - SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(logdevid); + SDL_bool failed = SDL_FALSE; + SDL_AudioStream *stream = NULL; + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(logdevid, &device); if (logdev == NULL) { // this shouldn't happen, but just in case. - SDL_CloseAudioDevice(logdevid); - return NULL; // error string should already be set. - } - - SDL_AudioDevice *physdevice = logdev->physical_device; - SDL_assert(physdevice != NULL); + failed = SDL_TRUE; + } else { + SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. - SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. - SDL_UnlockMutex(physdevice->lock); // we don't need to hold the lock for any of this. + SDL_assert(device != NULL); + const SDL_bool iscapture = device->iscapture; - const SDL_bool iscapture = physdevice->iscapture; + if (iscapture) { + stream = SDL_CreateAudioStream(&device->spec, spec); + } else { + stream = SDL_CreateAudioStream(spec, &device->spec); + } - SDL_AudioStream *stream = NULL; - if (iscapture) { - stream = SDL_CreateAudioStream(&physdevice->spec, spec); - } else { - stream = SDL_CreateAudioStream(spec, &physdevice->spec); + if (!stream || (SDL_BindAudioStream(logdevid, stream) == -1)) { + failed = SDL_TRUE; + } else { + logdev->simplified = SDL_TRUE; // forbid further binding changes on this logical device. + stream->simplified = SDL_TRUE; // so we know to close the audio device when this is destroyed. + + if (callback) { + int rc; + if (iscapture) { + rc = SDL_SetAudioStreamPutCallback(stream, callback, userdata); + } else { + rc = SDL_SetAudioStreamGetCallback(stream, callback, userdata); + } + SDL_assert(rc == 0); // should only fail if stream==NULL atm. + } + } } - if (!stream) { - SDL_CloseAudioDevice(logdevid); - return NULL; // error string should already be set. - } - if (SDL_BindAudioStream(logdevid, stream) == -1) { + ReleaseAudioDevice(device); + + if (failed) { SDL_DestroyAudioStream(stream); SDL_CloseAudioDevice(logdevid); - return NULL; // error string should already be set. - } - - logdev->simplified = SDL_TRUE; // forbid further binding changes on this logical device. - stream->simplified = SDL_TRUE; // so we know to close the audio device when this is destroyed. - - if (callback) { - int rc; - if (iscapture) { - rc = SDL_SetAudioStreamPutCallback(stream, callback, userdata); - } else { - rc = SDL_SetAudioStreamGetCallback(stream, callback, userdata); - } - SDL_assert(rc == 0); // should only fail if stream==NULL atm. + stream = NULL; } - return stream; // ready to rock. + return stream; } #define NUM_FORMATS 8 @@ -1913,9 +1963,21 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) } const SDL_bool iscapture = new_default_device->iscapture; + + // change the official default over right away, so new opens will go to the new device. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); const SDL_AudioDeviceID current_devid = iscapture ? current_audio.default_capture_device_id : current_audio.default_output_device_id; + const SDL_bool is_already_default = (new_default_device->instance_id == current_devid) ? SDL_TRUE : SDL_FALSE; + if (!is_already_default) { + if (iscapture) { + current_audio.default_capture_device_id = new_default_device->instance_id; + } else { + current_audio.default_output_device_id = new_default_device->instance_id; + } + } + SDL_UnlockRWLock(current_audio.device_hash_lock); - if (new_default_device->instance_id == current_devid) { + if (is_already_default) { return; // this is already the default. } @@ -1926,17 +1988,12 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) pending.next = NULL; SDL_PendingAudioDeviceEvent *pending_tail = &pending; - SDL_LockMutex(new_default_device->lock); + // Default device gets an extra ref, so it lives until a new default replaces it, even if disconnected. + RefPhysicalAudioDevice(new_default_device); - SDL_AudioDevice *current_default_device = ObtainPhysicalAudioDevice(current_devid); + ObtainPhysicalAudioDeviceObj(new_default_device); - /* change the official default ID over while we have locks on both devices, so if something raced to open the default during - this, it either gets the new device or is ready on the old and can be migrated. */ - if (iscapture) { - current_audio.default_capture_device_id = new_default_device->instance_id; - } else { - current_audio.default_output_device_id = new_default_device->instance_id; - } + SDL_AudioDevice *current_default_device = ObtainPhysicalAudioDevice(current_devid); if (current_default_device) { // migrate any logical devices that were opened as a default to the new physical device... @@ -1984,7 +2041,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) continue; // not opened as a default, leave it on the current physical device. } - // now migrate the logical device. + // now migrate the logical device. Hold device_hash_lock so ObtainLogicalAudioDevice doesn't get a device in the middle of transition. + SDL_LockRWLockForWriting(current_audio.device_hash_lock); if (logdev->next) { logdev->next->prev = logdev->prev; } @@ -1999,6 +2057,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) logdev->prev = NULL; logdev->next = new_default_device->logical_devices; new_default_device->logical_devices = logdev; + SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_assert(SDL_AtomicGet(¤t_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase... RefPhysicalAudioDevice(new_default_device); @@ -2024,19 +2083,21 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (current_default_device->logical_devices == NULL) { // nothing left on the current physical device, close it. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. - SDL_UnlockMutex(current_default_device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. + RefPhysicalAudioDevice(current_default_device); // hold a temp ref for a moment while we release... + ReleaseAudioDevice(current_default_device); // can't hold the lock or the audio thread will deadlock while we WaitThread it. ClosePhysicalAudioDevice(current_default_device); - SDL_LockMutex(current_default_device->lock); // we're about to unlock this again, so make sure the locks match. + ObtainPhysicalAudioDeviceObj(current_default_device); // we're about to unlock this again, so make sure the locks match. + UnrefPhysicalAudioDevice(current_default_device); // drop temp ref. } } - SDL_UnlockMutex(current_default_device->lock); + ReleaseAudioDevice(current_default_device); } - SDL_UnlockMutex(new_default_device->lock); + ReleaseAudioDevice(new_default_device); - // was current device already dead and just kept around to migrate to a new default device? Now we can kill it. Aim for the brain. - if (current_default_device && SDL_AtomicGet(¤t_default_device->zombie)) { + // Default device gets an extra ref, so it lives until a new default replaces it, even if disconnected. + if (current_default_device) { // (despite the name, it's no longer current at this point) UnrefPhysicalAudioDevice(current_default_device); } @@ -2136,9 +2197,9 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL int SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) { - SDL_LockMutex(device->lock); + ObtainPhysicalAudioDeviceObj(device); const int retval = SDL_AudioDeviceFormatChangedAlreadyLocked(device, newspec, new_sample_frames); - SDL_UnlockMutex(device->lock); + ReleaseAudioDevice(device); return retval; } From 759cdf6159d8aab8bcfb129d9733821ca0206938 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Nov 2023 00:39:51 -0400 Subject: [PATCH 182/725] audio: Fixed GetFirstAudioDeviceAdded(). It forgot to check for the type of device needed. --- src/audio/SDL_audio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index a46f4efa53903..bb6acbe2bffb7 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -761,9 +761,11 @@ static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) void *iter = NULL; while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; + // bit #0 of devid is set for output devices and unset for capture. // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; - if (isphysical && (devid < highest)) { + const SDL_bool devid_iscapture = (devid & (1 << 0)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool isphysical = (devid & (1 << 1)) ? SDL_TRUE : SDL_FALSE; + if (isphysical && (devid_iscapture == iscapture) && (devid < highest)) { highest = devid; retval = (SDL_AudioDevice *) value; } From 9323417e9cc955c87b1415d0f24798cdb4f8df27 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 1 Nov 2023 08:36:51 -0700 Subject: [PATCH 183/725] Fixed gendyapi.py parsing of SDL_RELEASE_GENERIC --- src/dynapi/gendynapi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index 591f3d6379797..5e6a11b8c0f7a 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -156,6 +156,7 @@ def main(): func = re.sub(" SDL_TRY_ACQUIRE_SHARED\(.*\)", "", func); func = re.sub(" SDL_RELEASE\(.*\)", "", func); func = re.sub(" SDL_RELEASE_SHARED\(.*\)", "", func); + func = re.sub(" SDL_RELEASE_GENERIC\(.*\)", "", func); # Should be a valid function here match = reg_parsing_function.match(func) From 9c664b00623926a0973a8f19cecc55bc7c757d5b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Nov 2023 18:40:41 -0400 Subject: [PATCH 184/725] main: Added _optional_ callback entry points. This lets apps optionally have a handful of callbacks for their entry points instead of a single main function. If used, the actual main/SDL_main/whatever entry point will be implemented in the single-header library SDL_main.h and the app will implement four separate functions: First: int SDL_AppInit(int argc, char **argv); This will be called once before anything else. argc/argv work like they always do. If this returns 0, the app runs. If it returns < 0, the app calls SDL_AppQuit and terminates with an exit code that reports an error to the platform. If it returns > 0, the app calls SDL_AppQuit and terminates with an exit code that reports success to the platform. This function should not go into an infinite mainloop; it should do any one-time startup it requires and then return. Then: int SDL_AppIterate(void); This is called over and over, possibly at the refresh rate of the display or some other metric that the platform dictates. This is where the heart of your app runs. It should return as quickly as reasonably possible, but it's not a "run one memcpy and that's all the time you have" sort of thing. The app should do any game updates, and render a frame of video. If it returns < 0, SDL will call SDL_AppQuit and terminate the process with an exit code that reports an error to the platform. If it returns > 0, the app calls SDL_AppQuit and terminates with an exit code that reports success to the platform. If it returns 0, then SDL_AppIterate will be called again at some regular frequency. The platform may choose to run this more or less (perhaps less in the background, etc), or it might just call this function in a loop as fast as possible. You do not check the event queue in this function (SDL_AppEvent exists for that). Next: int SDL_AppEvent(const SDL_Event *event); This will be called once for each event pushed into the SDL queue. This may be called from any thread, and possibly in parallel to SDL_AppIterate. The fields in event do not need to be free'd (as you would normally need to do for SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the same as from SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. Finally: void SDL_AppQuit(void); This is called once before terminating the app--assuming the app isn't being forcibly killed or crashed--as a last chance to clean up. After this returns, SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app to call it, too). Process termination proceeds as if the app returned normally from main(), so atexit handles will run, if your platform supports that. The app does not implement SDL_main if using this. To turn this on, define SDL_MAIN_USE_CALLBACKS before including SDL_main.h. Defines like SDL_MAIN_HANDLED and SDL_MAIN_NOIMPL are also respected for callbacks, if the app wants to do some sort of magic main implementation thing. In theory, on most platforms these can be implemented in the app itself, but this saves some #ifdefs in the app and lets everyone struggle less against some platforms, and might be more efficient in the long run, too. On some platforms, it's possible this is the only reasonable way to go, but we haven't actually hit one that 100% requires it yet (but we will, if we want to write a RetroArch backend, for example). Using the callback entry points works on every platform, because on platforms that don't require them, we can fake them with a simple loop in an internal implementation of the usual SDL_main. The primary way we expect people to write SDL apps is with SDL_main, and this is not intended to replace it. If the app chooses to use this, it just removes some platform-specific details they might have to otherwise manage, and maybe removes a barrier to entry on some future platform. Fixes #6785. Reference PR #8247. --- CMakeLists.txt | 17 + VisualC-GDK/SDL/SDL.vcxproj | 3 + VisualC-GDK/SDL/SDL.vcxproj.filters | 15 + VisualC-WinRT/SDL-UWP.vcxproj | 3 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 15 + VisualC/SDL/SDL.vcxproj | 3 + VisualC/SDL/SDL.vcxproj.filters | 15 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 27 + include/SDL3/SDL_hints.h | 16 + include/SDL3/SDL_main.h | 224 +++++++- include/SDL3/SDL_main_impl.h | 26 + include/SDL3/SDL_test_common.h | 16 +- src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/main/SDL_main_callbacks.c | 114 ++++ src/main/SDL_main_callbacks.h | 31 ++ src/main/emscripten/SDL_sysmain_callbacks.c | 47 ++ src/main/generic/SDL_sysmain_callbacks.c | 80 +++ src/main/ios/SDL_sysmain_callbacks.m | 82 +++ src/test/SDL_test_common.c | 21 +- test/CMakeLists.txt | 23 +- test/loopwave.c | 112 ++-- test/testaudio.c | 543 ++++++++++---------- test/testaudiocapture.c | 177 +++---- test/testsprite.c | 63 +-- 26 files changed, 1151 insertions(+), 525 deletions(-) create mode 100644 src/main/SDL_main_callbacks.c create mode 100644 src/main/SDL_main_callbacks.h create mode 100644 src/main/emscripten/SDL_sysmain_callbacks.c create mode 100644 src/main/generic/SDL_sysmain_callbacks.c create mode 100644 src/main/ios/SDL_sysmain_callbacks.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bfd22464056b..dd24bbfb512f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -475,6 +475,7 @@ sdl_glob_sources( "${SDL3_SOURCE_DIR}/src/hidapi/*.c" "${SDL3_SOURCE_DIR}/src/libm/*.c" "${SDL3_SOURCE_DIR}/src/locale/*.c" + "${SDL3_SOURCE_DIR}/src/main/*.c" "${SDL3_SOURCE_DIR}/src/misc/*.c" "${SDL3_SOURCE_DIR}/src/power/*.c" "${SDL3_SOURCE_DIR}/src/render/*.c" @@ -1383,6 +1384,9 @@ elseif(EMSCRIPTEN) # project. Uncomment at will for verbose cross-compiling -I/../ path info. sdl_compile_options(PRIVATE "-Wno-warn-absolute-paths") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/emscripten/*.c") + set(HAVE_SDL_MAIN_CALLBACKS TRUE) + if(SDL_MISC) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/emscripten/*.c") set(HAVE_SDL_MISC TRUE) @@ -2033,6 +2037,8 @@ elseif(WINDOWS) elseif(APPLE) # TODO: rework this all for proper macOS, iOS and Darwin support + # !!! FIXME: all the `if(IOS OR TVOS OR VISIONOS)` checks should get merged into one variable, so we're ready for the next platform (or just WatchOS). + # We always need these libs on macOS at the moment. # !!! FIXME: we need Carbon for some very old API calls in # !!! FIXME: src/video/cocoa/SDL_cocoakeyboard.c, but we should figure out @@ -2044,6 +2050,12 @@ elseif(APPLE) set(SDL_FRAMEWORK_FOUNDATION 1) set(SDL_FRAMEWORK_COREVIDEO 1) + # iOS can use a CADisplayLink for main callbacks. macOS just uses the generic one atm. + if(IOS OR TVOS OR VISIONOS) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ios/*.m") + set(HAVE_SDL_MAIN_CALLBACKS TRUE) + endif() + # Requires the darwin file implementation if(SDL_FILE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") @@ -2803,6 +2815,11 @@ if(NOT HAVE_SDL_TIMERS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/dummy/*.c") endif() +# Most platforms use this. +if(NOT HAVE_SDL_MAIN_CALLBACKS) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/generic/*.c") +endif() + # config variables may contain generator expression, so we need to generate SDL_build_config.h in 2 steps: # 1. replace all `#cmakedefine`'s and `@abc@` configure_file("${SDL3_SOURCE_DIR}/include/build_config/SDL_build_config.h.cmake" diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 70b625b37f42a..b19bb5fba48ee 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -418,6 +418,7 @@ + @@ -468,6 +469,8 @@ $(IntDir)$(TargetName)_cpp.pch $(IntDir)$(TargetName)_cpp.pch + + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index a530ef1bfa18d..ba454f428fe1e 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -175,6 +175,12 @@ {3ad16a8a-0ed8-439c-a771-383af2e2867f} + + {00002ddb6c5ea921181bf32d50e40000} + + + {00000a808f8ba6b489985f82a4e80000} + @@ -399,6 +405,9 @@ API Headers + + main + @@ -846,6 +855,12 @@ + + main\generic + + + main + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 21c5e7ebba226..0dee306b691fd 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -133,6 +133,7 @@ + @@ -337,6 +338,8 @@ + + true diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 430babceb1239..7d765c13c113a 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -7,6 +7,12 @@ {68e1b30b-19ed-4612-93e4-6260c5a979e5} + + {00004a2523fc69c7128c60648c860000} + + + {0000318d975e0a2867ab1d5727bf0000} + @@ -270,6 +276,9 @@ Source Files + + main + Source Files @@ -588,6 +597,12 @@ Source Files + + main\generic + + + main + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 84e774521acc5..57eb07e85ca1c 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -368,6 +368,7 @@ + @@ -397,6 +398,8 @@ Create Create + + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 23fa7b2e3ffd4..cd7b2b2e3e176 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -169,6 +169,12 @@ {f48c2b17-1bee-4fec-a7c8-24cf619abe08} + + {00001967ea2801028a046a722a070000} + + + {0000ddc7911820dbe64274d3654f0000} + @@ -390,6 +396,9 @@ API Headers + + main + @@ -828,6 +837,12 @@ + + main\generic + + + main + diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 279a74856b0ff..bd32ee428903b 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ /* Begin PBXBuildFile section */ 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; + 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; 007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; platformFilters = (macos, ); }; 007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; platformFilters = (ios, maccatalyst, macos, ); }; 00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; platformFilters = (macos, ); }; @@ -476,6 +477,8 @@ F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E72933074E00816151 /* SDL_begin_code.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E52933074E00816151 /* SDL_system.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E82933074E00816151 /* SDL_system.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; + 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */; }; + 0000C3B22D46279F99170000 /* SDL_main_callbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 00003260407E1002EAC10000 /* SDL_main_callbacks.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -504,6 +507,7 @@ /* Begin PBXFileReference section */ 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hashtable.c; sourceTree = ""; }; 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hashtable.h; sourceTree = ""; }; + 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_sysmain_callbacks.m; sourceTree = ""; }; 0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; @@ -977,6 +981,8 @@ F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; }; F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; }; FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; + 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_main_callbacks.c; path = SDL_main_callbacks.c; sourceTree = ""; }; + 00003260407E1002EAC10000 /* SDL_main_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_main_callbacks.h; path = SDL_main_callbacks.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1002,6 +1008,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 000082EF09C89B62BD840000 /* main */ = { + isa = PBXGroup; + children = ( + 00008B5A0CB83D2069E80000 /* ios */, + 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */, + 00003260407E1002EAC10000 /* SDL_main_callbacks.h */, + ); + path = main; + sourceTree = ""; + }; + 00008B5A0CB83D2069E80000 /* ios */ = { + isa = PBXGroup; + children = ( + 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */, + ); + path = ios; + sourceTree = ""; + }; 0153844A006D81B07F000001 /* Public Headers */ = { isa = PBXGroup; children = ( @@ -1122,6 +1146,7 @@ A7D8A91123E2514000DCD162 /* libm */, A7D8A85D23E2513F00DCD162 /* loadso */, 566E26CB246274AE00718109 /* locale */, + 000082EF09C89B62BD840000 /* main */, 5616CA47252BB278005D5928 /* misc */, A7D8A7DF23E2513F00DCD162 /* power */, A7D8A8DA23E2514000DCD162 /* render */, @@ -2614,6 +2639,8 @@ A7D8AB6123E2514100DCD162 /* SDL_offscreenwindow.c in Sources */, 566E26D8246274CC00718109 /* SDL_locale.c in Sources */, 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */, + 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */, + 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 01193b0cd905f..2af3c88fff89e 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2531,6 +2531,22 @@ extern "C" { */ #define SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" + +/** + * Request SDL_AppIterate() be called at a specific rate. + * + * This number is in Hz, so "60" means try to iterate 60 times per second. + * + * On some platforms, or if you are using SDL_main instead of SDL_AppIterate, + * this hint is ignored. When the hint can be used, it is allowed to be + * changed at any time. + * + * This defaults to 60, and specifying NULL for the hint's value will restore + * the default. + */ +#define SDL_HINT_MAIN_CALLBACK_RATE "SDL_MAIN_CALLBACK_RATE" + + /** * \brief An enumeration of hint priorities */ diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 6181c0c010696..1833fa73f2f7c 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -140,7 +140,7 @@ * \endcode */ -#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) +#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) || defined(SDL_MAIN_USE_CALLBACKS) #define main SDL_main #endif @@ -149,11 +149,199 @@ extern "C" { #endif +union SDL_Event; +typedef int (SDLCALL *SDL_AppInit_func)(int argc, char *argv[]); +typedef int (SDLCALL *SDL_AppIterate_func)(void); +typedef int (SDLCALL *SDL_AppEvent_func)(const union SDL_Event *event); +typedef void (SDLCALL *SDL_AppQuit_func)(void); + +/** + * You can (optionally!) define SDL_MAIN_USE_CALLBACKS before including + * SDL_main.h, and then your application will _not_ have a standard + * "main" entry point. Instead, it will operate as a collection of + * functions that are called as necessary by the system. On some + * platforms, this is just a layer where SDL drives your program + * instead of your program driving SDL, on other platforms this might + * hook into the OS to manage the lifecycle. Programs on most platforms + * can use whichever approach they prefer, but the decision boils down + * to: + * + * - Using a standard "main" function: this works like it always has for + * the past 50+ years in C programming, and your app is in control. + * - Using the callback functions: this might clean up some code, + * avoid some #ifdef blocks in your program for some platforms, be more + * resource-friendly to the system, and possibly be the primary way to + * access some future platforms (but none require this at the moment). + * + * This is up to the app; both approaches are considered valid and supported + * ways to write SDL apps. + * + * If using the callbacks, don't define a "main" function. Instead, implement + * the functions listed below in your program. + */ +#ifdef SDL_MAIN_USE_CALLBACKS + +/** + * App-implemented initial entry point for SDL_MAIN_USE_CALLBACKS apps. + * + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If + * using a standard "main" function, you should not supply this. + * + * This function is called by SDL once, at startup. The function should + * initialize whatever is necessary, possibly create windows and open + * audio devices, etc. The `argc` and `argv` parameters work like they would + * with a standard "main" function. + * + * This function should not go into an infinite mainloop; it should do any + * one-time setup it requires and then return. + * + * If this function returns 0, the app will proceed to normal operation, + * and will begin receiving repeated calls to SDL_AppIterate and SDL_AppEvent + * for the life of the program. If this function returns < 0, SDL will + * call SDL_AppQuit and terminate the process with an exit code that reports + * an error to the platform. If it returns > 0, the SDL calls SDL_AppQuit + * and terminates with an exit code that reports success to the platform. + * + * \param argc The standard ANSI C main's argc; number of elements in `argv` + * \param argv The standard ANSI C main's argv; array of command line arguments. + * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AppIterate + * \sa SDL_AppEvent + * \sa SDL_AppQuit + */ +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(int argc, char *argv[]); + +/** + * App-implemented iteration entry point for SDL_MAIN_USE_CALLBACKS apps. + * + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If + * using a standard "main" function, you should not supply this. + * + * This function is called repeatedly by SDL after SDL_AppInit returns 0. + * The function should operate as a single iteration the program's primary + * loop; it should update whatever state it needs and draw a new frame of + * video, usually. + * + * On some platforms, this function will be called at the refresh rate of + * the display (which might change during the life of your app!). There are + * no promises made about what frequency this function might run at. You + * should use SDL's timer functions if you need to see how much time has + * passed since the last iteration. + * + * There is no need to process the SDL event queue during this function; + * SDL will send events as they arrive in SDL_AppEvent, and in most cases + * the event queue will be empty when this function runs anyhow. + * + * This function should not go into an infinite mainloop; it should do one + * iteration of whatever the program does and return. + * + * If this function returns 0, the app will continue normal operation, + * receiving repeated calls to SDL_AppIterate and SDL_AppEvent for the life + * of the program. If this function returns < 0, SDL will call SDL_AppQuit + * and terminate the process with an exit code that reports an error to the + * platform. If it returns > 0, the SDL calls SDL_AppQuit and terminates with + * an exit code that reports success to the platform. + * + * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AppInit + * \sa SDL_AppEvent + * \sa SDL_AppQuit + */ +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void); + +/** + * App-implemented event entry point for SDL_MAIN_USE_CALLBACKS apps. + * + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If + * using a standard "main" function, you should not supply this. + * + * This function is called as needed by SDL after SDL_AppInit returns 0; + * It is called once for each new event. + * + * There is (currently) no guarantee about what thread this will be called + * from; whatever thread pushes an event onto SDL's queue will trigger this + * function. SDL is responsible for pumping the event queue between + * each call to SDL_AppIterate, so in normal operation one should only + * get events in a serial fashion, but be careful if you have a thread that + * explicitly calls SDL_PushEvent. + * + * Events sent to this function are not owned by the app; if you need to + * save the data, you should copy it. + * + * You do not need to free event data (such as the `file` string in + * SDL_EVENT_DROP_FILE), as SDL will free it once this function returns. + * Note that this is different than one might expect when using a standard + * "main" function! + * + * This function should not go into an infinite mainloop; it should handle + * the provided event appropriately and return. + * + * If this function returns 0, the app will continue normal operation, + * receiving repeated calls to SDL_AppIterate and SDL_AppEvent for the life + * of the program. If this function returns < 0, SDL will call SDL_AppQuit + * and terminate the process with an exit code that reports an error to the + * platform. If it returns > 0, the SDL calls SDL_AppQuit and terminates with + * an exit code that reports success to the platform. + * + * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AppInit + * \sa SDL_AppIterate + * \sa SDL_AppQuit + */ +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(const SDL_Event *event); + +/** + * App-implemented deinit entry point for SDL_MAIN_USE_CALLBACKS apps. + * + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If + * using a standard "main" function, you should not supply this. + * + * This function is called once by SDL before terminating the program. + * + * This function will be called no matter what, even if SDL_AppInit + * requests termination. + * + * This function should not go into an infinite mainloop; it should + * deinitialize any resources necessary, perform whatever shutdown + * activities, and return. + * + * You do not need to call SDL_Quit() in this function, as SDL will call + * it after this function returns and before the process terminates, but + * it is safe to do so. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AppInit + * \sa SDL_AppIterate + * \sa SDL_AppEvent + */ +extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void); + +#endif /* SDL_MAIN_USE_CALLBACKS */ + + /** * The prototype for the application's main() function */ -typedef int (*SDL_main_func)(int argc, char *argv[]); -extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); +typedef int (SDLCALL *SDL_main_func)(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDLCALL SDL_main(int argc, char *argv[]); /** @@ -198,6 +386,33 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void); */ extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved); +/** + * An entry point for SDL's use in SDL_MAIN_USE_CALLBACKS. + * + * Generally, you should not call this function directly. This only exists + * to hand off work into SDL as soon as possible, where it has a lot more + * control and functionality available, and make the inline code in + * SDL_main.h as small as possible. + * + * Not all platforms use this, it's actual use is hidden in a magic + * header-only library, and you should not call this directly unless you + * _really_ know what you're doing. + * + * \param argc standard Unix main argc + * \param argv standard Unix main argv + * \param appinit The application's SDL_AppInit function + * \param appiter The application's SDL_AppIterate function + * \param appevent The application's SDL_AppEvent function + * \param appquit The application's SDL_AppQuit function + * \returns standard Unix main return value + * + * \threadsafety It is not safe to call this anywhere except as the only function call in SDL_main. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); + + #if defined(__WIN32__) || defined(__GDK__) /** @@ -282,7 +497,8 @@ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #if !defined(SDL_MAIN_HANDLED) && !defined(SDL_MAIN_NOIMPL) /* include header-only SDL_main implementations */ -#if defined(__WIN32__) || defined(__GDK__) || defined(__IOS__) || defined(__TVOS__) \ +#if defined(SDL_MAIN_USE_CALLBACKS) \ + || defined(__WIN32__) || defined(__GDK__) || defined(__IOS__) || defined(__TVOS__) \ || defined(__3DS__) || defined(__NGAGE__) || defined(__PS2__) || defined(__PSP__) /* platforms which main (-equivalent) can be implemented in plain C */ diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index 6b73bbb3f6d7b..dd35dbd52c0a3 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -41,6 +41,30 @@ # undef main #endif /* main */ +#ifdef SDL_MAIN_USE_CALLBACKS + +#if 0 + /* currently there are no platforms that _need_ a magic entry point here + for callbacks, but if one shows up, implement it here. */ + +#else /* use a standard SDL_main, which the app SHOULD NOT ALSO SUPPLY. */ + +/* this define makes the normal SDL_main entry point stuff work...we just provide SDL_main() instead of the app. */ +#define SDL_MAIN_CALLBACK_STANDARD 1 + +int SDL_main(int argc, char **argv) +{ + return SDL_EnterAppMainCallbacks(argc, argv, SDL_AppInit, SDL_AppIterate, SDL_AppEvent, SDL_AppQuit); +} + +#endif /* platform-specific tests */ + +#endif /* SDL_MAIN_USE_CALLBACKS */ + + +/* set up the usual SDL_main stuff if we're not using callbacks or if we are but need the normal entry point. */ +#if !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) + #if defined(__WIN32__) || defined(__GDK__) /* these defines/typedefs are needed for the WinMain() definition */ @@ -193,6 +217,8 @@ int main(int argc, char *argv[]) #endif /* __WIN32__ etc */ +#endif /* !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) */ + /* rename users main() function to SDL_main() so it can be called from the wrappers above */ #define main SDL_main diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index f2d66e51e77fc..f194a42b5c392 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -201,15 +201,27 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state); SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **argv); /** - * \brief Common event handler for test windows. + * Common event handler for test windows if you use a standard SDL_main. + * + * This will free data from the event, like the string in a drop event! * * \param state The common state used to create test window. * \param event The event to handle. * \param done Flag indicating we are done. - * */ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done); +/** + * Common event handler for test windows if you use SDL_AppEvent. + * + * This does _not_ free anything in `event`. + * + * \param state The common state used to create test window. + * \param event The event to handle. + * \returns Value suitable for returning from SDL_AppEvent(). + */ +int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event); + /** * \brief Close test window. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index c53c02adc6cd8..6ee8a813a9791 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -920,6 +920,7 @@ SDL3_0.0.0 { SDL_GetSurfaceProperties; SDL_GetWindowProperties; SDL_ClearProperty; + SDL_EnterAppMainCallbacks; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index dc85966627dd4..09c6dbbd45712 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -945,3 +945,4 @@ #define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL #define SDL_ClearProperty SDL_ClearProperty_REAL +#define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index ac41615e9de1f..868a35ec9d145 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -977,3 +977,4 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSensorProperties,(SDL_Sensor *a),(a),ret SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c new file mode 100644 index 0000000000000..5d880066df243 --- /dev/null +++ b/src/main/SDL_main_callbacks.c @@ -0,0 +1,114 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" +#include "SDL_main_callbacks.h" + +static SDL_AppEvent_func SDL_main_event_callback; +static SDL_AppIterate_func SDL_main_iteration_callback; +static SDL_AppQuit_func SDL_main_quit_callback; +static SDL_AtomicInt apprc; // use an atomic, since events might land from any thread and we don't want to wrap this all in a mutex. A CAS makes sure we only move from zero once. + +static int SDLCALL EventWatcher(void *userdata, SDL_Event *event) +{ + if (SDL_AtomicGet(&apprc) == 0) { // if already quitting, don't send the event to the app. + SDL_AtomicCAS(&apprc, 0, SDL_main_event_callback(event)); + } + return 0; +} + +int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) +{ + SDL_main_iteration_callback = appiter; + SDL_main_event_callback = appevent; + SDL_main_quit_callback = appquit; + SDL_AtomicSet(&apprc, 0); + + const int rc = appinit(argc, argv); + if (SDL_AtomicCAS(&apprc, 0, rc) && (rc == 0)) { // bounce if SDL_AppInit already said abort, otherwise... + // make sure we definitely have events initialized, even if the app didn't do it. + if (SDL_InitSubSystem(SDL_INIT_EVENTS) == -1) { + SDL_AtomicSet(&apprc, -1); + return -1; + } + + // drain any initial events that might have arrived before we added a watcher. + SDL_Event event; + SDL_Event *pending_events = NULL; + int total_pending_events = 0; + while (SDL_PollEvent(&event)) { + void *ptr = SDL_realloc(pending_events, sizeof (SDL_Event) * (total_pending_events + 1)); + if (!ptr) { + SDL_OutOfMemory(); + SDL_free(pending_events); + SDL_AtomicSet(&apprc, -1); + return -1; + } + pending_events = (SDL_Event *) ptr; + SDL_copyp(&pending_events[total_pending_events], &event); + total_pending_events++; + } + + SDL_AddEventWatch(EventWatcher, NULL); // !!! FIXME: this should really return an error. + + for (int i = 0; i < total_pending_events; i++) { + SDL_PushEvent(&pending_events[i]); + } + + SDL_free(pending_events); + } + + return SDL_AtomicGet(&apprc); +} + +int SDL_IterateMainCallbacks(void) +{ + SDL_Event event; + SDL_PumpEvents(); + while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) == 1) { + // just empty the queue, EventWatcher sends the events to the app. + switch (event.type) { + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + SDL_free(event.drop.file); + break; + } + } + + int rc = SDL_main_iteration_callback(); + if (!SDL_AtomicCAS(&apprc, 0, rc)) { + rc = SDL_AtomicGet(&apprc); // something else already set a quit result, keep that. + } + + return rc; +} + +void SDL_QuitMainCallbacks(void) +{ + SDL_DelEventWatch(EventWatcher, NULL); + SDL_main_quit_callback(); + + // for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow. + //SDL_QuitSubSystem(SDL_INIT_EVENTS); + + SDL_Quit(); +} + diff --git a/src/main/SDL_main_callbacks.h b/src/main/SDL_main_callbacks.h new file mode 100644 index 0000000000000..9df171a99c13b --- /dev/null +++ b/src/main/SDL_main_callbacks.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_main_callbacks_h_ +#define SDL_main_callbacks_h_ + +int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit); +int SDL_IterateMainCallbacks(void); +void SDL_QuitMainCallbacks(void); + +#endif // SDL_main_callbacks_h_ + + diff --git a/src/main/emscripten/SDL_sysmain_callbacks.c b/src/main/emscripten/SDL_sysmain_callbacks.c new file mode 100644 index 0000000000000..fc6f53e6c7d3f --- /dev/null +++ b/src/main/emscripten/SDL_sysmain_callbacks.c @@ -0,0 +1,47 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" +#include "../SDL_main_callbacks.h" + +#include + +static void EmscriptenInternalMainloop(void) +{ + const int rc = SDL_IterateMainCallbacks(); + if (rc != 0) { + SDL_QuitMainCallbacks(); + emscripten_cancel_main_loop(); // kill" the mainloop, so it stops calling back into it. + exit((rc < 0) ? 1 : 0); // hopefully this takes down everything else, too. + } +} + +int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) +{ + const int rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit); + if (rc == 0) { + emscripten_set_main_loop(EmscriptenInternalMainloop, 0, 0); // run at refresh rate, don't throw an exception since we do an orderly return. + } else { + SDL_QuitMainCallbacks(); + } + return (rc < 0) ? 1 : 0; +} + diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c new file mode 100644 index 0000000000000..3e47264e3e6f3 --- /dev/null +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -0,0 +1,80 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" +#include "../SDL_main_callbacks.h" +#include "../../video/SDL_sysvideo.h" + +static int callback_rate_increment = 0; + +static void SDLCALL MainCallbackRateHintChanged(void *userdata, const char *name, const char *oldValue, const char *newValue) +{ + const int callback_rate = newValue ? SDL_atoi(newValue) : 60; + if (callback_rate > 0) { + callback_rate_increment = ((Uint64) 1000000000) / ((Uint64) callback_rate); + } else { + callback_rate_increment = 0; + } +} + +int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) +{ + int rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit); + + SDL_AddHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); + + Uint64 next_iteration = callback_rate_increment ? (SDL_GetTicksNS() + callback_rate_increment) : 0; + + while ((rc = SDL_IterateMainCallbacks()) == 0) { + // !!! FIXME: this can be made more complicated if we decide to + // !!! FIXME: optionally hand off callback responsibility to the + // !!! FIXME: video subsystem (for example, if Wayland has a + // !!! FIXME: protocol to drive an animation loop, maybe we hand + // !!! FIXME: off to them here if/when the video subsystem becomes + // !!! FIXME: initialized). + + // !!! FIXME: maybe respect this hint even if there _is_ a window. + // if there's no window, try to run at about 60fps (or whatever rate + // the hint requested). This makes this not eat all the CPU in + // simple things like loopwave. If there's a window, we run as fast + // as possible, which means we'll clamp to vsync in common cases, + // and won't be restrained to vsync if the app is doing a benchmark + // or doesn't want to be, based on how they've set up that window. + if ((callback_rate_increment == 0) || SDL_HasWindows()) { + next_iteration = 0; // just clear the timer and run at the pace the video subsystem allows. + } else { + const Uint64 now = SDL_GetTicksNS(); + if (next_iteration > now) { // Running faster than the limit, sleep a little. + SDL_DelayNS(next_iteration - now); + } else { + next_iteration = now; // running behind (or just lost the window)...reset the timer. + } + next_iteration += callback_rate_increment; + } + } + + SDL_DelHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); + + SDL_QuitMainCallbacks(); + + return (rc < 0) ? 1 : 0; +} + diff --git a/src/main/ios/SDL_sysmain_callbacks.m b/src/main/ios/SDL_sysmain_callbacks.m new file mode 100644 index 0000000000000..63722630f04e0 --- /dev/null +++ b/src/main/ios/SDL_sysmain_callbacks.m @@ -0,0 +1,82 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" +#include "../SDL_main_callbacks.h" + +#ifdef __IOS__ + +#import + +@interface SDLIosMainCallbacksDisplayLink : NSObject +@property(nonatomic, retain) CADisplayLink *displayLink; +- (void)appIteration:(CADisplayLink *)sender; +- (instancetype)init:(SDL_AppIterate_func)_appiter quitfunc:(SDL_AppQuit_func)_appquit; +@end + +static SDLIosMainCallbacksDisplayLink *globalDisplayLink; + +@implementation SDLIosMainCallbacksDisplayLink + +- (instancetype)init:(SDL_AppIterate_func)_appiter quitfunc:(SDL_AppQuit_func)_appquit; +{ + if ((self = [super init])) { + self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(appIteration:)]; + [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + } + return self; +} + +- (void)appIteration:(CADisplayLink *)sender +{ + const int rc = SDL_IterateMainCallbacks(); + if (rc != 0) { + [self.displayLink invalidate]; + self.displayLink = nil; + globalDisplayLink = nil; + SDL_QuitMainCallbacks(); + exit((rc < 0) ? 1 : 0); + } +} +@end + +// SDL_RunApp will land in UIApplicationMain, which calls SDL_main from postFinishLaunch, which calls this. +// When we return from here, we're living in the RunLoop, and a CADisplayLink is firing regularly for us. +int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) +{ + const int rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit); + if (rc == 0) { + globalDisplayLink = [[SDLIosMainCallbacksDisplayLink alloc] init:appiter quitfunc:appquit]; + if (globalDisplayLink != nil) { + return 0; // this will fall all the way out of SDL_main, where UIApplicationMain will keep running the RunLoop. + } + } + + // appinit requested quit, just bounce out now. + SDL_QuitMainCallbacks(); + exit((rc < 0) ? 1 : 0); + + return 1; // just in case. +} + +#endif + + diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index e4b62709b9655..f18e940280474 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1560,7 +1560,7 @@ static const char *GamepadButtonName(const SDL_GamepadButton button) } } -static void SDLTest_PrintEvent(SDL_Event *event) +static void SDLTest_PrintEvent(const SDL_Event *event) { switch (event->type) { case SDL_EVENT_SYSTEM_THEME_CHANGED: @@ -2029,7 +2029,7 @@ static void FullscreenTo(SDLTest_CommonState *state, int index, int windowId) SDL_free(displays); } -void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done) +int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event) { int i; @@ -2408,20 +2408,27 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done } break; case SDLK_ESCAPE: - *done = 1; - break; + return 1; default: break; } break; } case SDL_EVENT_QUIT: - *done = 1; - break; + return 1; + } + return 0; /* keep going */ +} + +void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done) +{ + *done = SDLTest_CommonEventMainCallbacks(state, event) ? 1 : 0; + + switch (event->type) { case SDL_EVENT_DROP_FILE: case SDL_EVENT_DROP_TEXT: - SDL_free(event->drop.file); + SDL_free(event->drop.file); // SDL frees these if you use SDL_AppEvent, not us, so explicitly handle it here. break; } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4ce431e73feeb..ee4251a478f21 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -47,11 +47,16 @@ if(WINDOWS_STORE) target_link_libraries(sdl_test_main_uwp PRIVATE SDL3::Headers) target_compile_options(sdl_test_main_uwp PRIVATE "/ZW") + add_library(sdl_test_main_callbacks_uwp OBJECT main.cpp) + target_link_libraries(sdl_test_main_callbacks_uwp PRIVATE SDL3::Headers) + target_compile_options(sdl_test_main_callbacks_uwp PRIVATE "/ZW") + target_compile_definitions(sdl_test_main_callbacks_uwp PRIVATE "SDL_MAIN_USE_CALLBACKS") + set_source_files_properties(${RESOURCE_FILES} PROPERTIES VS_DEPLOYENT_LOCATION "Assets") endif() macro(add_sdl_test_executable TARGET) - cmake_parse_arguments(AST "BUILD_DEPENDENT;NONINTERACTIVE;NEEDS_RESOURCES;TESTUTILS;NO_C90" "" "NONINTERACTIVE_TIMEOUT;NONINTERACTIVE_ARGS;SOURCES" ${ARGN}) + cmake_parse_arguments(AST "BUILD_DEPENDENT;NONINTERACTIVE;NEEDS_RESOURCES;TESTUTILS;NO_C90;MAIN_CALLBACKS" "" "NONINTERACTIVE_TIMEOUT;NONINTERACTIVE_ARGS;SOURCES" ${ARGN}) if(AST_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}") endif() @@ -73,8 +78,14 @@ macro(add_sdl_test_executable TARGET) TARGET "${TARGET}" ) set_property(SOURCE "${uwp_bindir}/${TARGET}.appxmanifest" PROPERTY VS_DEPLOYMENT_CONTENT 1) + + if(AST_MAIN_CALLBACKS) + list(APPEND EXTRA_SOURCES "$") + else() + list(APPEND EXTRA_SOURCES "$") + endif() + list(APPEND EXTRA_SOURCES - "$" "${uwp_bindir}/${TARGET}.appxmanifest" "uwp/logo-50x50.png" "uwp/square-44x44.png" @@ -213,7 +224,7 @@ endif() add_sdl_test_executable(checkkeys SOURCES checkkeys.c) add_sdl_test_executable(checkkeysthreads SOURCES checkkeysthreads.c) -add_sdl_test_executable(loopwave NEEDS_RESOURCES TESTUTILS SOURCES loopwave.c) +add_sdl_test_executable(loopwave NEEDS_RESOURCES TESTUTILS MAIN_CALLBACKS SOURCES loopwave.c) add_sdl_test_executable(testsurround SOURCES testsurround.c) add_sdl_test_executable(testresample NEEDS_RESOURCES SOURCES testresample.c) add_sdl_test_executable(testaudioinfo SOURCES testaudioinfo.c) @@ -223,7 +234,7 @@ file(GLOB TESTAUTOMATION_SOURCE_FILES testautomation*.c) add_sdl_test_executable(testautomation NONINTERACTIVE NONINTERACTIVE_TIMEOUT 120 NEEDS_RESOURCES NO_C90 SOURCES ${TESTAUTOMATION_SOURCE_FILES}) add_sdl_test_executable(testmultiaudio NEEDS_RESOURCES TESTUTILS SOURCES testmultiaudio.c) add_sdl_test_executable(testaudiohotplug NEEDS_RESOURCES TESTUTILS SOURCES testaudiohotplug.c) -add_sdl_test_executable(testaudiocapture SOURCES testaudiocapture.c) +add_sdl_test_executable(testaudiocapture MAIN_CALLBACKS SOURCES testaudiocapture.c) add_sdl_test_executable(testatomic NONINTERACTIVE SOURCES testatomic.c) add_sdl_test_executable(testintersections SOURCES testintersections.c) add_sdl_test_executable(testrelative SOURCES testrelative.c) @@ -304,7 +315,7 @@ files2headers(gamepad_image_headers ) files2headers(icon_bmp_header icon.bmp) -add_sdl_test_executable(testaudio NEEDS_RESOURCES TESTUTILS SOURCES testaudio.c) +add_sdl_test_executable(testaudio MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testaudio.c) add_sdl_test_executable(testfile NONINTERACTIVE SOURCES testfile.c) add_sdl_test_executable(testcontroller TESTUTILS SOURCES testcontroller.c gamepadutils.c ${gamepad_image_headers}) add_sdl_test_executable(testgeometry TESTUTILS SOURCES testgeometry.c) @@ -341,7 +352,7 @@ add_sdl_test_executable(testsem NONINTERACTIVE NONINTERACTIVE_ARGS 10 NONINTERAC add_sdl_test_executable(testsensor SOURCES testsensor.c) add_sdl_test_executable(testshader NEEDS_RESOURCES TESTUTILS SOURCES testshader.c) add_sdl_test_executable(testshape NEEDS_RESOURCES SOURCES testshape.c) -add_sdl_test_executable(testsprite NEEDS_RESOURCES TESTUTILS SOURCES testsprite.c) +add_sdl_test_executable(testsprite MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testsprite.c) add_sdl_test_executable(testspriteminimal SOURCES testspriteminimal.c ${icon_bmp_header}) add_sdl_test_executable(teststreaming NEEDS_RESOURCES TESTUTILS SOURCES teststreaming.c) add_sdl_test_executable(testtimer NONINTERACTIVE NONINTERACTIVE_ARGS --no-interactive NONINTERACTIVE_TIMEOUT 60 SOURCES testtimer.c) diff --git a/test/loopwave.c b/test/loopwave.c index 1fa1b91e1a9d6..877fe8f3918ca 100644 --- a/test/loopwave.c +++ b/test/loopwave.c @@ -17,10 +17,7 @@ */ #include -#ifdef __EMSCRIPTEN__ -#include -#endif - +#define SDL_MAIN_USE_CALLBACKS 1 #include #include #include @@ -34,68 +31,24 @@ static struct } wave; static SDL_AudioStream *stream; +static SDLTest_CommonState *state; -static void fillerup(void) +static int fillerup(void) { const int minimum = (wave.soundlen / SDL_AUDIO_FRAMESIZE(wave.spec)) / 2; if (SDL_GetAudioStreamQueued(stream) < minimum) { SDL_PutAudioStreamData(stream, wave.sound, wave.soundlen); } + return 0; } -/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ -static void -quit(int rc) -{ - SDL_Quit(); - /* Let 'main()' return normally */ - if (rc != 0) { - exit(rc); - } -} - -static void -close_audio(void) -{ - if (stream) { - SDL_DestroyAudioStream(stream); - stream = NULL; - } -} - -static void -open_audio(void) -{ - stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); - if (!stream) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); - SDL_free(wave.sound); - quit(2); - } - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); -} - - -static int done = 0; - - - -#ifdef __EMSCRIPTEN__ -static void loop(void) -{ - if (done) { - emscripten_cancel_main_loop(); - } else { - fillerup(); - } -} -#endif - -int main(int argc, char *argv[]) +int SDL_AppInit(int argc, char *argv[]) { int i; char *filename = NULL; - SDLTest_CommonState *state; + + /* this doesn't have to run very much, so give up tons of CPU time between iterations. */ + SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5"); /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); @@ -129,22 +82,25 @@ int main(int argc, char *argv[]) /* Load the SDL library */ if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); - return 1; + return -1; } filename = GetResourceFilename(filename, "sample.wav"); if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); - quit(1); + return -1; } /* Load the wave file into memory */ if (SDL_LoadWAV(filename, &wave.spec, &wave.sound, &wave.soundlen) == -1) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); - quit(1); + SDL_free(filename); + return -1; } + SDL_free(filename); + /* Show the list of available drivers */ SDL_Log("Available audio drivers:"); for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { @@ -153,30 +109,30 @@ int main(int argc, char *argv[]) SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); - open_audio(); + stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); + if (!stream) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); + return -1; + } + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); -#ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(loop, 0, 1); -#else - while (!done) { - SDL_Event event; + return 0; +} - while (SDL_PollEvent(&event) > 0) { - if (event.type == SDL_EVENT_QUIT) { - done = 1; - } - } +int SDL_AppEvent(const SDL_Event *event) +{ + return (event->type == SDL_EVENT_QUIT) ? 1 : 0; +} - fillerup(); - SDL_Delay(100); - } -#endif +int SDL_AppIterate(void) +{ + return fillerup(); +} - /* Clean up on signal */ - close_audio(); +void SDL_AppQuit(void) +{ + SDL_DestroyAudioStream(stream); SDL_free(wave.sound); - SDL_free(filename); - SDL_Quit(); SDLTest_CommonDestroyState(state); - return 0; } + diff --git a/test/testaudio.c b/test/testaudio.c index e77901c94e72c..d7b8b56aebd8c 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -1,9 +1,4 @@ -#include - -#ifdef __EMSCRIPTEN__ -#include -#endif - +#define SDL_MAIN_USE_CALLBACKS 1 #include #include #include @@ -103,7 +98,6 @@ struct Thing static Uint64 app_ready_ticks = 0; -static int done = 0; static SDLTest_CommonState *state = NULL; static Thing *things = NULL; @@ -124,51 +118,6 @@ static Texture *trashcan_texture = NULL; static Texture *soundboard_texture = NULL; static Texture *soundboard_levels_texture = NULL; -static void DestroyTexture(Texture *tex); -static void DestroyThing(Thing *thing); - - -/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ -static void Quit(int rc) -{ - while (things != NULL) { - DestroyThing(things); /* make sure all the audio devices are closed, etc. */ - } - - DestroyTexture(physdev_texture); - DestroyTexture(logdev_texture); - DestroyTexture(audio_texture); - DestroyTexture(trashcan_texture); - DestroyTexture(soundboard_texture); - DestroyTexture(soundboard_levels_texture); - SDLTest_CommonQuit(state); - - /* Let 'main()' return normally */ - if (rc != 0) { - exit(rc); - } -} - -static char *xstrdup(const char *str) -{ - char *ptr = SDL_strdup(str); - if (!ptr) { - SDL_Log("Out of memory!"); - Quit(1); - } - return ptr; -} - -static void *xalloc(const size_t len) -{ - void *ptr = SDL_calloc(1, len); - if (!ptr) { - SDL_Log("Out of memory!"); - Quit(1); - } - return ptr; -} - static void SetTitleBar(const char *fmt, ...) { @@ -232,7 +181,12 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl Thing *i; Thing *thing; - thing = (Thing *) xalloc(sizeof (Thing)); + thing = (Thing *) SDL_calloc(1, sizeof (Thing)); + if (!thing) { + SDL_Log("Out of memory!"); + return NULL; + } + if ((w < 0) || (h < 0)) { SDL_assert(texture != NULL); if (w < 0) { @@ -256,7 +210,7 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl thing->scale = 1.0f; thing->createticks = SDL_GetTicks(); thing->texture = texture; - thing->titlebar = titlebar ? xstrdup(titlebar) : NULL; + thing->titlebar = titlebar ? SDL_strdup(titlebar) : NULL; /* if allocation fails, oh well. */ /* insert in list by Z order (furthest from the "camera" first, so they get drawn over; negative Z is not drawn at all). */ if (things == NULL) { @@ -515,12 +469,14 @@ static Thing *CreatePoofThing(Thing *poofing_thing) const float centery = poofing_thing->rect.y + (poofing_thing->rect.h / 2); const float z = poofing_thing->z; Thing *thing = CreateThing(THING_POOF, poofing_thing->rect.x, poofing_thing->rect.y, z, poofing_thing->rect.w, poofing_thing->rect.h, poofing_thing->texture, NULL); - thing->data.poof.startw = poofing_thing->rect.w; - thing->data.poof.starth = poofing_thing->rect.h; - thing->data.poof.centerx = centerx; - thing->data.poof.centery = centery; - thing->ontick = PoofThing_ontick; - thing->ondrag = PoofThing_ondrag; + if (thing) { + thing->data.poof.startw = poofing_thing->rect.w; + thing->data.poof.starth = poofing_thing->rect.h; + thing->data.poof.centerx = centerx; + thing->data.poof.centery = centery; + thing->ontick = PoofThing_ontick; + thing->ondrag = PoofThing_ondrag; + } return thing; } @@ -638,18 +594,20 @@ static Thing *CreateStreamThing(const SDL_AudioSpec *spec, const Uint8 *buf, con { static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_LOGDEV, THING_LOGDEV_CAPTURE, THING_NULL }; Thing *thing = CreateThing(THING_STREAM, x, y, 0, -1, -1, soundboard_texture, fname); - SDL_Log("Adding audio stream for %s", fname ? fname : "(null)"); - thing->data.stream.stream = SDL_CreateAudioStream(spec, spec); - if (buf && buflen) { - SDL_PutAudioStreamData(thing->data.stream.stream, buf, (int) buflen); - SDL_FlushAudioStream(thing->data.stream.stream); - thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream); - } - thing->ontick = StreamThing_ontick; - thing->ondrag = StreamThing_ondrag; - thing->ondrop = StreamThing_ondrop; - thing->ondraw = StreamThing_ondraw; - thing->can_be_dropped_onto = can_be_dropped_onto; + if (thing) { + SDL_Log("Adding audio stream for %s", fname ? fname : "(null)"); + thing->data.stream.stream = SDL_CreateAudioStream(spec, spec); + if (buf && buflen) { + SDL_PutAudioStreamData(thing->data.stream.stream, buf, (int) buflen); + SDL_FlushAudioStream(thing->data.stream.stream); + thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream); + } + thing->ontick = StreamThing_ontick; + thing->ondrag = StreamThing_ondrag; + thing->ondrop = StreamThing_ondrop; + thing->ondraw = StreamThing_ondraw; + thing->can_be_dropped_onto = can_be_dropped_onto; + } return thing; } @@ -703,13 +661,15 @@ static Thing *LoadWavThing(const char *fname, float x, float y) SDL_asprintf(&titlebar, "WAV file (\"%s\", %s, %s, %uHz)", nodirs, AudioFmtToString(spec.format), AudioChansToStr(spec.channels), (unsigned int) spec.freq); thing = CreateThing(THING_WAV, x - (audio_texture->w / 2), y - (audio_texture->h / 2), 5, -1, -1, audio_texture, titlebar); - SDL_free(titlebar); - SDL_memcpy(&thing->data.wav.spec, &spec, sizeof (SDL_AudioSpec)); - thing->data.wav.buf = buf; - thing->data.wav.buflen = buflen; - thing->can_be_dropped_onto = can_be_dropped_onto; - thing->ondrag = WavThing_ondrag; - thing->ondrop = WavThing_ondrop; + if (thing) { + SDL_free(titlebar); + SDL_memcpy(&thing->data.wav.spec, &spec, sizeof (SDL_AudioSpec)); + thing->data.wav.buf = buf; + thing->data.wav.buflen = buflen; + thing->can_be_dropped_onto = can_be_dropped_onto; + thing->ondrag = WavThing_ondrag; + thing->ondrop = WavThing_ondrop; + } } SDL_free(path); @@ -743,17 +703,21 @@ static void DestroyTexture(Texture *tex) static Texture *CreateTexture(const char *fname) { - Texture *tex = (Texture *) xalloc(sizeof (Texture)); - int texw, texh; - tex->texture = LoadTexture(state->renderers[0], fname, SDL_TRUE, &texw, &texh); - if (!tex->texture) { - SDL_Log("Failed to load '%s': %s", fname, SDL_GetError()); - SDL_free(tex); - Quit(1); + Texture *tex = (Texture *) SDL_calloc(1, sizeof (Texture)); + if (!tex) { + SDL_Log("Out of memory!"); + } else { + int texw, texh; + tex->texture = LoadTexture(state->renderers[0], fname, SDL_TRUE, &texw, &texh); + if (!tex->texture) { + SDL_Log("Failed to load '%s': %s", fname, SDL_GetError()); + SDL_free(tex); + return NULL; + } + SDL_SetTextureBlendMode(tex->texture, SDL_BLENDMODE_BLEND); + tex->w = (float) texw; + tex->h = (float) texh; } - SDL_SetTextureBlendMode(tex->texture, SDL_BLENDMODE_BLEND); - tex->w = (float) texw; - tex->h = (float) texh; return tex; } @@ -763,9 +727,11 @@ static void DeviceThing_ondrag(Thing *thing, int button, float x, float y) { if ((button == SDL_BUTTON_MIDDLE) && (thing->what == THING_LOGDEV_CAPTURE)) { /* drag out a new stream. This is a UX mess. :/ */ dragging_thing = CreateStreamThing(&thing->data.logdev.spec, NULL, 0, NULL, x, y); - dragging_thing->data.stream.next_level_update = SDL_GetTicks() + 100; - SDL_BindAudioStream(thing->data.logdev.devid, dragging_thing->data.stream.stream); /* bind to new device! */ - dragging_thing->line_connected_to = thing; + if (dragging_thing) { + dragging_thing->data.stream.next_level_update = SDL_GetTicks() + 100; + SDL_BindAudioStream(thing->data.logdev.devid, dragging_thing->data.stream.stream); /* bind to new device! */ + dragging_thing->line_connected_to = thing; + } } else if (button == SDL_BUTTON_RIGHT) { /* drag out a new logical device. */ const SDL_AudioDeviceID which = ((thing->what == THING_LOGDEV) || (thing->what == THING_LOGDEV_CAPTURE)) ? thing->data.logdev.devid : thing->data.physdev.devid; const SDL_AudioDeviceID devid = SDL_OpenAudioDevice(which, NULL); @@ -929,22 +895,24 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh SDL_Log("Adding logical audio device %u", (unsigned int) which); thing = CreateThing(iscapture ? THING_LOGDEV_CAPTURE : THING_LOGDEV, x, y, 5, -1, -1, logdev_texture, NULL); - thing->data.logdev.devid = which; - thing->data.logdev.iscapture = iscapture; - thing->data.logdev.physdev = physthing; - thing->data.logdev.visualizer = SDL_CreateTexture(state->renderers[0], SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, VISUALIZER_WIDTH, VISUALIZER_HEIGHT); - thing->data.logdev.postmix_lock = SDL_CreateMutex(); - if (thing->data.logdev.visualizer) { - SDL_SetTextureBlendMode(thing->data.logdev.visualizer, SDL_BLENDMODE_BLEND); - } - thing->line_connected_to = physthing; - thing->ontick = LogicalDeviceThing_ontick; - thing->ondrag = DeviceThing_ondrag; - thing->ondrop = LogicalDeviceThing_ondrop; - thing->ondraw = LogicalDeviceThing_ondraw; - thing->can_be_dropped_onto = can_be_dropped_onto; - - SetLogicalDeviceTitlebar(thing); + if (thing) { + thing->data.logdev.devid = which; + thing->data.logdev.iscapture = iscapture; + thing->data.logdev.physdev = physthing; + thing->data.logdev.visualizer = SDL_CreateTexture(state->renderers[0], SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, VISUALIZER_WIDTH, VISUALIZER_HEIGHT); + thing->data.logdev.postmix_lock = SDL_CreateMutex(); + if (thing->data.logdev.visualizer) { + SDL_SetTextureBlendMode(thing->data.logdev.visualizer, SDL_BLENDMODE_BLEND); + } + thing->line_connected_to = physthing; + thing->ontick = LogicalDeviceThing_ontick; + thing->ondrag = DeviceThing_ondrag; + thing->ondrop = LogicalDeviceThing_ondrop; + thing->ondraw = LogicalDeviceThing_ondraw; + thing->can_be_dropped_onto = can_be_dropped_onto; + + SetLogicalDeviceTitlebar(thing); + } return thing; } @@ -1002,21 +970,23 @@ static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL SDL_Log("Adding physical audio device %u", (unsigned int) which); thing = CreateThing(iscapture ? THING_PHYSDEV_CAPTURE : THING_PHYSDEV, next_physdev_x, 170, 5, -1, -1, physdev_texture, NULL); - thing->data.physdev.devid = which; - thing->data.physdev.iscapture = iscapture; - thing->data.physdev.name = SDL_GetAudioDeviceName(which); - thing->ondrag = DeviceThing_ondrag; - thing->ondrop = PhysicalDeviceThing_ondrop; - thing->ontick = PhysicalDeviceThing_ontick; - thing->can_be_dropped_onto = can_be_dropped_onto; - - SetPhysicalDeviceTitlebar(thing); - if (SDL_GetTicks() <= (app_ready_ticks + 2000)) { /* assume this is the initial batch if it happens in the first two seconds. */ - RepositionRowOfThings(THING_PHYSDEV, 10.0f); /* don't rearrange them after the initial add. */ - RepositionRowOfThings(THING_PHYSDEV_CAPTURE, 170.0f); /* don't rearrange them after the initial add. */ - next_physdev_x = 0.0f; - } else { - next_physdev_x += physdev_texture->w * 1.5f; + if (thing) { + thing->data.physdev.devid = which; + thing->data.physdev.iscapture = iscapture; + thing->data.physdev.name = SDL_GetAudioDeviceName(which); + thing->ondrag = DeviceThing_ondrag; + thing->ondrop = PhysicalDeviceThing_ondrop; + thing->ontick = PhysicalDeviceThing_ontick; + thing->can_be_dropped_onto = can_be_dropped_onto; + + SetPhysicalDeviceTitlebar(thing); + if (SDL_GetTicks() <= (app_ready_ticks + 2000)) { /* assume this is the initial batch if it happens in the first two seconds. */ + RepositionRowOfThings(THING_PHYSDEV, 10.0f); /* don't rearrange them after the initial add. */ + RepositionRowOfThings(THING_PHYSDEV_CAPTURE, 170.0f); /* don't rearrange them after the initial add. */ + next_physdev_x = 0.0f; + } else { + next_physdev_x += physdev_texture->w * 1.5f; + } } return thing; @@ -1066,157 +1036,13 @@ static void WindowResized(const int newwinw, const int newwinh) state->window_h = newwinh; } - -static void Loop(void) -{ - SDL_Event event; - SDL_bool saw_event = SDL_FALSE; - - if (app_ready_ticks == 0) { - app_ready_ticks = SDL_GetTicks(); - } - - while (SDL_PollEvent(&event)) { - Thing *thing = NULL; - - saw_event = SDL_TRUE; - - switch (event.type) { - case SDL_EVENT_MOUSE_MOTION: - thing = UpdateMouseOver(event.motion.x, event.motion.y); - if ((dragging_button == -1) && event.motion.state) { - if (event.motion.state & SDL_BUTTON_LMASK) { - /* for people that don't have all three buttons... */ - if (ctrl_held) { - dragging_button = SDL_BUTTON_RIGHT; - } else if (alt_held) { - dragging_button = SDL_BUTTON_MIDDLE; - } else { - dragging_button = SDL_BUTTON_LEFT; - } - dragging_button_real = SDL_BUTTON_LEFT; - } else if (event.motion.state & SDL_BUTTON_RMASK) { - dragging_button = SDL_BUTTON_RIGHT; - dragging_button_real = SDL_BUTTON_RIGHT; - } else if (event.motion.state & SDL_BUTTON_MMASK) { - dragging_button = SDL_BUTTON_MIDDLE; - dragging_button_real = SDL_BUTTON_MIDDLE; - } - - - if (dragging_button != -1) { - dragging_thing = thing; - if (thing && thing->ondrag) { - thing->ondrag(thing, dragging_button, event.motion.x, event.motion.y); - } - } - } - - droppable_highlighted_thing = NULL; - if (dragging_thing) { - dragging_thing->rect.x = event.motion.x - (dragging_thing->rect.w / 2); - dragging_thing->rect.y = event.motion.y - (dragging_thing->rect.h / 2); - if (dragging_thing->can_be_dropped_onto) { - thing = FindThingAtPoint(event.motion.x, event.motion.y); - if (thing) { - int i; - for (i = 0; dragging_thing->can_be_dropped_onto[i]; i++) { - if (dragging_thing->can_be_dropped_onto[i] == thing->what) { - droppable_highlighted_thing = thing; - break; - } - } - } - } - } - break; - - case SDL_EVENT_MOUSE_BUTTON_DOWN: - thing = UpdateMouseOver(event.button.x, event.button.y); - break; - - case SDL_EVENT_MOUSE_BUTTON_UP: - if (dragging_button_real == event.button.button) { - Thing *dropped_thing = dragging_thing; - dragging_thing = NULL; - dragging_button = -1; - dragging_button_real = -1; - if (dropped_thing && dropped_thing->ondrop) { - dropped_thing->ondrop(dropped_thing, event.button.button, event.button.x, event.button.y); - } - droppable_highlighted_thing = NULL; - } - thing = UpdateMouseOver(event.button.x, event.button.y); - break; - - case SDL_EVENT_MOUSE_WHEEL: - UpdateMouseOver(event.wheel.mouseX, event.wheel.mouseY); - break; - - case SDL_EVENT_KEY_DOWN: - case SDL_EVENT_KEY_UP: - ctrl_held = ((event.key.keysym.mod & SDL_KMOD_CTRL) != 0) ? SDL_TRUE : SDL_FALSE; - alt_held = ((event.key.keysym.mod & SDL_KMOD_ALT) != 0) ? SDL_TRUE : SDL_FALSE; - break; - - case SDL_EVENT_DROP_FILE: - SDL_Log("Drop file! '%s'", event.drop.file); - LoadWavThing(event.drop.file, event.drop.x, event.drop.y); - /* SDLTest_CommonEvent will free the string, below. */ - break; - - case SDL_EVENT_WINDOW_RESIZED: - WindowResized(event.window.data1, event.window.data2); - break; - - case SDL_EVENT_AUDIO_DEVICE_ADDED: - CreatePhysicalDeviceThing(event.adevice.which, event.adevice.iscapture); - break; - - case SDL_EVENT_AUDIO_DEVICE_REMOVED: { - const SDL_AudioDeviceID which = event.adevice.which; - Thing *i, *next; - SDL_Log("Removing audio device %u", (unsigned int) which); - for (i = things; i != NULL; i = next) { - next = i->next; - if (((i->what == THING_PHYSDEV) || (i->what == THING_PHYSDEV_CAPTURE)) && (i->data.physdev.devid == which)) { - TrashThing(i); - next = things; /* in case we mangled the list. */ - } else if (((i->what == THING_LOGDEV) || (i->what == THING_LOGDEV_CAPTURE)) && (i->data.logdev.devid == which)) { - TrashThing(i); - next = things; /* in case we mangled the list. */ - } - } - break; - } - - default: break; - } - - SDLTest_CommonEvent(state, &event, &done); - } - - TickThings(); - Draw(); - - if (!saw_event) { - SDL_Delay(10); - } - - #ifdef __EMSCRIPTEN__ - if (done) { - emscripten_cancel_main_loop(); - } - #endif -} - -int main(int argc, char *argv[]) +int SDL_AppInit(int argc, char *argv[]) { int i; state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO); if (state == NULL) { - Quit(1); + return -1; } state->window_flags |= SDL_WINDOW_RESIZABLE; @@ -1234,13 +1060,13 @@ int main(int argc, char *argv[]) NULL }; SDLTest_CommonLogUsage(state, argv[0], options); - Quit(1); + return -1; } i += consumed; } if (!SDLTest_CommonInit(state)) { - Quit(2); + return -1; } if (state->audio_id) { @@ -1250,27 +1076,174 @@ int main(int argc, char *argv[]) SetDefaultTitleBar(); - physdev_texture = CreateTexture("physaudiodev.bmp"); - logdev_texture = CreateTexture("logaudiodev.bmp"); - audio_texture = CreateTexture("audiofile.bmp"); - trashcan_texture = CreateTexture("trashcan.bmp"); - soundboard_texture = CreateTexture("soundboard.bmp"); - soundboard_levels_texture = CreateTexture("soundboard_levels.bmp"); + if ((physdev_texture = CreateTexture("physaudiodev.bmp")) == NULL) { return -1; } + if ((logdev_texture = CreateTexture("logaudiodev.bmp")) == NULL) { return -1; } + if ((audio_texture = CreateTexture("audiofile.bmp")) == NULL) { return -1; } + if ((trashcan_texture = CreateTexture("trashcan.bmp")) == NULL) { return -1; } + if ((soundboard_texture = CreateTexture("soundboard.bmp")) == NULL) { return -1; } + if ((soundboard_levels_texture = CreateTexture("soundboard_levels.bmp")) == NULL) { return -1; } LoadStockWavThings(); CreateTrashcanThing(); CreateDefaultPhysicalDevice(SDL_FALSE); CreateDefaultPhysicalDevice(SDL_TRUE); -#ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(Loop, 0, 1); -#else - while (!done) { - Loop(); + return 0; +} + + +static SDL_bool saw_event = SDL_FALSE; + +int SDL_AppEvent(const SDL_Event *event) +{ + Thing *thing = NULL; + + saw_event = SDL_TRUE; + + switch (event->type) { + case SDL_EVENT_MOUSE_MOTION: + thing = UpdateMouseOver(event->motion.x, event->motion.y); + if ((dragging_button == -1) && event->motion.state) { + if (event->motion.state & SDL_BUTTON_LMASK) { + /* for people that don't have all three buttons... */ + if (ctrl_held) { + dragging_button = SDL_BUTTON_RIGHT; + } else if (alt_held) { + dragging_button = SDL_BUTTON_MIDDLE; + } else { + dragging_button = SDL_BUTTON_LEFT; + } + dragging_button_real = SDL_BUTTON_LEFT; + } else if (event->motion.state & SDL_BUTTON_RMASK) { + dragging_button = SDL_BUTTON_RIGHT; + dragging_button_real = SDL_BUTTON_RIGHT; + } else if (event->motion.state & SDL_BUTTON_MMASK) { + dragging_button = SDL_BUTTON_MIDDLE; + dragging_button_real = SDL_BUTTON_MIDDLE; + } + + if (dragging_button != -1) { + dragging_thing = thing; + if (thing && thing->ondrag) { + thing->ondrag(thing, dragging_button, event->motion.x, event->motion.y); + } + } + } + + droppable_highlighted_thing = NULL; + if (dragging_thing) { + dragging_thing->rect.x = event->motion.x - (dragging_thing->rect.w / 2); + dragging_thing->rect.y = event->motion.y - (dragging_thing->rect.h / 2); + if (dragging_thing->can_be_dropped_onto) { + thing = FindThingAtPoint(event->motion.x, event->motion.y); + if (thing) { + int i; + for (i = 0; dragging_thing->can_be_dropped_onto[i]; i++) { + if (dragging_thing->can_be_dropped_onto[i] == thing->what) { + droppable_highlighted_thing = thing; + break; + } + } + } + } + } + break; + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + thing = UpdateMouseOver(event->button.x, event->button.y); + break; + + case SDL_EVENT_MOUSE_BUTTON_UP: + if (dragging_button_real == event->button.button) { + Thing *dropped_thing = dragging_thing; + dragging_thing = NULL; + dragging_button = -1; + dragging_button_real = -1; + if (dropped_thing && dropped_thing->ondrop) { + dropped_thing->ondrop(dropped_thing, event->button.button, event->button.x, event->button.y); + } + droppable_highlighted_thing = NULL; + } + thing = UpdateMouseOver(event->button.x, event->button.y); + break; + + case SDL_EVENT_MOUSE_WHEEL: + UpdateMouseOver(event->wheel.mouseX, event->wheel.mouseY); + break; + + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + ctrl_held = ((event->key.keysym.mod & SDL_KMOD_CTRL) != 0) ? SDL_TRUE : SDL_FALSE; + alt_held = ((event->key.keysym.mod & SDL_KMOD_ALT) != 0) ? SDL_TRUE : SDL_FALSE; + break; + + case SDL_EVENT_DROP_FILE: + SDL_Log("Drop file! '%s'", event->drop.file); + LoadWavThing(event->drop.file, event->drop.x, event->drop.y); + /* SDL frees event->drop.file for you when you use SDL_AppEvent(). */ + break; + + case SDL_EVENT_WINDOW_RESIZED: + WindowResized(event->window.data1, event->window.data2); + break; + + case SDL_EVENT_AUDIO_DEVICE_ADDED: + CreatePhysicalDeviceThing(event->adevice.which, event->adevice.iscapture); + break; + + case SDL_EVENT_AUDIO_DEVICE_REMOVED: { + const SDL_AudioDeviceID which = event->adevice.which; + Thing *i, *next; + SDL_Log("Removing audio device %u", (unsigned int) which); + for (i = things; i != NULL; i = next) { + next = i->next; + if (((i->what == THING_PHYSDEV) || (i->what == THING_PHYSDEV_CAPTURE)) && (i->data.physdev.devid == which)) { + TrashThing(i); + next = things; /* in case we mangled the list. */ + } else if (((i->what == THING_LOGDEV) || (i->what == THING_LOGDEV_CAPTURE)) && (i->data.logdev.devid == which)) { + TrashThing(i); + next = things; /* in case we mangled the list. */ + } + } + break; + } + + default: break; } -#endif - Quit(0); - return 0; + return SDLTest_CommonEventMainCallbacks(state, event); +} + +int SDL_AppIterate(void) +{ + if (app_ready_ticks == 0) { + app_ready_ticks = SDL_GetTicks(); + } + + TickThings(); + Draw(); + + if (saw_event) { + saw_event = SDL_FALSE; /* reset this so we know when SDL_AppEvent() runs again */ + } else { + SDL_Delay(10); + } + + return 0; /* keep going. */ +} + +void SDL_AppQuit(void) +{ + while (things != NULL) { + DestroyThing(things); /* make sure all the audio devices are closed, etc. */ + } + + DestroyTexture(physdev_texture); + DestroyTexture(logdev_texture); + DestroyTexture(audio_texture); + DestroyTexture(trashcan_texture); + DestroyTexture(soundboard_texture); + DestroyTexture(soundboard_levels_texture); + SDLTest_CommonQuit(state); } diff --git a/test/testaudiocapture.c b/test/testaudiocapture.c index efc4be1010fe3..9b44b6573540d 100644 --- a/test/testaudiocapture.c +++ b/test/testaudiocapture.c @@ -10,94 +10,20 @@ freely. */ -#include - +#define SDL_MAIN_USE_CALLBACKS 1 #include #include #include -#ifdef __EMSCRIPTEN__ -#include -#endif - static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; static SDL_AudioStream *stream_in = NULL; static SDL_AudioStream *stream_out = NULL; -static int done = 0; +static SDLTest_CommonState *state = NULL; -static void loop(void) -{ - const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in); - const SDL_AudioDeviceID devid_out = SDL_GetAudioStreamDevice(stream_out); - SDL_bool please_quit = SDL_FALSE; - SDL_Event e; - - while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) { - please_quit = SDL_TRUE; - } else if (e.type == SDL_EVENT_KEY_DOWN) { - if (e.key.keysym.sym == SDLK_ESCAPE) { - please_quit = SDL_TRUE; - } - } else if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { - if (e.button.button == 1) { - SDL_PauseAudioDevice(devid_out); - SDL_ResumeAudioDevice(devid_in); - } - } else if (e.type == SDL_EVENT_MOUSE_BUTTON_UP) { - if (e.button.button == 1) { - SDL_PauseAudioDevice(devid_in); - SDL_FlushAudioStream(stream_in); /* so no samples are held back for resampling purposes. */ - SDL_ResumeAudioDevice(devid_out); - } - } - } - - if (!SDL_AudioDevicePaused(devid_in)) { - SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); - } else { - SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); - } - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - - /* Feed any new data we captured to the output stream. It'll play when we unpause the device. */ - while (!please_quit && (SDL_GetAudioStreamAvailable(stream_in) > 0)) { - Uint8 buf[1024]; - const int br = SDL_GetAudioStreamData(stream_in, buf, sizeof(buf)); - if (br < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to read from input audio stream: %s\n", SDL_GetError()); - please_quit = 1; - } else if (SDL_PutAudioStreamData(stream_out, buf, br) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to write to output audio stream: %s\n", SDL_GetError()); - please_quit = 1; - } - } - - if (please_quit) { - /* stop playing back, quit. */ - SDL_Log("Shutting down.\n"); - SDL_CloseAudioDevice(devid_in); - SDL_CloseAudioDevice(devid_out); - SDL_DestroyAudioStream(stream_in); - SDL_DestroyAudioStream(stream_out); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); -#ifdef __EMSCRIPTEN__ - emscripten_cancel_main_loop(); -#endif - /* Let 'main()' return normally */ - done = 1; - return; - } -} - -int main(int argc, char **argv) +int SDL_AppInit(int argc, char **argv) { SDL_AudioDeviceID *devices; - SDLTest_CommonState *state; SDL_AudioSpec outspec; SDL_AudioSpec inspec; SDL_AudioDeviceID device; @@ -105,6 +31,9 @@ int main(int argc, char **argv) const char *devname = NULL; int i; + /* this doesn't have to run very much, so give up tons of CPU time between iterations. */ + SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "15"); + /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); if (state == NULL) { @@ -128,7 +57,7 @@ int main(int argc, char **argv) if (consumed <= 0) { static const char *options[] = { "[device_name]", NULL }; SDLTest_CommonLogUsage(state, argv[0], options); - exit(1); + return -1; } i += consumed; @@ -175,20 +104,17 @@ int main(int argc, char **argv) device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, NULL); if (!device) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } SDL_PauseAudioDevice(device); SDL_GetAudioDeviceFormat(device, &outspec, NULL); stream_out = SDL_CreateAudioStream(&outspec, &outspec); if (!stream_out) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for playback: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } else if (SDL_BindAudioStream(device, stream_out) == -1) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for playback: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } SDL_Log("Opening capture device %s%s%s...\n", @@ -199,38 +125,89 @@ int main(int argc, char **argv) device = SDL_OpenAudioDevice(want_device, NULL); if (!device) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } SDL_PauseAudioDevice(device); SDL_GetAudioDeviceFormat(device, &inspec, NULL); stream_in = SDL_CreateAudioStream(&inspec, &inspec); if (!stream_in) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for capture: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } else if (SDL_BindAudioStream(device, stream_in) == -1) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for capture: %s!\n", SDL_GetError()); - SDL_Quit(); - exit(1); + return -1; } SDL_SetAudioStreamFormat(stream_in, NULL, &outspec); /* make sure we output at the playback format. */ SDL_Log("Ready! Hold down mouse or finger to record!\n"); -#ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(loop, 0, 1); -#else - while (!done) { - loop(); - if (!done) { - SDL_Delay(16); + return 0; +} + +int SDL_AppEvent(const SDL_Event *event) +{ + if (event->type == SDL_EVENT_QUIT) { + return 1; /* terminate as success. */ + } else if (event->type == SDL_EVENT_KEY_DOWN) { + if (event->key.keysym.sym == SDLK_ESCAPE) { + return 1; /* terminate as success. */ + } + } else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + if (event->button.button == 1) { + SDL_PauseAudioDevice(SDL_GetAudioStreamDevice(stream_out)); + SDL_FlushAudioStream(stream_out); /* so no samples are held back for resampling purposes. */ + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream_in)); + } + } else if (event->type == SDL_EVENT_MOUSE_BUTTON_UP) { + if (event->button.button == 1) { + SDL_PauseAudioDevice(SDL_GetAudioStreamDevice(stream_in)); + SDL_FlushAudioStream(stream_in); /* so no samples are held back for resampling purposes. */ + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream_out)); } } -#endif + return 0; /* keep going. */ +} - SDLTest_CommonDestroyState(state); +int SDL_AppIterate(void) +{ + if (!SDL_AudioDevicePaused(SDL_GetAudioStreamDevice(stream_in))) { + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + } else { + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); + } + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); - return 0; + /* Feed any new data we captured to the output stream. It'll play when we unpause the device. */ + while (SDL_GetAudioStreamAvailable(stream_in) > 0) { + Uint8 buf[1024]; + const int br = SDL_GetAudioStreamData(stream_in, buf, sizeof(buf)); + if (br < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to read from input audio stream: %s\n", SDL_GetError()); + return -1; /* quit the app, report failure. */ + } else if (SDL_PutAudioStreamData(stream_out, buf, br) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to write to output audio stream: %s\n", SDL_GetError()); + return -1; /* quit the app, report failure. */ + } + } + + return 0; /* keep app going. */ } + +void SDL_AppQuit(void) +{ + SDL_Log("Shutting down.\n"); + const SDL_AudioDeviceID devid_in = SDL_GetAudioStreamDevice(stream_in); + const SDL_AudioDeviceID devid_out = SDL_GetAudioStreamDevice(stream_out); + SDL_CloseAudioDevice(devid_in); /* !!! FIXME: use SDL_OpenAudioDeviceStream instead so we can dump this. */ + SDL_CloseAudioDevice(devid_out); + SDL_DestroyAudioStream(stream_in); + SDL_DestroyAudioStream(stream_out); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDLTest_CommonDestroyState(state); + SDL_Quit(); +} + + diff --git a/test/testsprite.c b/test/testsprite.c index 9afa6f0dac3c9..217dc181b4cef 100644 --- a/test/testsprite.c +++ b/test/testsprite.c @@ -14,10 +14,7 @@ #include #include -#ifdef __EMSCRIPTEN__ -#include -#endif - +#define SDL_MAIN_USE_CALLBACKS 1 #include #include #include @@ -48,20 +45,12 @@ static SDL_bool suspend_when_occluded; /* -1: infinite random moves (default); >=0: enables N deterministic moves */ static int iterations = -1; -static int done; - -/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ -static void -quit(int rc) +void SDL_AppQuit(void) { SDL_free(sprites); SDL_free(positions); SDL_free(velocities); SDLTest_CommonQuit(state); - /* Let 'main()' return normally */ - if (rc != 0) { - exit(rc); - } } static int LoadSprite(const char *file) @@ -395,17 +384,17 @@ static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite) SDL_RenderPresent(renderer); } -static void loop(void) +int SDL_AppEvent(const SDL_Event *event) +{ + return SDLTest_CommonEventMainCallbacks(state, event); +} + +int SDL_AppIterate(void) { Uint64 now; int i; int active_windows = 0; - SDL_Event event; - /* Check for events */ - while (SDL_PollEvent(&event)) { - SDLTest_CommonEvent(state, &event, &done); - } for (i = 0; i < state->num_windows; ++i) { if (state->windows[i] == NULL || (suspend_when_occluded && (SDL_GetWindowFlags(state->windows[i]) & SDL_WINDOW_OCCLUDED))) { @@ -414,14 +403,9 @@ static void loop(void) ++active_windows; MoveSprites(state->renderers[i], sprites[i]); } -#ifdef __EMSCRIPTEN__ - if (done) { - emscripten_cancel_main_loop(); - } -#endif /* If all windows are occluded, throttle the event polling to 15hz. */ - if (!done && !active_windows) { + if (!active_windows) { SDL_DelayNS(SDL_NS_PER_SECOND / 15); } @@ -435,9 +419,11 @@ static void loop(void) next_fps_check = now + fps_check_delay; frames = 0; } + + return 0; /* keep going */ } -int main(int argc, char *argv[]) +int SDL_AppInit(int argc, char *argv[]) { int i; Uint64 seed; @@ -449,7 +435,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); if (state == NULL) { - return 1; + return -1; } for (i = 1; i < argc;) { @@ -532,12 +518,12 @@ int main(int argc, char *argv[]) NULL }; SDLTest_CommonLogUsage(state, argv[0], options); - quit(1); + return -1; } i += consumed; } if (!SDLTest_CommonInit(state)) { - quit(2); + return -1; } /* Create the windows, initialize the renderers, and load the textures */ @@ -545,7 +531,7 @@ int main(int argc, char *argv[]) (SDL_Texture **)SDL_malloc(state->num_windows * sizeof(*sprites)); if (sprites == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); - quit(2); + return -1; } for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; @@ -553,7 +539,7 @@ int main(int argc, char *argv[]) SDL_RenderClear(renderer); } if (LoadSprite(icon) < 0) { - quit(2); + return -1; } /* Allocate memory for the sprite info */ @@ -561,7 +547,7 @@ int main(int argc, char *argv[]) velocities = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*velocities)); if (positions == NULL || velocities == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); - quit(2); + return -1; } /* Position sprites and set their velocities using the fuzzer */ @@ -586,19 +572,10 @@ int main(int argc, char *argv[]) } } - /* Main render loop */ + /* Main render loop in SDL_AppIterate will begin when this function returns. */ frames = 0; next_fps_check = SDL_GetTicks() + fps_check_delay; - done = 0; -#ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(loop, 0, 1); -#else - while (!done) { - loop(); - } -#endif - - quit(0); return 0; } + From ac6b32bb0280f225bd117a0c1db554dc3ee8f3f2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Nov 2023 21:47:42 -0400 Subject: [PATCH 185/725] gendynapi.py: Discard SDLMAIN_DECLSPEC functions. Otherwise SDL_main and SDL_App* functions look like exported symbols instead of functions the app is meant to implement. Reference PR #8247. --- src/dynapi/gendynapi.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index 5e6a11b8c0f7a..b91f2ee7f2cac 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -134,7 +134,13 @@ def main(): # Discard if it doesn't contain 'SDLCALL' if "SDLCALL" not in func: if args.debug: - print(" Discard: " + func) + print(" Discard, doesn't have SDLCALL: " + func) + continue + + # Discard if it contains 'SDLMAIN_DECLSPEC' (these are not SDL symbols). + if "SDLMAIN_DECLSPEC" in func: + if args.debug: + print(" Discard, has SDLMAIN_DECLSPEC: " + func) continue if args.debug: From ad0af488837e44cbea0f0eab3b2f73b50a74bff4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 2 Nov 2023 08:33:15 -0700 Subject: [PATCH 186/725] Check to make sure the Windows joystick device has buttons and axes This reverts commit e5a15f94e2f1a8fbbffb25ea9932cda9679a68fd. It turns out removing this check allows mice like the ROG PUGIO II to show up as game controllers. We need to find a different way to differentiate between gaming mice and pedals. Since these mice show up as controllers, and potentially causing games to use them instead of real controllers, we'll go ahead revert this change for now. Reopens https://github.com/libsdl-org/SDL/issues/8227 --- src/joystick/windows/SDL_dinputjoystick.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index fbb0e8240c618..b6868891a9fa1 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -451,6 +451,7 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta char *hidPath = NULL; char *name = NULL; LPDIRECTINPUTDEVICE8 device = NULL; + DIDEVCAPS caps; /* We are only supporting HID devices. */ CHECK(pDeviceInstance->dwDevType & DIDEVTYPE_HID); @@ -460,6 +461,13 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta CHECK(QueryDevicePath(device, &hidPath)); CHECK(QueryDeviceInfo(device, &vendor, &product)); + /* Check to make sure the device has buttons and axes. + * This fixes incorrectly detecting the ROG CHAKRAM X mouse as a game controller on Windows 10 + */ + caps.dwSize = sizeof(caps); + CHECK(SUCCEEDED(IDirectInputDevice8_GetCapabilities(device, &caps))); + CHECK(caps.dwAxes > 0 && caps.dwButtons > 0); + CHECK(!SDL_IsXInputDevice(vendor, product, hidPath)); pNewJoystick = *(JoyStick_DeviceData **)pContext; From 618d15bce6cbc430baa94154a31c7f0288b5b27c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 2 Nov 2023 10:33:44 -0700 Subject: [PATCH 187/725] Fixed typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd24bbfb512f4..90c4e05cc9afd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,7 +494,7 @@ if(MSVC AND TARGET SDL3-shared) target_compile_options(SDL3-shared PRIVATE "$<$:/nologo>") set_property(SOURCE "${asm_src}" PROPERTY LANGUAGE "ASM_MASM") target_sources(SDL3-shared PRIVATE "${asm_src}") - elseif(SDL_CPU_ARM32 OR DL_CPU_ARM64) + elseif(SDL_CPU_ARM32 OR SDL_CPU_ARM64) # FIXME: ARM assembler (armasm.exe/armasm64.exe) is NOT ASM_MASM, and does currently not work with CMake # (https://gitlab.kitware.com/cmake/cmake/-/issues/18912) endif() From 338974bb29bb13edba64add3a06242e08bddcd07 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 2 Nov 2023 20:33:02 +0300 Subject: [PATCH 188/725] SDL_test_memory.c: fix build against older windows SDKs. --- src/test/SDL_test_memory.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/SDL_test_memory.c b/src/test/SDL_test_memory.c index 526686ad8266e..2ca790fb312a5 100644 --- a/src/test/SDL_test_memory.c +++ b/src/test/SDL_test_memory.c @@ -43,6 +43,10 @@ typedef BOOL (__stdcall *dbghelp_SymGetLineFromAddr_fn)(HANDLE hProcess, DWORD q #endif static dbghelp_SymGetLineFromAddr_fn dbghelp_SymGetLineFromAddr; +/* older SDKs might not have this: */ +__declspec(dllimport) USHORT WINAPI RtlCaptureStackBackTrace(ULONG FramesToSkip, ULONG FramesToCapture, PVOID* BackTrace, PULONG BackTraceHash); +#define CaptureStackBackTrace RtlCaptureStackBackTrace + #endif /* This is a simple tracking allocator to demonstrate the use of SDL's @@ -179,7 +183,7 @@ static void SDL_TrackAllocation(void *mem, size_t size) line.LineNumber = 0; } - SDL_snprintf(entry->stack_names[i], sizeof(entry->stack_names[i]), "%s+0x%llx %s:%u", pSymbol->Name, (unsigned long long)dwDisplacement, line.FileName, (Uint32)line.LineNumber); + SDL_snprintf(entry->stack_names[i], sizeof(entry->stack_names[i]), "%s+0x%I64x %s:%u", pSymbol->Name, dwDisplacement, line.FileName, (Uint32)line.LineNumber); } } } From d0d8b28df125f00eca5eb4f09c1d6fb8ab0eba8d Mon Sep 17 00:00:00 2001 From: ilyas-taouaou Date: Thu, 2 Nov 2023 17:20:26 +0100 Subject: [PATCH 189/725] Change SDL_Vulkan_GetInstanceExtensions --- include/SDL3/SDL_vulkan.h | 3 +-- src/dynapi/SDL_dynapi_procs.h | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 9 ++------- src/video/SDL_vulkan_internal.h | 7 ------- src/video/SDL_vulkan_utils.c | 21 --------------------- src/video/android/SDL_androidvulkan.c | 14 +++++--------- src/video/cocoa/SDL_cocoavulkan.m | 14 +++++--------- src/video/kmsdrm/SDL_kmsdrmvulkan.c | 14 ++++---------- src/video/kmsdrm/SDL_kmsdrmvulkan.h | 5 ++--- src/video/uikit/SDL_uikitvulkan.m | 15 +++++---------- src/video/vivante/SDL_vivantevulkan.c | 14 +++++--------- src/video/wayland/SDL_waylandvulkan.c | 13 +++---------- src/video/wayland/SDL_waylandvulkan.h | 5 ++--- src/video/windows/SDL_windowsvulkan.c | 14 ++++---------- src/video/x11/SDL_x11vulkan.c | 21 ++++++++++----------- src/video/x11/SDL_x11vulkan.h | 5 ++--- test/testvulkan.c | 25 ++----------------------- 18 files changed, 54 insertions(+), 149 deletions(-) diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 13047c9d0c82d..3b2cd31894e42 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -160,8 +160,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * * \sa SDL_Vulkan_CreateSurface */ -extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions(unsigned int *pCount, - const char **pNames); +extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint32 *pCount); /** * Create a Vulkan rendering surface for a window. diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 868a35ec9d145..25ee29776f168 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -719,7 +719,7 @@ SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurfaceRects,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return) SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, VkSurfaceKHR *c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_GetInstanceExtensions,(unsigned int *a, const char **b),(a,b),return) +SDL_DYNAPI_PROC(char const* const*,SDL_Vulkan_GetInstanceExtensions,(Uint32 *a),(a),return) SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_Vulkan_GetVkGetInstanceProcAddr,(void),(),return) SDL_DYNAPI_PROC(int,SDL_Vulkan_LoadLibrary,(const char *a),(a),return) SDL_DYNAPI_PROC(void,SDL_Vulkan_UnloadLibrary,(void),(),) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index cb5e4c188e82e..40ca819422804 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -290,7 +290,7 @@ struct SDL_VideoDevice */ int (*Vulkan_LoadLibrary)(SDL_VideoDevice *_this, const char *path); void (*Vulkan_UnloadLibrary)(SDL_VideoDevice *_this); - SDL_bool (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, unsigned *count, const char **names); + char const* const* (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, Uint32 *count); SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface); /* * * */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index eec3e0dd87978..d6f667dc3ecf9 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -5140,14 +5140,9 @@ void SDL_Vulkan_UnloadLibrary(void) } } -SDL_bool SDL_Vulkan_GetInstanceExtensions(unsigned *count, const char **names) +char const* const* SDL_Vulkan_GetInstanceExtensions(Uint32 *count) { - if (count == NULL) { - SDL_InvalidParamError("count"); - return SDL_FALSE; - } - - return _this->Vulkan_GetInstanceExtensions(_this, count, names); + return _this->Vulkan_GetInstanceExtensions(_this, count); } SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window, diff --git a/src/video/SDL_vulkan_internal.h b/src/video/SDL_vulkan_internal.h index 5242aecef01d4..74452134bd52f 100644 --- a/src/video/SDL_vulkan_internal.h +++ b/src/video/SDL_vulkan_internal.h @@ -63,13 +63,6 @@ extern VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList( PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties, Uint32 *extensionCount); /* free returned list with SDL_free */ -/* Implements functionality of SDL_Vulkan_GetInstanceExtensions for a list of - * names passed in nameCount and names. */ -extern SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount, - const char **userNames, - unsigned nameCount, - const char *const *names); - /* Create a surface directly from a display connected to a physical device * using the DisplayKHR extension. * This needs to be passed an instance that was created with the VK_KHR_DISPLAY_EXTENSION_NAME diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index 2993fc7991a86..5ce81a7b0804b 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -167,27 +167,6 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList( return retval; } -SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount, - const char **userNames, - unsigned nameCount, - const char *const *names) -{ - if (userNames) { - unsigned i; - - if (*userCount < nameCount) { - SDL_SetError("Output array for SDL_Vulkan_GetInstanceExtensions needs to be at least %d big", nameCount); - return SDL_FALSE; - } - - for (i = 0; i < nameCount; i++) { - userNames[i] = names[i]; - } - } - *userCount = nameCount; - return SDL_TRUE; -} - /* Alpha modes, in order of preference */ static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = { VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c index 8a0af19629f16..d47d422a97146 100644 --- a/src/video/android/SDL_androidvulkan.c +++ b/src/video/android/SDL_androidvulkan.c @@ -111,20 +111,16 @@ void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForAndroid[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; + if(count) { + *count = SDL_arraysize(extensionsForAndroid); } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForAndroid), - extensionsForAndroid); + return extensionsForAndroid; } SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index 027ba2ac24483..55d1f352fb0d1 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -163,20 +163,16 @@ void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForCocoa[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; + if(count) { + *count = SDL_arraysize(extensionsForCocoa); } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForCocoa), - extensionsForCocoa); + return extensionsForCocoa; } static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this, diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index 619053c9fc64d..fba00b6585cd4 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -142,20 +142,14 @@ void KMSDRM_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) /* members of the VkInstanceCreateInfo struct passed to */ /* vkCreateInstance(). */ /*********************************************************************/ -SDL_bool KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForKMSDRM[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; - } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForKMSDRM), - extensionsForKMSDRM); + if(count) { *count = SDL_arraysize(extensionsForKMSDRM); } + return extensionsForKMSDRM; } /***********************************************************************/ diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.h b/src/video/kmsdrm/SDL_kmsdrmvulkan.h index 68efc02d030cf..7db828d93a525 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.h +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.h @@ -36,9 +36,8 @@ int KMSDRM_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void KMSDRM_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m index 5bdc743807253..833485062ba53 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -169,21 +169,16 @@ void UIKit_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForUIKit[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; + if(count) { + *count = SDL_arraysize(extensionsForUIKit); } - - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForUIKit), - extensionsForUIKit); + return extensionsForUIKit; } SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c index 24d9107002618..d5a30e79e96eb 100644 --- a/src/video/vivante/SDL_vivantevulkan.c +++ b/src/video/vivante/SDL_vivantevulkan.c @@ -118,20 +118,16 @@ void VIVANTE_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForVivante[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; + if(count) { + *count = SDL_arraysize(extensionsForVivante); } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForVivante), - extensionsForVivante); + return extensionsForVivante; } SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this, diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 1f667512a8cf2..3e372bd2a66a3 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -118,20 +118,13 @@ void Wayland_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForWayland[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; - } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForWayland), - extensionsForWayland); + return extensionsForWayland; } SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this, diff --git a/src/video/wayland/SDL_waylandvulkan.h b/src/video/wayland/SDL_waylandvulkan.h index 18aa3ed573607..ebcd4c1c5656f 100644 --- a/src/video/wayland/SDL_waylandvulkan.h +++ b/src/video/wayland/SDL_waylandvulkan.h @@ -36,9 +36,8 @@ int Wayland_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void Wayland_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c index f0b288b421456..79b64ffd8f77e 100644 --- a/src/video/windows/SDL_windowsvulkan.c +++ b/src/video/windows/SDL_windowsvulkan.c @@ -112,20 +112,14 @@ void WIN_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { static const char *const extensionsForWin32[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; - } - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForWin32), - extensionsForWin32); + if(count) { *count = SDL_arraysize(extensionsForWin32); } + return extensionsForWin32; } SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this, diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c index b81b980417ba3..7eea5a34bba82 100644 --- a/src/video/x11/SDL_x11vulkan.c +++ b/src/video/x11/SDL_x11vulkan.c @@ -142,29 +142,28 @@ void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -SDL_bool X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names) +char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) { SDL_VideoData *videoData = _this->driverdata; - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - return SDL_FALSE; - } if (videoData->vulkan_xlib_xcb_library) { static const char *const extensionsForXCB[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME, }; - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForXCB), extensionsForXCB); + if(count) { + *count = SDL_arraysize(extensionsForXCB); + } + return extensionsForXCB; } else { static const char *const extensionsForXlib[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME, }; - return SDL_Vulkan_GetInstanceExtensions_Helper( - count, names, SDL_arraysize(extensionsForXlib), extensionsForXlib); + if(count) { + *count = SDL_arraysize(extensionsForXlib); + } + return extensionsForXlib; } } diff --git a/src/video/x11/SDL_x11vulkan.h b/src/video/x11/SDL_x11vulkan.h index 30b047e03594a..acaf5d65cbc65 100644 --- a/src/video/x11/SDL_x11vulkan.h +++ b/src/video/x11/SDL_x11vulkan.h @@ -32,9 +32,8 @@ typedef xcb_connection_t *(*PFN_XGetXCBConnection)(Display *dpy); int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, diff --git a/test/testvulkan.c b/test/testvulkan.c index c20e4bc9e5ed1..e13e3ace84210 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -222,36 +222,15 @@ static void createInstance(void) { VkApplicationInfo appInfo = { 0 }; VkInstanceCreateInfo instanceCreateInfo = { 0 }; - const char **extensions = NULL; - unsigned extensionCount = 0; VkResult result; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.apiVersion = VK_API_VERSION_1_0; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceCreateInfo.pApplicationInfo = &appInfo; - if (!SDL_Vulkan_GetInstanceExtensions(&extensionCount, NULL)) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_Vulkan_GetInstanceExtensions(): %s\n", - SDL_GetError()); - quit(2); - } - extensions = (const char **)SDL_malloc(sizeof(const char *) * extensionCount); - if (extensions == NULL) { - SDL_OutOfMemory(); - quit(2); - } - if (!SDL_Vulkan_GetInstanceExtensions(&extensionCount, extensions)) { - SDL_free((void *)extensions); - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_Vulkan_GetInstanceExtensions(): %s\n", - SDL_GetError()); - quit(2); - } - instanceCreateInfo.enabledExtensionCount = extensionCount; - instanceCreateInfo.ppEnabledExtensionNames = extensions; + + instanceCreateInfo.ppEnabledExtensionNames = SDL_Vulkan_GetInstanceExtensions(&instanceCreateInfo.enabledExtensionCount); result = vkCreateInstance(&instanceCreateInfo, NULL, &vulkanContext->instance); - SDL_free((void *)extensions); if (result != VK_SUCCESS) { vulkanContext->instance = VK_NULL_HANDLE; SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, From 9224a0a2d84bf58cd50c7a10450008e598ae144d Mon Sep 17 00:00:00 2001 From: ilyas-taouaou Date: Thu, 2 Nov 2023 18:54:27 +0100 Subject: [PATCH 190/725] Fix emscripten, android, uikit and windows --- include/SDL3/SDL_vulkan.h | 2 -- src/video/android/SDL_androidvulkan.h | 5 ++--- src/video/uikit/SDL_uikitvulkan.h | 5 ++--- src/video/windows/SDL_windowsvulkan.h | 5 ++--- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 3b2cd31894e42..6499f12bd03e3 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -152,8 +152,6 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * * \param pCount A pointer to an unsigned int corresponding to the number of * extensions to be returned - * \param pNames NULL or a pointer to an array to be filled with required - * Vulkan instance extensions * \returns SDL_TRUE on success, SDL_FALSE on error. * * \since This function is available since SDL 3.0.0. diff --git a/src/video/android/SDL_androidvulkan.h b/src/video/android/SDL_androidvulkan.h index 1b059c43d6bc3..e538ca917a2e4 100644 --- a/src/video/android/SDL_androidvulkan.h +++ b/src/video/android/SDL_androidvulkan.h @@ -36,9 +36,8 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, diff --git a/src/video/uikit/SDL_uikitvulkan.h b/src/video/uikit/SDL_uikitvulkan.h index 0e13675672e51..432edda9460d7 100644 --- a/src/video/uikit/SDL_uikitvulkan.h +++ b/src/video/uikit/SDL_uikitvulkan.h @@ -36,9 +36,8 @@ int UIKit_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void UIKit_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, diff --git a/src/video/windows/SDL_windowsvulkan.h b/src/video/windows/SDL_windowsvulkan.h index 17b69687ca52a..0fffcbf4278c9 100644 --- a/src/video/windows/SDL_windowsvulkan.h +++ b/src/video/windows/SDL_windowsvulkan.h @@ -36,9 +36,8 @@ int WIN_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void WIN_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, From 5b3a2c6df66a58f8694ccb917f7f5641cf699b2d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 2 Nov 2023 14:57:13 -0400 Subject: [PATCH 191/725] docs: Updated SDL_Vulkan_GetInstanceExtensions info in README-migration.md. Reference PR #8457. --- docs/README-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 85949df581554..6d0c9131f1813 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1293,7 +1293,7 @@ The following symbols have been renamed: ## SDL_vulkan.h -SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter. +SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no longer makes the app allocate query/allocate space for the result, instead returning a static const internal string. SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr. From 07a776f2553245cbbf39642e8876eb1c2701cf79 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 2 Nov 2023 15:12:24 -0400 Subject: [PATCH 192/725] include: Fixed documentation for SDL_Vulkan_GetInstanceExtensions. --- include/SDL3/SDL_vulkan.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 6499f12bd03e3..5f354f8c46746 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -135,24 +135,22 @@ extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr( extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); /** - * Get the names of the Vulkan instance extensions needed to create a surface - * with SDL_Vulkan_CreateSurface. + * Get the Vulkan instance extensions needed for vkCreateInstance. * * This should be called after either calling SDL_Vulkan_LoadLibrary() or * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag. * - * If `pNames` is NULL, then the number of required Vulkan instance extensions - * is returned in `pCount`. Otherwise, `pCount` must point to a variable set - * to the number of elements in the `pNames` array, and on return the variable - * is overwritten with the number of names actually written to `pNames`. If - * `pCount` is less than the number of required extensions, at most `pCount` - * structures will be written. If `pCount` is smaller than the number of - * required extensions, SDL_FALSE will be returned instead of SDL_TRUE, to - * indicate that not all the required extensions were returned. - * - * \param pCount A pointer to an unsigned int corresponding to the number of - * extensions to be returned - * \returns SDL_TRUE on success, SDL_FALSE on error. + * On return, the variable pointed to by `pCount` will be set to the number + * of elements returned, suitable for using with + * VkInstanceCreateInfo::enabledExtensionCount, and the returned array can be + * used with VkInstanceCreateInfo::ppEnabledExtensionNames, for calling + * Vulkan's vkCreateInstance API. + * + * You should not free the returned array; it is owned by SDL. + * + * \param pCount A pointer to Uint32 that will be filled with the number of + * extensions returned. + * \returns An array of extension name strings on success, NULL on error. * * \since This function is available since SDL 3.0.0. * From 5e869d1b3571fe4887df347039b56808b3bbee8f Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 2 Nov 2023 22:12:56 +0300 Subject: [PATCH 193/725] fix Cocoa_Vulkan_GetInstanceExtensions prototype for Mac --- src/video/cocoa/SDL_cocoavulkan.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video/cocoa/SDL_cocoavulkan.h b/src/video/cocoa/SDL_cocoavulkan.h index 3a49b2adfc04a..155dac30888bc 100644 --- a/src/video/cocoa/SDL_cocoavulkan.h +++ b/src/video/cocoa/SDL_cocoavulkan.h @@ -36,9 +36,8 @@ int Cocoa_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); +char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count); SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, From 6cf84e2c5bf9862218032f1ad50e8ebb125c7171 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 2 Nov 2023 21:31:32 +0100 Subject: [PATCH 194/725] cmake: fold HAVE_INPUT_EVENTS into HAVE_LINUX_INPUT_H --- CMakeLists.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90c4e05cc9afd..2962ed177dd31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1088,8 +1088,6 @@ if(SDL_LIBC) cmake_pop_check_state() if(NOT WINDOWS) - check_include_file(linux/input.h HAVE_LINUX_INPUT_H) - check_symbol_exists(getpagesize "unistd.h" HAVE_GETPAGESIZE) check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) check_symbol_exists(setjmp "setjmp.h" HAVE_SETJMP) @@ -1488,7 +1486,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) #ifndef EVIOCGNAME #error EVIOCGNAME() ioctl not available #endif - int main(int argc, char** argv) { return 0; }" HAVE_INPUT_EVENTS) + int main(int argc, char** argv) { return 0; }" HAVE_LINUX_INPUT_H) endif() if(LINUX) @@ -1525,11 +1523,11 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) }" HAVE_INPUT_WSCONS) endif() - if(HAVE_INPUT_EVENTS) + if(HAVE_LINUX_INPUT_H) set(SDL_INPUT_LINUXEV 1) endif() - if(SDL_HAPTIC AND HAVE_INPUT_EVENTS) + if(SDL_HAPTIC AND HAVE_LINUX_INPUT_H) set(SDL_HAPTIC_LINUX 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/linux/*.c") set(HAVE_SDL_HAPTIC TRUE) @@ -1617,7 +1615,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) sdl_sources("${SDL3_SOURCE_DIR}/src/core/linux/SDL_udev.c") endif() - if(HAVE_INPUT_EVENTS) + if(HAVE_LINUX_INPUT_H) sdl_sources( "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev.c" "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_kbd.c" From 14980b25a86f6d4657ed1dfa8e273b62238a3259 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 2 Nov 2023 22:32:25 -0700 Subject: [PATCH 195/725] Clarify documentation for audio callback migration --- docs/README-migration.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 6d0c9131f1813..109c5543fc254 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -62,7 +62,7 @@ In SDL2, you might have done something like this to play audio... ```c void SDLCALL MyAudioCallback(void *userdata, Uint8 * stream, int len) { - /* calculate a little more audio here, maybe using `userdata`, write it to `stream` */ + /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` */ } /* ...somewhere near startup... */ @@ -81,15 +81,25 @@ In SDL2, you might have done something like this to play audio... ...in SDL3, you can do this... ```c - void SDLCALL MyAudioCallback(SDL_AudioStream *stream, int len, void *userdata) + void SDLCALL MyAudioCallback3(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) { - /* calculate a little more audio here, maybe using `userdata`, write it to `stream` */ - SDL_PutAudioStreamData(stream, newdata, len); + /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` + * + * If you want to reuse the original callback, you could do something like this: + */ + if (additional_amount > 0) { + Uint16 *data = SDL_stack_alloc(Uint16, additional_amount / sizeof(Uint16)); + if (data) { + MyAudioCallback(userdata, data, additional_amount); + SDL_PutAudioStreamData(stream, data, additional_amount); + SDL_stack_free(data); + } + } } /* ...somewhere near startup... */ const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; - SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyAudioCallback, &my_audio_callback_user_data); + SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyAudioCallback3, &my_audio_callback_user_data); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); ``` From ea02630143c9312bab318996874d3e05bfab7453 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 00:28:05 -0700 Subject: [PATCH 196/725] More audio migration clarification --- docs/README-migration.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 109c5543fc254..494d69fce426b 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -81,14 +81,14 @@ In SDL2, you might have done something like this to play audio... ...in SDL3, you can do this... ```c - void SDLCALL MyAudioCallback3(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) + void SDLCALL MyNewAudioCallback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) { /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` * - * If you want to reuse the original callback, you could do something like this: + * If you want to use the original callback, you could do something like this: */ if (additional_amount > 0) { - Uint16 *data = SDL_stack_alloc(Uint16, additional_amount / sizeof(Uint16)); + Uint8 *data = SDL_stack_alloc(Uint8, additional_amount); if (data) { MyAudioCallback(userdata, data, additional_amount); SDL_PutAudioStreamData(stream, data, additional_amount); @@ -99,7 +99,7 @@ In SDL2, you might have done something like this to play audio... /* ...somewhere near startup... */ const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; - SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyAudioCallback3, &my_audio_callback_user_data); + SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyNewAudioCallback, &my_audio_callback_user_data); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); ``` From 70d75b4a2397eff8058165a8ef513e1371ba0d2d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 3 Nov 2023 10:13:46 -0400 Subject: [PATCH 197/725] Sync wiki -> headers --- include/SDL3/SDL_main.h | 11 ++++++----- include/SDL3/SDL_vulkan.h | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 1833fa73f2f7c..8c070b933d897 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -389,10 +389,10 @@ extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mai /** * An entry point for SDL's use in SDL_MAIN_USE_CALLBACKS. * - * Generally, you should not call this function directly. This only exists - * to hand off work into SDL as soon as possible, where it has a lot more - * control and functionality available, and make the inline code in - * SDL_main.h as small as possible. + * Generally, you should not call this function directly. This only exists to + * hand off work into SDL as soon as possible, where it has a lot more control + * and functionality available, and make the inline code in SDL_main.h as + * small as possible. * * Not all platforms use this, it's actual use is hidden in a magic * header-only library, and you should not call this directly unless you @@ -406,7 +406,8 @@ extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mai * \param appquit The application's SDL_AppQuit function * \returns standard Unix main return value * - * \threadsafety It is not safe to call this anywhere except as the only function call in SDL_main. + * \threadsafety It is not safe to call this anywhere except as the only + * function call in SDL_main. * * \since This function is available since SDL 3.0.0. */ diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 5f354f8c46746..baa4eaaf5a37b 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -140,8 +140,8 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * This should be called after either calling SDL_Vulkan_LoadLibrary() or * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag. * - * On return, the variable pointed to by `pCount` will be set to the number - * of elements returned, suitable for using with + * On return, the variable pointed to by `pCount` will be set to the number of + * elements returned, suitable for using with * VkInstanceCreateInfo::enabledExtensionCount, and the returned array can be * used with VkInstanceCreateInfo::ppEnabledExtensionNames, for calling * Vulkan's vkCreateInstance API. From 853c28e6247a9981b466a9085e118c048a4c49ed Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 3 Nov 2023 11:39:53 -0400 Subject: [PATCH 198/725] docs: Added first draft of README-main-functions.md Reference PR #8247. --- docs/README-main-functions.md | 213 ++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 docs/README-main-functions.md diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md new file mode 100644 index 0000000000000..386514d3fa8ca --- /dev/null +++ b/docs/README-main-functions.md @@ -0,0 +1,213 @@ +# Where an SDL program starts running. + +## History + +SDL has a long, complicated history with starting a program. + +In most of the civilized world, an application starts in a C-callable +function named "main". You probably learned it a long time ago: + +```c +int main(int argc, char **argv) +{ + printf("Hello world!\n"); + return 0; +} +``` + +But not all platforms work like this. Windows apps might want a different +function named "WinMain", for example, so SDL set out to paper over this +difference. + +Generally how this would work is: your app would always use the "standard" +`main(argc, argv)` function as its entry point, and `#include` the proper +SDL header before that, which did some macro magic. On platforms that used +a standard `main`, it would do nothing and what you saw was what you got. + +But those other platforms! If they needed something that _wasn't_ `main`, +SDL's macro magic would quietly rename your function to `SDL_main`, and +provide its own entry point that called it. Your app was none the wiser and +your code worked everywhere without changes. + +In SDL1, you linked with a static library that had startup code that _had_ to +run before you hit SDL_main(). For example, on macOS it would do various +magic to the process to make sure it was in the right state. Windows would +register win32 window classes and such. Things would break if you tried to +circumvent this, and you were in for a lot of trouble if you tried to use +SDL on a platform that needed this when you didn't control the entry point +(for example, as a plugin, or an SDL binding in a scripting language). + +In SDL2, the necessary support code moved into the main library, and the tiny +static library _only_ handled the basics of getting from the platform's real +entry point (like WinMain) to SDL_main; if the real entry was _already_ +standard main, the static library and macro magic was unnecessary. The goal +was to make it so you didn't have to change _your_ code to work on multiple +platforms and remove the original limitations. + +In SDL3, we've taken this much, much further. + +## The main entry point in SDL3 + +SDL3 still has the same macro tricks, but the static library is gone. Now it's +supplied by a "single-header library," which is to say you +`#include ` and that header will insert a small amount of +code into the source file that included it, so you no longer have to worry +about linking against an extra library that you might need on some platforms. +You just build your app and it works. + +You should _only_ include SDL_main.h from one file (the umbrella header, +SDL.h, does _not_ include it), and know that it will `#define main` to +something else, so if you use this symbol elsewhere as a variable name, etc, +it can cause you unexpected problems. + +SDL_main.h will also include platform-specific code (WinMain or whatnot) that +calls your _actual_ main function. This is compiled directly into your +program. + +If for some reason you need to include SDL_main.h in a file but also _don't_ +want it to generate this platform-specific code, you should define a special +macro before includin the header: + + +```c +#define SDL_MAIN_NOIMPL +``` + +If you are moving from SDL2, remove any references to the SDLmain static +library from your build system, and you should be done. Things should work as +they always have. + +If you have never controlled your process's entry point (you are using SDL +as a module from a general-purpose scripting language interpreter, or you're +SDL in a plugin for some otherwise-unrelated app), then there is nothing +required of you here; there is no startup code in SDL's entry point code that +is required, so using SDL_main.h is completely optional. Just start using +the SDL API when you are ready. + + +## Main callbacks in SDL3 + +There is a second option in SDL3 for how to structure your program. This is +completly optional and you can ignore it if you're happy using a standard +"main" function. + +Some platforms would rather your program operate in chunks. Most of the time, +games tend to look like this at the highest level: + +```c +int main(int argc, char **argv) +{ + initialize(); + while (keep_running()) { + handle_new_events(); + do_one_frame_of_stuff(); + } + deinitialize(); +} +``` + +There are platforms that would rather be in charge of that `while` loop: +iOS would rather you return from main() immediately and then it will let you +know that it's time to update and draw the next frame of video. Emscripten +(programs that run on a web page) absolutely requires this to function at all. +Video targets like Wayland can notify the app when to draw a new frame, to +save battery life and cooperate with the compositor more closely. + +In most cases, you can add special-case code to your program to deal with this +on different platforms, but SDL3 offers a system to handle transparently on +the app's behalf. + +To use this, you have to redesign the highest level of your app a little. Once +you do, it'll work on all supported SDL platforms without problems and +`#ifdef`s in your code. + +Instead of providing a "main" function, under this system, you would provide +several functions that SDL will call as appropriate. + +Using the callback entry points works on every platform, because on platforms +that don't require them, we can fake them with a simple loop in an internal +implementation of the usual SDL_main. + +The primary way we expect people to write SDL apps is still with SDL_main, and +this is not intended to replace it. If the app chooses to use this, it just +removes some platform-specific details they might have to otherwise manage, +and maybe removes a barrier to entry on some future platform. And you might +find you enjoy structuring your program like this more! + + +## How to use main callbacks in SDL3 + +To enable the callback entry points, you include SDL_main with an extra define +from a single source file in your project: + +```c +#define SDL_MAIN_USE_CALLBACKS +#include +``` + +Once you do this, you do not include a "main" function at all (and if you do, +the app will likely fail to link). Instead, you provide the following +functions: + +First: + +```c +int SDL_AppInit(int argc, char **argv); +``` + +This will be called _once_ before anything else. argc/argv work like they +always do. If this returns 0, the app runs. If it returns < 0, the app calls +SDL_AppQuit and terminates with an exit code that reports an error to the +platform. If it returns > 0, the app calls SDL_AppQuit and terminates with +an exit code that reports success to the platform. This function should not +go into an infinite mainloop; it should do any one-time startup it requires +and then return. + +Then: + +```c +int SDL_AppIterate(void); +``` + +This is called over and over, possibly at the refresh rate of the display or +some other metric that the platform dictates. This is where the heart of your +app runs. It should return as quickly as reasonably possible, but it's not a +"run one memcpy and that's all the time you have" sort of thing. The app +should do any game updates, and render a frame of video. If it returns < 0, +SDL will call SDL_AppQuit and terminate the process with an exit code that +reports an error to the platform. If it returns > 0, the app calls +SDL_AppQuit and terminates with an exit code that reports success to the +platform. If it returns 0, then SDL_AppIterate will be called again at some +regular frequency. The platform may choose to run this more or less (perhaps +less in the background, etc), or it might just call this function in a loop +as fast as possible. You do not check the event queue in this function +(SDL_AppEvent exists for that). + +Next: + +```c +int SDL_AppEvent(const SDL_Event *event); +``` + +This will be called once for each event pushed into the SDL queue. This may be +called from any thread, and possibly in parallel to SDL_AppIterate. The fields +in `event` do not need to be free'd (as you would normally need to do for +SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, +SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the +same as from SDL_AppIterate(), so you can terminate in response to +SDL_EVENT_QUIT, etc. + + +Finally: + +```c +void SDL_AppQuit(void); +``` + +This is called once before terminating the app--assuming the app isn't being +forcibly killed or crashed--as a last chance to clean up. After this returns, +SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app +to call it, too). Process termination proceeds as if the app returned normally +from main(), so atexit handles will run, if your platform supports that. + + From cf7e5bd0e8a4a489e339030dd3646d47211dba43 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Fri, 3 Nov 2023 15:41:14 +0000 Subject: [PATCH 199/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 426 +++++++++++++++++----------------- 1 file changed, 213 insertions(+), 213 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 386514d3fa8ca..cc4ca0c1441a0 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -1,213 +1,213 @@ -# Where an SDL program starts running. - -## History - -SDL has a long, complicated history with starting a program. - -In most of the civilized world, an application starts in a C-callable -function named "main". You probably learned it a long time ago: - -```c -int main(int argc, char **argv) -{ - printf("Hello world!\n"); - return 0; -} -``` - -But not all platforms work like this. Windows apps might want a different -function named "WinMain", for example, so SDL set out to paper over this -difference. - -Generally how this would work is: your app would always use the "standard" -`main(argc, argv)` function as its entry point, and `#include` the proper -SDL header before that, which did some macro magic. On platforms that used -a standard `main`, it would do nothing and what you saw was what you got. - -But those other platforms! If they needed something that _wasn't_ `main`, -SDL's macro magic would quietly rename your function to `SDL_main`, and -provide its own entry point that called it. Your app was none the wiser and -your code worked everywhere without changes. - -In SDL1, you linked with a static library that had startup code that _had_ to -run before you hit SDL_main(). For example, on macOS it would do various -magic to the process to make sure it was in the right state. Windows would -register win32 window classes and such. Things would break if you tried to -circumvent this, and you were in for a lot of trouble if you tried to use -SDL on a platform that needed this when you didn't control the entry point -(for example, as a plugin, or an SDL binding in a scripting language). - -In SDL2, the necessary support code moved into the main library, and the tiny -static library _only_ handled the basics of getting from the platform's real -entry point (like WinMain) to SDL_main; if the real entry was _already_ -standard main, the static library and macro magic was unnecessary. The goal -was to make it so you didn't have to change _your_ code to work on multiple -platforms and remove the original limitations. - -In SDL3, we've taken this much, much further. - -## The main entry point in SDL3 - -SDL3 still has the same macro tricks, but the static library is gone. Now it's -supplied by a "single-header library," which is to say you -`#include ` and that header will insert a small amount of -code into the source file that included it, so you no longer have to worry -about linking against an extra library that you might need on some platforms. -You just build your app and it works. - -You should _only_ include SDL_main.h from one file (the umbrella header, -SDL.h, does _not_ include it), and know that it will `#define main` to -something else, so if you use this symbol elsewhere as a variable name, etc, -it can cause you unexpected problems. - -SDL_main.h will also include platform-specific code (WinMain or whatnot) that -calls your _actual_ main function. This is compiled directly into your -program. - -If for some reason you need to include SDL_main.h in a file but also _don't_ -want it to generate this platform-specific code, you should define a special -macro before includin the header: - - -```c -#define SDL_MAIN_NOIMPL -``` - -If you are moving from SDL2, remove any references to the SDLmain static -library from your build system, and you should be done. Things should work as -they always have. - -If you have never controlled your process's entry point (you are using SDL -as a module from a general-purpose scripting language interpreter, or you're -SDL in a plugin for some otherwise-unrelated app), then there is nothing -required of you here; there is no startup code in SDL's entry point code that -is required, so using SDL_main.h is completely optional. Just start using -the SDL API when you are ready. - - -## Main callbacks in SDL3 - -There is a second option in SDL3 for how to structure your program. This is -completly optional and you can ignore it if you're happy using a standard -"main" function. - -Some platforms would rather your program operate in chunks. Most of the time, -games tend to look like this at the highest level: - -```c -int main(int argc, char **argv) -{ - initialize(); - while (keep_running()) { - handle_new_events(); - do_one_frame_of_stuff(); - } - deinitialize(); -} -``` - -There are platforms that would rather be in charge of that `while` loop: -iOS would rather you return from main() immediately and then it will let you -know that it's time to update and draw the next frame of video. Emscripten -(programs that run on a web page) absolutely requires this to function at all. -Video targets like Wayland can notify the app when to draw a new frame, to -save battery life and cooperate with the compositor more closely. - -In most cases, you can add special-case code to your program to deal with this -on different platforms, but SDL3 offers a system to handle transparently on -the app's behalf. - -To use this, you have to redesign the highest level of your app a little. Once -you do, it'll work on all supported SDL platforms without problems and -`#ifdef`s in your code. - -Instead of providing a "main" function, under this system, you would provide -several functions that SDL will call as appropriate. - -Using the callback entry points works on every platform, because on platforms -that don't require them, we can fake them with a simple loop in an internal -implementation of the usual SDL_main. - -The primary way we expect people to write SDL apps is still with SDL_main, and -this is not intended to replace it. If the app chooses to use this, it just -removes some platform-specific details they might have to otherwise manage, -and maybe removes a barrier to entry on some future platform. And you might -find you enjoy structuring your program like this more! - - -## How to use main callbacks in SDL3 - -To enable the callback entry points, you include SDL_main with an extra define -from a single source file in your project: - -```c -#define SDL_MAIN_USE_CALLBACKS -#include -``` - -Once you do this, you do not include a "main" function at all (and if you do, -the app will likely fail to link). Instead, you provide the following -functions: - -First: - -```c -int SDL_AppInit(int argc, char **argv); -``` - -This will be called _once_ before anything else. argc/argv work like they -always do. If this returns 0, the app runs. If it returns < 0, the app calls -SDL_AppQuit and terminates with an exit code that reports an error to the -platform. If it returns > 0, the app calls SDL_AppQuit and terminates with -an exit code that reports success to the platform. This function should not -go into an infinite mainloop; it should do any one-time startup it requires -and then return. - -Then: - -```c -int SDL_AppIterate(void); -``` - -This is called over and over, possibly at the refresh rate of the display or -some other metric that the platform dictates. This is where the heart of your -app runs. It should return as quickly as reasonably possible, but it's not a -"run one memcpy and that's all the time you have" sort of thing. The app -should do any game updates, and render a frame of video. If it returns < 0, -SDL will call SDL_AppQuit and terminate the process with an exit code that -reports an error to the platform. If it returns > 0, the app calls -SDL_AppQuit and terminates with an exit code that reports success to the -platform. If it returns 0, then SDL_AppIterate will be called again at some -regular frequency. The platform may choose to run this more or less (perhaps -less in the background, etc), or it might just call this function in a loop -as fast as possible. You do not check the event queue in this function -(SDL_AppEvent exists for that). - -Next: - -```c -int SDL_AppEvent(const SDL_Event *event); -``` - -This will be called once for each event pushed into the SDL queue. This may be -called from any thread, and possibly in parallel to SDL_AppIterate. The fields -in `event` do not need to be free'd (as you would normally need to do for -SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, -SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the -same as from SDL_AppIterate(), so you can terminate in response to -SDL_EVENT_QUIT, etc. - - -Finally: - -```c -void SDL_AppQuit(void); -``` - -This is called once before terminating the app--assuming the app isn't being -forcibly killed or crashed--as a last chance to clean up. After this returns, -SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app -to call it, too). Process termination proceeds as if the app returned normally -from main(), so atexit handles will run, if your platform supports that. - - +# Where an SDL program starts running. + +## History + +SDL has a long, complicated history with starting a program. + +In most of the civilized world, an application starts in a C-callable +function named "main". You probably learned it a long time ago: + +```c +int main(int argc, char **argv) +{ + printf("Hello world!\n"); + return 0; +} +``` + +But not all platforms work like this. Windows apps might want a different +function named "WinMain", for example, so SDL set out to paper over this +difference. + +Generally how this would work is: your app would always use the "standard" +`main(argc, argv)` function as its entry point, and `#include` the proper +SDL header before that, which did some macro magic. On platforms that used +a standard `main`, it would do nothing and what you saw was what you got. + +But those other platforms! If they needed something that _wasn't_ `main`, +SDL's macro magic would quietly rename your function to `SDL_main`, and +provide its own entry point that called it. Your app was none the wiser and +your code worked everywhere without changes. + +In SDL1, you linked with a static library that had startup code that _had_ to +run before you hit SDL_main(). For example, on macOS it would do various +magic to the process to make sure it was in the right state. Windows would +register win32 window classes and such. Things would break if you tried to +circumvent this, and you were in for a lot of trouble if you tried to use +SDL on a platform that needed this when you didn't control the entry point +(for example, as a plugin, or an SDL binding in a scripting language). + +In SDL2, the necessary support code moved into the main library, and the tiny +static library _only_ handled the basics of getting from the platform's real +entry point (like WinMain) to SDL_main; if the real entry was _already_ +standard main, the static library and macro magic was unnecessary. The goal +was to make it so you didn't have to change _your_ code to work on multiple +platforms and remove the original limitations. + +In SDL3, we've taken this much, much further. + +## The main entry point in SDL3 + +SDL3 still has the same macro tricks, but the static library is gone. Now it's +supplied by a "single-header library," which is to say you +`#include ` and that header will insert a small amount of +code into the source file that included it, so you no longer have to worry +about linking against an extra library that you might need on some platforms. +You just build your app and it works. + +You should _only_ include SDL_main.h from one file (the umbrella header, +SDL.h, does _not_ include it), and know that it will `#define main` to +something else, so if you use this symbol elsewhere as a variable name, etc, +it can cause you unexpected problems. + +SDL_main.h will also include platform-specific code (WinMain or whatnot) that +calls your _actual_ main function. This is compiled directly into your +program. + +If for some reason you need to include SDL_main.h in a file but also _don't_ +want it to generate this platform-specific code, you should define a special +macro before includin the header: + + +```c +#define SDL_MAIN_NOIMPL +``` + +If you are moving from SDL2, remove any references to the SDLmain static +library from your build system, and you should be done. Things should work as +they always have. + +If you have never controlled your process's entry point (you are using SDL +as a module from a general-purpose scripting language interpreter, or you're +SDL in a plugin for some otherwise-unrelated app), then there is nothing +required of you here; there is no startup code in SDL's entry point code that +is required, so using SDL_main.h is completely optional. Just start using +the SDL API when you are ready. + + +## Main callbacks in SDL3 + +There is a second option in SDL3 for how to structure your program. This is +completly optional and you can ignore it if you're happy using a standard +"main" function. + +Some platforms would rather your program operate in chunks. Most of the time, +games tend to look like this at the highest level: + +```c +int main(int argc, char **argv) +{ + initialize(); + while (keep_running()) { + handle_new_events(); + do_one_frame_of_stuff(); + } + deinitialize(); +} +``` + +There are platforms that would rather be in charge of that `while` loop: +iOS would rather you return from main() immediately and then it will let you +know that it's time to update and draw the next frame of video. Emscripten +(programs that run on a web page) absolutely requires this to function at all. +Video targets like Wayland can notify the app when to draw a new frame, to +save battery life and cooperate with the compositor more closely. + +In most cases, you can add special-case code to your program to deal with this +on different platforms, but SDL3 offers a system to handle transparently on +the app's behalf. + +To use this, you have to redesign the highest level of your app a little. Once +you do, it'll work on all supported SDL platforms without problems and +`#ifdef`s in your code. + +Instead of providing a "main" function, under this system, you would provide +several functions that SDL will call as appropriate. + +Using the callback entry points works on every platform, because on platforms +that don't require them, we can fake them with a simple loop in an internal +implementation of the usual SDL_main. + +The primary way we expect people to write SDL apps is still with SDL_main, and +this is not intended to replace it. If the app chooses to use this, it just +removes some platform-specific details they might have to otherwise manage, +and maybe removes a barrier to entry on some future platform. And you might +find you enjoy structuring your program like this more! + + +## How to use main callbacks in SDL3 + +To enable the callback entry points, you include SDL_main with an extra define +from a single source file in your project: + +```c +#define SDL_MAIN_USE_CALLBACKS +#include +``` + +Once you do this, you do not include a "main" function at all (and if you do, +the app will likely fail to link). Instead, you provide the following +functions: + +First: + +```c +int SDL_AppInit(int argc, char **argv); +``` + +This will be called _once_ before anything else. argc/argv work like they +always do. If this returns 0, the app runs. If it returns < 0, the app calls +SDL_AppQuit and terminates with an exit code that reports an error to the +platform. If it returns > 0, the app calls SDL_AppQuit and terminates with +an exit code that reports success to the platform. This function should not +go into an infinite mainloop; it should do any one-time startup it requires +and then return. + +Then: + +```c +int SDL_AppIterate(void); +``` + +This is called over and over, possibly at the refresh rate of the display or +some other metric that the platform dictates. This is where the heart of your +app runs. It should return as quickly as reasonably possible, but it's not a +"run one memcpy and that's all the time you have" sort of thing. The app +should do any game updates, and render a frame of video. If it returns < 0, +SDL will call SDL_AppQuit and terminate the process with an exit code that +reports an error to the platform. If it returns > 0, the app calls +SDL_AppQuit and terminates with an exit code that reports success to the +platform. If it returns 0, then SDL_AppIterate will be called again at some +regular frequency. The platform may choose to run this more or less (perhaps +less in the background, etc), or it might just call this function in a loop +as fast as possible. You do not check the event queue in this function +(SDL_AppEvent exists for that). + +Next: + +```c +int SDL_AppEvent(const SDL_Event *event); +``` + +This will be called once for each event pushed into the SDL queue. This may be +called from any thread, and possibly in parallel to SDL_AppIterate. The fields +in `event` do not need to be free'd (as you would normally need to do for +SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, +SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the +same as from SDL_AppIterate(), so you can terminate in response to +SDL_EVENT_QUIT, etc. + + +Finally: + +```c +void SDL_AppQuit(void); +``` + +This is called once before terminating the app--assuming the app isn't being +forcibly killed or crashed--as a last chance to clean up. After this returns, +SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app +to call it, too). Process termination proceeds as if the app returned normally +from main(), so atexit handles will run, if your platform supports that. + + From a76d8e39aa3c7e136eba58290880a7cbbc4f5faf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 08:44:26 -0700 Subject: [PATCH 200/725] Changed SDL_bool from an enum to unsigned int Fixes https://github.com/libsdl-org/SDL/issues/7957 --- include/SDL3/SDL_stdinc.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index a3d63325c3f24..43aaafc03adcd 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -122,18 +122,12 @@ char *alloca(); */ /* @{ */ -#ifdef __CC_ARM -/* ARM's compiler throws warnings if we use an enum: like "SDL_bool x = a < b;" */ +/** + * \brief A boolean type. + */ #define SDL_FALSE 0 #define SDL_TRUE 1 -typedef int SDL_bool; -#else -typedef enum -{ - SDL_FALSE = 0, - SDL_TRUE = 1 -} SDL_bool; -#endif +typedef unsigned int SDL_bool; /** * \brief A signed 8-bit integer type. From f3261fedcc81938f6e75b0e05652901a0b961da7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 09:27:29 -0700 Subject: [PATCH 201/725] Code cleanup now that SDL_bool is equivalent to a C boolean expression --- src/SDL.c | 4 +-- src/SDL_hashtable.c | 2 +- src/atomic/SDL_atomic.c | 16 +++++------ src/atomic/SDL_spinlock.c | 4 +-- src/audio/SDL_audio.c | 32 ++++++++++----------- src/audio/SDL_audiocvt.c | 2 +- src/audio/alsa/SDL_alsa_audio.c | 2 +- src/audio/coreaudio/SDL_coreaudio.m | 2 +- src/audio/emscripten/SDL_emscriptenaudio.c | 8 +++--- src/audio/pulseaudio/SDL_pulseaudio.c | 8 +++--- src/audio/wasapi/SDL_wasapi_winrt.cpp | 2 +- src/core/android/SDL_android.c | 7 ++--- src/core/linux/SDL_dbus.c | 2 +- src/core/linux/SDL_ibus.c | 2 +- src/events/SDL_events.c | 2 +- src/events/SDL_mouse.c | 4 +-- src/file/SDL_rwops.c | 14 ++++----- src/haptic/windows/SDL_xinputhaptic.c | 2 +- src/joystick/SDL_joystick.c | 2 +- src/joystick/hidapi/SDL_hidapi_ps4.c | 2 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 2 +- src/joystick/hidapi/SDL_hidapi_switch.c | 4 +-- src/joystick/hidapi/SDL_hidapi_wii.c | 8 +++--- src/joystick/hidapi/SDL_hidapi_xbox360.c | 4 +-- src/joystick/hidapi/SDL_hidapi_xboxone.c | 2 +- src/joystick/windows/SDL_rawinputjoystick.c | 2 +- src/joystick/windows/SDL_windowsjoystick.c | 4 +-- src/joystick/windows/SDL_xinputjoystick.c | 2 +- src/render/direct3d/SDL_render_d3d.c | 2 +- src/sensor/SDL_sensor.c | 2 +- src/stdlib/SDL_string.c | 2 +- src/test/SDL_test_common.c | 6 ++-- src/video/SDL_shape.c | 10 +++---- src/video/SDL_video.c | 30 +++++++++---------- src/video/emscripten/SDL_emscriptenvideo.c | 2 +- src/video/gdk/SDL_gdktextinput.cpp | 2 +- src/video/haiku/SDL_bclipboard.cc | 2 +- src/video/wayland/SDL_waylandevents.c | 6 ++-- src/video/wayland/SDL_waylandtouch.c | 2 +- src/video/wayland/SDL_waylandvideo.c | 2 +- src/video/wayland/SDL_waylandwindow.c | 4 +-- src/video/windows/SDL_windowsevents.c | 4 +-- src/video/windows/SDL_windowskeyboard.c | 4 +-- src/video/windows/SDL_windowsopengl.c | 5 +--- src/video/windows/SDL_windowsvideo.c | 3 +- src/video/x11/SDL_x11video.c | 2 +- src/video/x11/SDL_x11xinput2.c | 2 +- test/checkkeys.c | 2 +- test/checkkeysthreads.c | 2 +- test/testatomic.c | 16 +++++------ test/testaudio.c | 6 ++-- test/testaudiostreamdynamicresample.c | 4 +-- test/testshader.c | 2 +- 53 files changed, 133 insertions(+), 138 deletions(-) diff --git a/src/SDL.c b/src/SDL.c index 235233ce1ed1f..7ff9711cc2eac 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -137,7 +137,7 @@ static SDL_bool SDL_ShouldInitSubsystem(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); - return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) ? SDL_TRUE : SDL_FALSE; + return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)); } /* Private helper to check if a system needs to be quit. */ @@ -151,7 +151,7 @@ static SDL_bool SDL_ShouldQuitSubsystem(Uint32 subsystem) /* If we're in SDL_Quit, we shut down every subsystem, even if refcount * isn't zero. */ - return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE; + return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit); } void SDL_SetMainReady(void) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index e3133fe8623cf..1c3c7bb63b6c9 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -256,7 +256,7 @@ SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) } else if (!a || !b) { return SDL_FALSE; // one pointer is NULL (and first test shows they aren't the same pointer), must not match. } - return (SDL_strcmp((const char *)a, (const char *)b) == 0) ? SDL_TRUE : SDL_FALSE; // Check against actual string contents. + return (SDL_strcmp((const char *)a, (const char *)b) == 0); // Check against actual string contents. } // We assume we can fit the ID in the key directly diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index 4164a5f714415..5ffa2e61eabd0 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -128,13 +128,13 @@ SDL_bool SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval) SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(long) == sizeof(a->value)); return _InterlockedCompareExchange((long *)&a->value, (long)newval, (long)oldval) == (long)oldval; #elif defined(HAVE_WATCOM_ATOMICS) - return (SDL_bool)_SDL_cmpxchg_watcom(&a->value, newval, oldval); + return _SDL_cmpxchg_watcom(&a->value, newval, oldval); #elif defined(HAVE_GCC_ATOMICS) - return (SDL_bool)__sync_bool_compare_and_swap(&a->value, oldval, newval); + return __sync_bool_compare_and_swap(&a->value, oldval, newval); #elif defined(__MACOS__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ - return (SDL_bool)OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value); + return OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value); #elif defined(__SOLARIS__) - return (SDL_bool)((int)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval); + return ((int)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval); #elif defined(EMULATE_CAS) SDL_bool retval = SDL_FALSE; @@ -156,15 +156,15 @@ SDL_bool SDL_AtomicCASPtr(void **a, void *oldval, void *newval) #ifdef HAVE_MSC_ATOMICS return _InterlockedCompareExchangePointer(a, newval, oldval) == oldval; #elif defined(HAVE_WATCOM_ATOMICS) - return (SDL_bool)_SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval); + return _SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval); #elif defined(HAVE_GCC_ATOMICS) return __sync_bool_compare_and_swap(a, oldval, newval); #elif defined(__MACOS__) && defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ - return (SDL_bool)OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t *)a); + return OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t *)a); #elif defined(__MACOS__) && !defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ - return (SDL_bool)OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)a); + return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)a); #elif defined(__SOLARIS__) - return (SDL_bool)(atomic_cas_ptr(a, oldval, newval) == oldval); + return (atomic_cas_ptr(a, oldval, newval) == oldval); #elif defined(EMULATE_CAS) SDL_bool retval = SDL_FALSE; diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index d4eaff41c6022..6f37fa52ad36f 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -139,11 +139,11 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) #elif defined(__SOLARIS__) && defined(_LP64) /* Used for Solaris with non-gcc compilers. */ - return (SDL_bool)((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0); + return ((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0); #elif defined(__SOLARIS__) && !defined(_LP64) /* Used for Solaris with non-gcc compilers. */ - return (SDL_bool)((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0); + return ((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0); #elif defined(PS2) uint32_t oldintr; SDL_bool res = SDL_FALSE; diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index bb6acbe2bffb7..ef93f82817254 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -190,7 +190,7 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) !device->logical_devices->postmix && // there isn't a postmix callback device->logical_devices->bound_streams && // there's a bound stream !device->logical_devices->bound_streams->next_binding // there's only _ONE_ bound stream. - ) ? SDL_TRUE : SDL_FALSE; + ); } // should hold device->lock before calling. @@ -320,7 +320,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_LogicalAudioDevice *logdev = NULL; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool islogical = !(devid & (1<<1)); if (islogical) { // don't bother looking if it's not a logical device id value. SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); @@ -349,7 +349,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // ! SDL_AudioDevice *device = NULL; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool islogical = !(devid & (1<<1)); if (islogical) { ObtainLogicalAudioDevice(devid, &device); } else if (!SDL_GetCurrentAudioDriver()) { // (the `islogical` path, above, checks this in ObtainLogicalAudioDevice.) @@ -371,7 +371,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // ! static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE { - const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); if (!wants_default) { return ObtainPhysicalAudioDevice(devid); } @@ -623,7 +623,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) SDL_LockRWLockForReading(current_audio.device_hash_lock); const SDL_AudioDeviceID devid = device->instance_id; - const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)); SDL_UnlockRWLock(current_audio.device_hash_lock); const SDL_bool first_disconnect = SDL_AtomicCAS(&device->zombie, 0, 1); @@ -763,8 +763,8 @@ static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; // bit #0 of devid is set for output devices and unset for capture. // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool devid_iscapture = (devid & (1 << 0)) ? SDL_FALSE : SDL_TRUE; - const SDL_bool isphysical = (devid & (1 << 1)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool devid_iscapture = !(devid & (1 << 0)); + const SDL_bool isphysical = (devid & (1 << 1)); if (isphysical && (devid_iscapture == iscapture) && (devid < highest)) { highest = devid; retval = (SDL_AudioDevice *) value; @@ -784,7 +784,7 @@ static Uint32 HashAudioDeviceID(const void *key, void *data) static SDL_bool MatchAudioDeviceID(const void *a, const void *b, void *data) { - return (a == b) ? SDL_TRUE : SDL_FALSE; // they're simple Uint32 values cast to pointers. + return (a == b); } static void NukeAudioDeviceHashItem(const void *key, const void *value, void *data) @@ -966,7 +966,7 @@ void SDL_QuitAudio(void) while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { // bit #1 of devid is set for physical devices and unset for logical. const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; - const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool isphysical = (devid & (1<<1)); if (isphysical) { DestroyPhysicalAudioDevice((SDL_AudioDevice *) value); } @@ -1273,8 +1273,8 @@ static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_bool iscapture) const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; // bit #0 of devid is set for output devices and unset for capture. // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool devid_iscapture = (devid & (1<<0)) ? SDL_FALSE : SDL_TRUE; - const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool devid_iscapture = !(devid & (1<<0)); + const SDL_bool isphysical = (devid & (1<<1)); if (isphysical && (devid_iscapture == iscapture)) { SDL_assert(devs_seen < num_devices); retval[devs_seen++] = devid; @@ -1320,7 +1320,7 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_ while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool isphysical = (devid & (1<<1)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool isphysical = (devid & (1<<1)); if (isphysical) { SDL_AudioDevice *device = (SDL_AudioDevice *) value; if (callback(device, userdata)) { // found it? @@ -1577,11 +1577,11 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp return 0; } - SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) ? SDL_TRUE : SDL_FALSE; + SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); // this will let you use a logical device to make a new logical device on the parent physical device. Could be useful? SDL_AudioDevice *device = NULL; - const SDL_bool islogical = (wants_default || (devid & (1<<1))) ? SDL_FALSE : SDL_TRUE; + const SDL_bool islogical = (!wants_default && !(devid & (1<<1))); if (!islogical) { device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); } else { @@ -1700,7 +1700,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams) { - const SDL_bool islogical = (devid & (1<<1)) ? SDL_FALSE : SDL_TRUE; + const SDL_bool islogical = !(devid & (1<<1)); SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = NULL; int retval = 0; @@ -1969,7 +1969,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) // change the official default over right away, so new opens will go to the new device. SDL_LockRWLockForWriting(current_audio.device_hash_lock); const SDL_AudioDeviceID current_devid = iscapture ? current_audio.default_capture_device_id : current_audio.default_output_device_id; - const SDL_bool is_already_default = (new_default_device->instance_id == current_devid) ? SDL_TRUE : SDL_FALSE; + const SDL_bool is_already_default = (new_default_device->instance_id == current_devid); if (!is_already_default) { if (iscapture) { current_audio.default_capture_device_id = new_default_device->instance_id; diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index b64ca480dc848..f4eb332a29815 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -207,7 +207,7 @@ static SDL_bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt) static SDL_bool SDL_IsSupportedChannelCount(const int channels) { - return ((channels >= 1) && (channels <= 8)) ? SDL_TRUE : SDL_FALSE; + return ((channels >= 1) && (channels <= 8)); } diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 46ba1dc797267..4a076419f9f84 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -818,7 +818,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de } // only want physical hardware interfaces - const SDL_bool is_default = (has_default == i) ? SDL_TRUE : SDL_FALSE; + const SDL_bool is_default = (has_default == i); if (is_default || (match != NULL && SDL_strncmp(name, match, match_len) == 0)) { char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID"); const SDL_bool isoutput = (ioid == NULL) || (SDL_strcmp(ioid, "Output") == 0); diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 0cb1d3f9c3518..807ad8a675f74 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -185,7 +185,7 @@ static void RefreshPhysicalDevices(void) CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8); char *name = (char *)SDL_malloc(len + 1); - SDL_bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8))) ? SDL_TRUE : SDL_FALSE; + SDL_bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8))); CFRelease(cfstr); diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 32afd20bc87ae..51eec747e1440 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -321,7 +321,7 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) return true; } return false; - }) ? SDL_TRUE : SDL_FALSE; + }); if (!available) { SDL_SetError("No audio context available"); @@ -334,10 +334,10 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) return true; } return false; - }) ? SDL_TRUE : SDL_FALSE; + }); - impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE; - impl->OnlyHasDefaultCaptureDevice = capture_available ? SDL_TRUE : SDL_FALSE; + impl->HasCaptureSupport = capture_available; + impl->OnlyHasDefaultCaptureDevice = capture_available; return available; } diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 0a4d231efc018..0612d88089f73 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -832,14 +832,14 @@ static SDL_bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata) { const uint32_t idx = (uint32_t) (uintptr_t) userdata; const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; - return (handle->device_index == idx) ? SDL_TRUE : SDL_FALSE; + return (handle->device_index == idx); } static SDL_bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata) { const char *path = (const char *) userdata; const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; - return (SDL_strcmp(handle->device_path, path) == 0) ? SDL_TRUE : SDL_FALSE; + return (SDL_strcmp(handle->device_path, path) == 0); } // This is called when PulseAudio has a device connected/removed/changed. @@ -925,8 +925,8 @@ static int SDLCALL HotplugThread(void *data) SDL_free(current_default_source); // set these to true if we didn't handle the change OR there was _another_ change while we were working unlocked. - default_sink_changed = (default_sink_changed || check_default_sink) ? SDL_TRUE : SDL_FALSE; - default_source_changed = (default_source_changed || check_default_source) ? SDL_TRUE : SDL_FALSE; + default_sink_changed = (default_sink_changed || check_default_sink); + default_source_changed = (default_source_changed || check_default_source); } if (op) { diff --git a/src/audio/wasapi/SDL_wasapi_winrt.cpp b/src/audio/wasapi/SDL_wasapi_winrt.cpp index f3aeadc794379..7fce6776051e0 100644 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp @@ -55,7 +55,7 @@ static Platform::String ^ SDL_PKEY_AudioEngine_DeviceFormat = L"{f19f064d-082c-4 static SDL_bool FindWinRTAudioDeviceCallback(SDL_AudioDevice *device, void *userdata) { - return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0) ? SDL_TRUE : SDL_FALSE; + return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0); } static SDL_AudioDevice *FindWinRTAudioDevice(LPCWSTR devid) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 8bf816610a0d1..99ebd7492de7e 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -1011,7 +1011,7 @@ SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_c void *handle = (void *)((size_t)device_id); if (!SDL_FindPhysicalAudioDeviceByHandle(handle)) { const char *utf8name = (*env)->GetStringUTFChars(env, name, NULL); - SDL_AddAudioDevice(is_capture ? SDL_TRUE : SDL_FALSE, SDL_strdup(utf8name), NULL, handle); + SDL_AddAudioDevice(is_capture, SDL_strdup(utf8name), NULL, handle); (*env)->ReleaseStringUTFChars(env, name, utf8name); } } @@ -1072,7 +1072,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)( const char *name = (*env)->GetStringUTFChars(env, device_name, NULL); const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL); - retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, is_accelerometer ? SDL_TRUE : SDL_FALSE, button_mask, naxes, axis_mask, nhats); + retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, is_accelerometer, button_mask, naxes, axis_mask, nhats); (*env)->ReleaseStringUTFChars(env, device_name, name); (*env)->ReleaseStringUTFChars(env, device_desc, desc); @@ -2057,8 +2057,7 @@ char *Android_JNI_GetClipboardText(void) SDL_bool Android_JNI_HasClipboardText(void) { JNIEnv *env = Android_JNI_GetEnv(); - jboolean retval = (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText); - return (retval == JNI_TRUE) ? SDL_TRUE : SDL_FALSE; + return (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText); } /* returns 0 on success or -1 on error (others undefined then) diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index ba961be042855..14154319f1e28 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -508,7 +508,7 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { return SDL_FALSE; } - return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE; + return (screensaver_cookie != 0); } else { if (!SDL_DBus_CallVoidMethod(bus_name, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { return SDL_FALSE; diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 92475c2579fae..592dc9d49e764 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -696,7 +696,7 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) SDL_IBus_UpdateTextRect(NULL); - return result ? SDL_TRUE : SDL_FALSE; + return (result != 0); } void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 7bf48cad09590..bd926f3d7625f 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -1036,7 +1036,7 @@ int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_Window *wakeup_window; Uint64 start, expiration; - SDL_bool include_sentinel = (timeoutNS == 0) ? SDL_TRUE : SDL_FALSE; + SDL_bool include_sentinel = (timeoutNS == 0); int result; /* If there isn't a poll sentinel event pending, pump events and add one */ diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index ee9d4a25776c5..fc38e682a2304 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -392,7 +392,7 @@ int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); - if (!SDL_UpdateMouseFocus(window, x, y, GetButtonState(mouse, SDL_TRUE), (mouseID == SDL_TOUCH_MOUSEID) ? SDL_FALSE : SDL_TRUE)) { + if (!SDL_UpdateMouseFocus(window, x, y, GetButtonState(mouse, SDL_TRUE), (mouseID != SDL_TOUCH_MOUSEID))) { return 0; } } @@ -656,7 +656,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; /* Set us pending (or clear during a normal mouse movement event) as having triggered */ - mouse->was_touch_mouse_events = (mouseID == SDL_TOUCH_MOUSEID) ? SDL_TRUE : SDL_FALSE; + mouse->was_touch_mouse_events = (mouseID == SDL_TOUCH_MOUSEID); event.motion.state = GetButtonState(mouse, SDL_TRUE); event.motion.x = mouse->x; event.motion.y = mouse->y; diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index aa429609982f5..049cf51206de5 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -952,13 +952,13 @@ SDL_bool SDL_ReadS64BE(SDL_RWops *src, Sint64 *value) SDL_bool SDL_WriteU8(SDL_RWops *dst, Uint8 value) { - return (SDL_RWwrite(dst, &value, sizeof(value)) == sizeof(value)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &value, sizeof(value)) == sizeof(value)); } SDL_bool SDL_WriteU16LE(SDL_RWops *dst, Uint16 value) { const Uint16 swapped = SDL_SwapLE16(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS16LE(SDL_RWops *dst, Sint16 value) @@ -969,7 +969,7 @@ SDL_bool SDL_WriteS16LE(SDL_RWops *dst, Sint16 value) SDL_bool SDL_WriteU16BE(SDL_RWops *dst, Uint16 value) { const Uint16 swapped = SDL_SwapBE16(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS16BE(SDL_RWops *dst, Sint16 value) @@ -980,7 +980,7 @@ SDL_bool SDL_WriteS16BE(SDL_RWops *dst, Sint16 value) SDL_bool SDL_WriteU32LE(SDL_RWops *dst, Uint32 value) { const Uint32 swapped = SDL_SwapLE32(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS32LE(SDL_RWops *dst, Sint32 value) @@ -991,7 +991,7 @@ SDL_bool SDL_WriteS32LE(SDL_RWops *dst, Sint32 value) SDL_bool SDL_WriteU32BE(SDL_RWops *dst, Uint32 value) { const Uint32 swapped = SDL_SwapBE32(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS32BE(SDL_RWops *dst, Sint32 value) @@ -1002,7 +1002,7 @@ SDL_bool SDL_WriteS32BE(SDL_RWops *dst, Sint32 value) SDL_bool SDL_WriteU64LE(SDL_RWops *dst, Uint64 value) { const Uint64 swapped = SDL_SwapLE64(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS64LE(SDL_RWops *dst, Sint64 value) @@ -1013,7 +1013,7 @@ SDL_bool SDL_WriteS64LE(SDL_RWops *dst, Sint64 value) SDL_bool SDL_WriteU64BE(SDL_RWops *dst, Uint64 value) { const Uint64 swapped = SDL_SwapBE64(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)) ? SDL_TRUE : SDL_FALSE; + return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } SDL_bool SDL_WriteS64BE(SDL_RWops *dst, Sint64 value) diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index 681b4571ea9fc..d4add0da6dc9a 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -43,7 +43,7 @@ static SDL_bool loaded_xinput = SDL_FALSE; int SDL_XINPUT_HapticInit(void) { if (SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE)) { - loaded_xinput = (WIN_LoadXInputDLL() == 0) ? SDL_TRUE : SDL_FALSE; + loaded_xinput = (WIN_LoadXInputDLL() == 0); } /* If the joystick subsystem is active, it will manage adding XInput haptic devices */ diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index bf5b1f4f56a31..d657b02acb579 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -181,7 +181,7 @@ void SDL_UnlockJoysticks(void) SDL_bool SDL_JoysticksLocked(void) { - return (SDL_joysticks_locked > 0) ? SDL_TRUE : SDL_FALSE; + return (SDL_joysticks_locked > 0); } void SDL_AssertJoysticksLocked(void) diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 47ea29042b32f..1fb377bfa3918 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -1131,7 +1131,7 @@ static SDL_bool VerifyCRC(Uint8 *data, int size) packetCRC[1], packetCRC[2], packetCRC[3]); - return (unCRC == unPacketCRC) ? SDL_TRUE : SDL_FALSE; + return (unCRC == unPacketCRC); } static SDL_bool HIDAPI_DriverPS4_IsPacketValid(SDL_DriverPS4_Context *ctx, Uint8 *data, int size) diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 8446c553cee2c..6a6f7b1e2f566 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -1429,7 +1429,7 @@ static SDL_bool VerifyCRC(Uint8 *data, int size) packetCRC[1], packetCRC[2], packetCRC[3]); - return (unCRC == unPacketCRC) ? SDL_TRUE : SDL_FALSE; + return (unCRC == unPacketCRC); } static SDL_bool HIDAPI_DriverPS5_IsPacketValid(SDL_DriverPS5_Context *ctx, Uint8 *data, int size) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 0da65eb7fb1af..f5b0f185580a0 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -1192,7 +1192,7 @@ static SDL_bool HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device, return SDL_FALSE; } - return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE; + return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO); } static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device) @@ -1466,7 +1466,7 @@ static int HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context * SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]); } - ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE; + ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble); if (!WriteRumble(ctx)) { return SDL_SetError("Couldn't send rumble packet"); diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 397d5550bec12..037cf0252b55c 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -505,8 +505,8 @@ static void UpdatePowerLevelWii(SDL_Joystick *joystick, Uint8 batteryLevelByte) static void UpdatePowerLevelWiiU(SDL_Joystick *joystick, Uint8 extensionBatteryByte) { - SDL_bool charging = extensionBatteryByte & 0x08 ? SDL_FALSE : SDL_TRUE; - SDL_bool pluggedIn = extensionBatteryByte & 0x04 ? SDL_FALSE : SDL_TRUE; + SDL_bool charging = !(extensionBatteryByte & 0x08); + SDL_bool pluggedIn = !(extensionBatteryByte & 0x04); Uint8 batteryLevel = extensionBatteryByte >> 4; /* Not sure if all Wii U Pro controllers act like this, but on mine @@ -814,7 +814,7 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy static int HIDAPI_DriverWii_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; - SDL_bool active = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE; + SDL_bool active = (low_frequency_rumble || high_frequency_rumble); if (active != ctx->m_bRumbleActive) { Uint8 data[2]; @@ -1407,7 +1407,7 @@ static void GetExtensionData(WiiButtonData *dst, const Uint8 *src, int size) static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick) { SDL_bool hadExtension = ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_None; - SDL_bool hasExtension = ctx->m_rgucReadBuffer[3] & 2 ? SDL_TRUE : SDL_FALSE; + SDL_bool hasExtension = (ctx->m_rgucReadBuffer[3] & 2) ? SDL_TRUE : SDL_FALSE; WiiButtonData data; SDL_zero(data); GetBaseButtons(&data, ctx->m_rgucReadBuffer + 1); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index c2dddccf2c08f..cefde2b8d8536 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -94,9 +94,9 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device if (SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) { return SDL_FALSE; } - return (type == SDL_GAMEPAD_TYPE_XBOX360 || type == SDL_GAMEPAD_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE; + return (type == SDL_GAMEPAD_TYPE_XBOX360 || type == SDL_GAMEPAD_TYPE_XBOXONE); #else - return (type == SDL_GAMEPAD_TYPE_XBOX360) ? SDL_TRUE : SDL_FALSE; + return (type == SDL_GAMEPAD_TYPE_XBOX360); #endif } diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 1a49990ecda97..dc86c0718f7a4 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -351,7 +351,7 @@ static SDL_bool HIDAPI_DriverXboxOne_IsSupportedDevice(SDL_HIDAPI_Device *device return SDL_FALSE; } #endif - return (type == SDL_GAMEPAD_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE; + return (type == SDL_GAMEPAD_TYPE_XBOXONE); } static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device) diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 468dd92acea36..4bdb3cf3a5772 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -331,7 +331,7 @@ static void RAWINPUT_UpdateXInput() if (xinput_device_change) { for (user_index = 0; user_index < XUSER_MAX_COUNT; user_index++) { XINPUT_CAPABILITIES capabilities; - xinput_state[user_index].connected = (XINPUTGETCAPABILITIES(user_index, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE; + xinput_state[user_index].connected = (XINPUTGETCAPABILITIES(user_index, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS); } xinput_device_change = SDL_FALSE; xinput_state_dirty = SDL_TRUE; diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 173ac431edb4e..a329ebfb281cc 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -336,7 +336,7 @@ static SDL_bool SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, } } SDL_LockMutex(mutex); - return (lastret != -1) ? SDL_TRUE : SDL_FALSE; + return (lastret != -1); } #endif /* !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) */ @@ -377,7 +377,7 @@ static int SDLCALL SDL_JoystickThread(void *_data) for (userId = 0; userId < XUSER_MAX_COUNT; userId++) { XINPUT_CAPABILITIES capabilities; const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities); - const SDL_bool available = (result == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE; + const SDL_bool available = (result == ERROR_SUCCESS); if (bOpenedXInputDevices[userId] != available) { s_bWindowsDeviceChanged = SDL_TRUE; bOpenedXInputDevices[userId] = available; diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index debc6d443627e..fe45ed61f8685 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -377,7 +377,7 @@ int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystic return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?"); } SDL_zero(state); - joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE; + joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS); joystick->hwdata->userid = userId; /* The XInput API has a hard coded button/axis mapping, so we just match it */ diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index e04ae37532982..02c8cb3718cdf 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1186,7 +1186,7 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v const SDL_Rect *viewport = &data->drawstate.viewport; const int backw = istarget ? renderer->target->w : data->pparams.BackBufferWidth; const int backh = istarget ? renderer->target->h : data->pparams.BackBufferHeight; - const SDL_bool viewport_equal = ((viewport->x == 0) && (viewport->y == 0) && (viewport->w == backw) && (viewport->h == backh)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool viewport_equal = ((viewport->x == 0) && (viewport->y == 0) && (viewport->w == backw) && (viewport->h == backh)); if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) { IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE); diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 9bc262858e499..3eeb9e85ab64e 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -115,7 +115,7 @@ void SDL_UnlockSensors(void) SDL_bool SDL_SensorsLocked(void) { - return (SDL_sensors_locked > 0) ? SDL_TRUE : SDL_FALSE; + return (SDL_sensors_locked > 0); } void SDL_AssertSensorsLocked(void) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index baa794301d44c..0c97cc0248f8a 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1227,7 +1227,7 @@ static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len) } } if (invert) { - result = result ? SDL_FALSE : SDL_TRUE; + result = !result; } return result; } diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index f18e940280474..b10bc24255057 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -2273,7 +2273,7 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event /* Ctrl-G toggle mouse grab */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { - SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE); + SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window)); } } break; @@ -2282,7 +2282,7 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event /* Ctrl-K toggle keyboard grab */ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); if (window) { - SDL_SetWindowKeyboardGrab(window, !SDL_GetWindowKeyboardGrab(window) ? SDL_TRUE : SDL_FALSE); + SDL_SetWindowKeyboardGrab(window, !SDL_GetWindowKeyboardGrab(window)); } } break; @@ -2311,7 +2311,7 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event case SDLK_r: if (withControl) { /* Ctrl-R toggle mouse relative mode */ - SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE); + SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode()); } break; case SDLK_t: diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index cbbfa7e61621b..b5fc437b7dae3 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -52,7 +52,7 @@ SDL_bool SDL_IsShapedWindow(const SDL_Window *window) if (window == NULL) { return SDL_FALSE; } - return (SDL_bool)(window->shaper != NULL); + return (window->shaper != NULL); } /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */ @@ -125,17 +125,17 @@ static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SD } switch (mode.mode) { case (ShapeModeDefault): - pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE); + pixel_opaque = (a >= 1); break; case (ShapeModeBinarizeAlpha): - pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE); + pixel_opaque = (a >= mode.parameters.binarizationCutoff); break; case (ShapeModeReverseBinarizeAlpha): - pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE); + pixel_opaque = (a <= mode.parameters.binarizationCutoff); break; case (ShapeModeColorKey): key = mode.parameters.colorKey; - pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE); + pixel_opaque = (key.r != r || key.g != g || key.b != b); break; } if (last_opaque == -1) { diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index d6f667dc3ecf9..232d0a0379984 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -228,7 +228,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_RendererInfo info; SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA); - const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; + const SDL_bool transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; int i; int w, h; @@ -598,7 +598,7 @@ SDL_VideoDevice *SDL_GetVideoDevice(void) SDL_bool SDL_OnVideoThread(void) { - return (_this && SDL_ThreadID() == _this->thread) ? SDL_TRUE : SDL_FALSE; + return (_this && SDL_ThreadID() == _this->thread); } SDL_bool SDL_IsVideoContextExternal(void) @@ -2485,15 +2485,15 @@ int SDL_SetWindowBordered(SDL_Window *window, SDL_bool bordered) CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const int want = (bordered != SDL_FALSE); /* normalize the flag. */ - const int have = !(window->flags & SDL_WINDOW_BORDERLESS); + const SDL_bool want = (bordered != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = !(window->flags & SDL_WINDOW_BORDERLESS); if ((want != have) && (_this->SetWindowBordered)) { if (want) { window->flags &= ~SDL_WINDOW_BORDERLESS; } else { window->flags |= SDL_WINDOW_BORDERLESS; } - _this->SetWindowBordered(_this, window, (SDL_bool)want); + _this->SetWindowBordered(_this, window, want); } } return 0; @@ -2504,15 +2504,15 @@ int SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable) CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const int want = (resizable != SDL_FALSE); /* normalize the flag. */ - const int have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0); + const SDL_bool want = (resizable != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0); if ((want != have) && (_this->SetWindowResizable)) { if (want) { window->flags |= SDL_WINDOW_RESIZABLE; } else { window->flags &= ~SDL_WINDOW_RESIZABLE; } - _this->SetWindowResizable(_this, window, (SDL_bool)want); + _this->SetWindowResizable(_this, window, want); } } return 0; @@ -2523,15 +2523,15 @@ int SDL_SetWindowAlwaysOnTop(SDL_Window *window, SDL_bool on_top) CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const int want = (on_top != SDL_FALSE); /* normalize the flag. */ - const int have = ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0); + const SDL_bool want = (on_top != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0); if ((want != have) && (_this->SetWindowAlwaysOnTop)) { if (want) { window->flags |= SDL_WINDOW_ALWAYS_ON_TOP; } else { window->flags &= ~SDL_WINDOW_ALWAYS_ON_TOP; } - _this->SetWindowAlwaysOnTop(_this, window, (SDL_bool)want); + _this->SetWindowAlwaysOnTop(_this, window, want); } } return 0; @@ -3154,15 +3154,15 @@ int SDL_SetWindowFocusable(SDL_Window *window, SDL_bool focusable) { CHECK_WINDOW_MAGIC(window, -1); - const int want = (focusable != SDL_FALSE); /* normalize the flag. */ - const int have = !(window->flags & SDL_WINDOW_NOT_FOCUSABLE); + const SDL_bool want = (focusable != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = !(window->flags & SDL_WINDOW_NOT_FOCUSABLE); if ((want != have) && (_this->SetWindowFocusable)) { if (want) { window->flags &= ~SDL_WINDOW_NOT_FOCUSABLE; } else { window->flags |= SDL_WINDOW_NOT_FOCUSABLE; } - _this->SetWindowFocusable(_this, window, (SDL_bool)want); + _this->SetWindowFocusable(_this, window, want); } return 0; @@ -3621,7 +3621,7 @@ SDL_bool SDL_ScreenSaverEnabled(void) if (_this == NULL) { return SDL_TRUE; } - return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE; + return !_this->suspend_screensaver; } int SDL_EnableScreenSaver(void) diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index 544118434b2ad..b9a8c11d9991b 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -293,7 +293,7 @@ static void Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *w if (fullscreen) { EmscriptenFullscreenStrategy strategy; - SDL_bool is_fullscreen_desktop = window->fullscreen_exclusive ? SDL_FALSE : SDL_TRUE; + SDL_bool is_fullscreen_desktop = !window->fullscreen_exclusive; int res; strategy.scaleMode = is_fullscreen_desktop ? EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH : EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT; diff --git a/src/video/gdk/SDL_gdktextinput.cpp b/src/video/gdk/SDL_gdktextinput.cpp index 934a029eb2901..92485ecbe489b 100644 --- a/src/video/gdk/SDL_gdktextinput.cpp +++ b/src/video/gdk/SDL_gdktextinput.cpp @@ -230,7 +230,7 @@ SDL_bool GDK_IsTextInputShown(SDL_VideoDevice *_this) * just below the text box, so technically * this is true whenever the window is shown. */ - return (g_TextBlock != NULL) ? SDL_TRUE : SDL_FALSE; + return (g_TextBlock != NULL); } SDL_bool GDK_HasScreenKeyboardSupport(SDL_VideoDevice *_this) diff --git a/src/video/haiku/SDL_bclipboard.cc b/src/video/haiku/SDL_bclipboard.cc index 04625ad8e5833..8bc1558404c20 100644 --- a/src/video/haiku/SDL_bclipboard.cc +++ b/src/video/haiku/SDL_bclipboard.cc @@ -79,7 +79,7 @@ SDL_bool HAIKU_HasClipboardText(SDL_VideoDevice *_this) { SDL_bool result = SDL_FALSE; char *text = HAIKU_GetClipboardText(_this); if (text) { - result = text[0] != '\0' ? SDL_TRUE : SDL_FALSE; + result = (text[0] != '\0'); SDL_free(text); } return result; diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 14d7c4380cb3f..b4700e8db48fe 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -2530,13 +2530,13 @@ static void tablet_tool_handle_button(void *data, struct zwp_tablet_tool_v2 *too switch (button) { /* see %{_includedir}/linux/input-event-codes.h */ case 0x14b: /* BTN_STYLUS */ - input->btn_stylus = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE; + input->btn_stylus = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); break; case 0x14c: /* BTN_STYLUS2 */ - input->btn_stylus2 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE; + input->btn_stylus2 = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); break; case 0x149: /* BTN_STYLUS3 */ - input->btn_stylus3 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE; + input->btn_stylus3 = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); break; } diff --git a/src/video/wayland/SDL_waylandtouch.c b/src/video/wayland/SDL_waylandtouch.c index e301fa50d634e..f7348aecdc263 100644 --- a/src/video/wayland/SDL_waylandtouch.c +++ b/src/video/wayland/SDL_waylandtouch.c @@ -108,7 +108,7 @@ static void touch_handle_touch(void *data, case QtWaylandTouchPointPressed: case QtWaylandTouchPointReleased: SDL_SendTouch(Wayland_GetTouchTimestamp(viddata->input, time), deviceId, (SDL_FingerID)id, - window, (touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE, xf, yf, pressuref); + window, (touchState == QtWaylandTouchPointPressed), xf, yf, pressuref); break; case QtWaylandTouchPointMoved: SDL_SendTouchMotion(Wayland_GetTouchTimestamp(viddata->input, time), deviceId, (SDL_FingerID)id, diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 92f03263d93e9..b7d8d05a33a7f 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -598,7 +598,7 @@ static void display_handle_done(void *data, if (driverdata->display == 0) { /* First time getting display info, create the VideoDisplay */ - SDL_bool send_event = driverdata->videodata->initializing ? SDL_FALSE : SDL_TRUE; + SDL_bool send_event = !driverdata->videodata->initializing; if (driverdata->physical_width >= driverdata->physical_height) { driverdata->placeholder.natural_orientation = SDL_ORIENTATION_LANDSCAPE; } else { diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 364a8a4609eeb..dce908cdd16a0 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1346,7 +1346,7 @@ int Wayland_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysW } else #endif if (viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) { - SDL_bool popup = (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ? SDL_TRUE : SDL_FALSE; + SDL_bool popup = (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP); info->info.wl.xdg_surface = data->shell_surface.xdg.surface; info->info.wl.xdg_toplevel = popup ? NULL : data->shell_surface.xdg.roleobj.toplevel; if (popup) { @@ -1894,7 +1894,7 @@ void Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, /* Don't send redundant fullscreen set/unset events. */ if (wind->is_fullscreen != fullscreen) { - wind->fullscreen_was_positioned = fullscreen ? SDL_TRUE : SDL_FALSE; + wind->fullscreen_was_positioned = fullscreen; SetFullscreen(window, fullscreen ? output : NULL); } else if (wind->is_fullscreen) { /* diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 5ab0e68fb313f..f2e747ee9c920 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -486,8 +486,8 @@ static void WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus) { SDL_WindowData *data = window->driverdata; HWND hwnd = data->hwnd; - SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE; - SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? SDL_TRUE : SDL_FALSE; + SDL_bool had_focus = (SDL_GetKeyboardFocus() == window); + SDL_bool has_focus = (GetForegroundWindow() == hwnd); if (had_focus == has_focus || has_focus != expect_focus) { return; diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 503218767930e..3d5589543e37c 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -735,7 +735,7 @@ static void IME_UpdateInputLocale(SDL_VideoData *videodata) } videodata->ime_hkl = hklnext; - videodata->ime_candvertical = (PRIMLANG() == LANG_KOREAN || LANG() == LANG_CHS) ? SDL_FALSE : SDL_TRUE; + videodata->ime_candvertical = (PRIMLANG() != LANG_KOREAN && LANG() != LANG_CHS); } static void IME_ClearComposition(SDL_VideoData *videodata) @@ -766,7 +766,7 @@ static SDL_bool IME_IsTextInputShown(SDL_VideoData *videodata) return SDL_FALSE; } - return videodata->ime_uicontext != 0 ? SDL_TRUE : SDL_FALSE; + return videodata->ime_uicontext != 0; } static void IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD string) diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index acc7af9da440b..08834bc4a19b6 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -897,7 +897,6 @@ SDL_bool WIN_GL_SetPixelFormatFrom(SDL_VideoDevice *_this, SDL_Window *fromWindo { HDC hfromdc = fromWindow->driverdata->hdc; HDC htodc = toWindow->driverdata->hdc; - BOOL result; /* get the pixel format of the fromWindow */ int pixel_format = GetPixelFormat(hfromdc); @@ -906,9 +905,7 @@ SDL_bool WIN_GL_SetPixelFormatFrom(SDL_VideoDevice *_this, SDL_Window *fromWindo DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd); /* set the pixel format of the toWindow */ - result = SetPixelFormat(htodc, pixel_format, &pfd); - - return result ? SDL_TRUE : SDL_FALSE; + return SetPixelFormat(htodc, pixel_format, &pfd); } #endif /* SDL_VIDEO_OPENGL_WGL */ diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 66ad8e9b18a0c..b0d7122b50668 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -717,8 +717,7 @@ SDL_bool WIN_IsPerMonitorV2DPIAware(SDL_VideoDevice *_this) if (data->AreDpiAwarenessContextsEqual && data->GetThreadDpiAwarenessContext) { /* Windows 10, version 1607 */ - return (SDL_bool)data->AreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, - data->GetThreadDpiAwarenessContext()); + return data->AreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, data->GetThreadDpiAwarenessContext()); } #endif return SDL_FALSE; diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 4192bf331c56d..ac1340c79322c 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -459,7 +459,7 @@ void X11_VideoQuit(SDL_VideoDevice *_this) SDL_bool X11_UseDirectColorVisuals(void) { - return SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ? SDL_FALSE : SDL_TRUE; + return (SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") == NULL); } #endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index 522d8d05b7a40..7705e957fe8bc 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -246,7 +246,7 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, for (i = 0; i < xidevinfo->num_classes; i++) { const XIValuatorClassInfo *v = (const XIValuatorClassInfo *)xidevinfo->classes[i]; if (v->type == XIValuatorClass) { - devinfo->relative[axis] = (v->mode == XIModeRelative) ? SDL_TRUE : SDL_FALSE; + devinfo->relative[axis] = (v->mode == XIModeRelative); devinfo->minval[axis] = v->min; devinfo->maxval[axis] = v->max; if (++axis >= 2) { diff --git a/test/checkkeys.c b/test/checkkeys.c index 49f39231523c6..0db15282167e8 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -165,7 +165,7 @@ static void loop(void) switch (event.type) { case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE); + PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED), (event.key.repeat > 0)); if (event.type == SDL_EVENT_KEY_DOWN) { switch (event.key.keysym.sym) { case SDLK_BACKSPACE: diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index 811584c09b5a7..cca4740e4c0be 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -179,7 +179,7 @@ static void loop(void) switch (event.type) { case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE); + PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED), (event.key.repeat > 0)); break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.text.text); diff --git a/test/testatomic.c b/test/testatomic.c index b28ef9bcf64d0..dbbc38326e1de 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -50,28 +50,28 @@ static void RunBasicTest(void) SDL_Log("\natomic -----------------------------------------\n\n"); SDL_AtomicSet(&v, 0); - tfret = SDL_AtomicSet(&v, 10) == 0 ? SDL_TRUE : SDL_FALSE; + tfret = SDL_AtomicSet(&v, 10) == 0; SDL_Log("AtomicSet(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); - tfret = SDL_AtomicAdd(&v, 10) == 10 ? SDL_TRUE : SDL_FALSE; + tfret = SDL_AtomicAdd(&v, 10) == 10; SDL_Log("AtomicAdd(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicSet(&v, 0); SDL_AtomicIncRef(&v); - tfret = (SDL_AtomicGet(&v) == 1) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicGet(&v) == 1); SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicIncRef(&v); - tfret = (SDL_AtomicGet(&v) == 2) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicGet(&v) == 2); SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); - tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE); SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); - tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE); SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicSet(&v, 10); - tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE); SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); value = SDL_AtomicGet(&v); - tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE; + tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE); SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); } diff --git a/test/testaudio.c b/test/testaudio.c index d7b8b56aebd8c..e6ee2c1e15571 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -833,7 +833,7 @@ static void UpdateVisualizer(SDL_Renderer *renderer, SDL_Texture *visualizer, co static void LogicalDeviceThing_ontick(Thing *thing, Uint64 now) { - const SDL_bool ismousedover = (thing == mouseover_thing) ? SDL_TRUE : SDL_FALSE; + const SDL_bool ismousedover = (thing == mouseover_thing); if (!thing->data.logdev.visualizer || !thing->data.logdev.postmix_lock) { /* need these to work, skip if they failed. */ return; @@ -1173,8 +1173,8 @@ int SDL_AppEvent(const SDL_Event *event) case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - ctrl_held = ((event->key.keysym.mod & SDL_KMOD_CTRL) != 0) ? SDL_TRUE : SDL_FALSE; - alt_held = ((event->key.keysym.mod & SDL_KMOD_ALT) != 0) ? SDL_TRUE : SDL_FALSE; + ctrl_held = ((event->key.keysym.mod & SDL_KMOD_CTRL) != 0); + alt_held = ((event->key.keysym.mod & SDL_KMOD_ALT) != 0); break; case SDL_EVENT_DROP_FILE: diff --git a/test/testaudiostreamdynamicresample.c b/test/testaudiostreamdynamicresample.c index 9dacc87d5a8fe..0c6c2c197f0a1 100644 --- a/test/testaudiostreamdynamicresample.c +++ b/test/testaudiostreamdynamicresample.c @@ -233,9 +233,9 @@ static void loop(void) SDL_PauseAudioDevice(state->audio_id); } } else if (sym == SDLK_w) { - auto_loop = auto_loop ? SDL_FALSE : SDL_TRUE; + auto_loop = !auto_loop; } else if (sym == SDLK_e) { - auto_flush = auto_flush ? SDL_FALSE : SDL_TRUE; + auto_flush = !auto_flush; } else if (sym == SDLK_a) { SDL_ClearAudioStream(stream); SDL_Log("Cleared audio stream"); diff --git a/test/testshader.c b/test/testshader.c index 7d896f2889736..2de2380dfda94 100644 --- a/test/testshader.c +++ b/test/testshader.c @@ -222,7 +222,7 @@ static SDL_bool CompileShaderProgram(ShaderData *data) } glUseProgramObjectARB(0); - return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE; + return (glGetError() == GL_NO_ERROR); } static void DestroyShaderProgram(ShaderData *data) From 0b460f34ba70394e33637ab1470efb59b5bdfeab Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 14:47:20 -0700 Subject: [PATCH 202/725] The HP HyperX controllers have a share button --- src/hidapi/libusb/hid.c | 2 +- src/joystick/SDL_joystick.c | 6 ++++++ src/joystick/usb_ids.h | 8 ++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index 3cdb891020bbe..b063dafe39f45 100644 --- a/src/hidapi/libusb/hid.c +++ b/src/hidapi/libusb/hid.c @@ -868,7 +868,7 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de static const int xb1_iface_subclass = 71; static const int xb1_iface_protocol = 208; static const int supported_vendors[] = { - 0x03f0, /* HP */ + 0x03f0, /* HP */ 0x044f, /* Thrustmaster */ 0x045e, /* Microsoft */ 0x0738, /* Mad Catz */ diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index d657b02acb579..cd17d285cdc3f 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2479,6 +2479,12 @@ SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) return SDL_TRUE; } } + if (vendor_id == USB_VENDOR_HP) { + if (product_id == USB_PRODUCT_XBOX_SERIES_X_HP_HYPERX || + product_id == USB_PRODUCT_XBOX_SERIES_X_HP_HYPERX_RGB) { + return SDL_TRUE; + } + } if (vendor_id == USB_VENDOR_RAZER) { if (product_id == USB_PRODUCT_RAZER_WOLVERINE_V2 || product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_CHROMA) { diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 773e58f7c9ae4..3da1c24991321 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -33,6 +33,7 @@ #define USB_VENDOR_DRAGONRISE 0x0079 #define USB_VENDOR_GOOGLE 0x18d1 #define USB_VENDOR_HORI 0x0f0d +#define USB_VENDOR_HP 0x03f0 #define USB_VENDOR_HYPERKIN 0x2e24 #define USB_VENDOR_LOGITECH 0x046d #define USB_VENDOR_MADCATZ 0x0738 @@ -66,6 +67,7 @@ #define USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X 0x014f #define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c #define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184 +#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184 #define USB_PRODUCT_LOGITECH_F310 0xc216 #define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1 #define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337 @@ -125,12 +127,14 @@ #define USB_PRODUCT_XBOX_ONE_S_REV2_BLE 0x0b20 #define USB_PRODUCT_XBOX_SERIES_X 0x0b12 #define USB_PRODUCT_XBOX_SERIES_X_BLE 0x0b13 -#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6 -#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9 +#define USB_PRODUCT_XBOX_SERIES_X_HP_HYPERX 0x08b6 +#define USB_PRODUCT_XBOX_SERIES_X_HP_HYPERX_RGB 0x07a0 #define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da +#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9 #define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001 #define USB_PRODUCT_XBOX_SERIES_X_POWERA_MOGA_XP_ULTRA 0x890b #define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002 +#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6 #define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */ #define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */ #define USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD 0x11ff From fe175d025f8a657db3a8364a2237df27c3126a8d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 14:54:11 -0700 Subject: [PATCH 203/725] Fixed building Vivante video driver --- src/video/vivante/SDL_vivantevulkan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vivante/SDL_vivantevulkan.h b/src/video/vivante/SDL_vivantevulkan.h index dc77bbf3571cd..a4bc784ab4bd2 100644 --- a/src/video/vivante/SDL_vivantevulkan.h +++ b/src/video/vivante/SDL_vivantevulkan.h @@ -35,7 +35,7 @@ int VIVANTE_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void VIVANTE_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -SDL_bool VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, +char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, unsigned *count, const char **names); SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this, From dad1a84be4e9236267dd7c5393b56c60b3ed7875 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 14:56:15 -0700 Subject: [PATCH 204/725] Fixed building Vivante video driver --- src/video/vivante/SDL_vivantevulkan.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/vivante/SDL_vivantevulkan.h b/src/video/vivante/SDL_vivantevulkan.h index a4bc784ab4bd2..b39fd2b9f0af5 100644 --- a/src/video/vivante/SDL_vivantevulkan.h +++ b/src/video/vivante/SDL_vivantevulkan.h @@ -36,8 +36,7 @@ int VIVANTE_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); void VIVANTE_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - unsigned *count, - const char **names); + Uint32 *count); SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, From ad5264e54f19bab2b26ab8045bbe99be793ec6e4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 21:34:04 -0700 Subject: [PATCH 205/725] Don't run SDL_IterateMainCallbacks() if the init call returns an exit code This fixes a crash in testsprite if you pass invalid command line parameters. --- src/main/generic/SDL_sysmain_callbacks.c | 56 ++++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index 3e47264e3e6f3..9a0bab3e6e1e8 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -38,41 +38,41 @@ static void SDLCALL MainCallbackRateHintChanged(void *userdata, const char *name int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) { int rc = SDL_InitMainCallbacks(argc, argv, appinit, appiter, appevent, appquit); + if (rc == 0) { + SDL_AddHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); - SDL_AddHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); + Uint64 next_iteration = callback_rate_increment ? (SDL_GetTicksNS() + callback_rate_increment) : 0; - Uint64 next_iteration = callback_rate_increment ? (SDL_GetTicksNS() + callback_rate_increment) : 0; + while ((rc = SDL_IterateMainCallbacks()) == 0) { + // !!! FIXME: this can be made more complicated if we decide to + // !!! FIXME: optionally hand off callback responsibility to the + // !!! FIXME: video subsystem (for example, if Wayland has a + // !!! FIXME: protocol to drive an animation loop, maybe we hand + // !!! FIXME: off to them here if/when the video subsystem becomes + // !!! FIXME: initialized). - while ((rc = SDL_IterateMainCallbacks()) == 0) { - // !!! FIXME: this can be made more complicated if we decide to - // !!! FIXME: optionally hand off callback responsibility to the - // !!! FIXME: video subsystem (for example, if Wayland has a - // !!! FIXME: protocol to drive an animation loop, maybe we hand - // !!! FIXME: off to them here if/when the video subsystem becomes - // !!! FIXME: initialized). - - // !!! FIXME: maybe respect this hint even if there _is_ a window. - // if there's no window, try to run at about 60fps (or whatever rate - // the hint requested). This makes this not eat all the CPU in - // simple things like loopwave. If there's a window, we run as fast - // as possible, which means we'll clamp to vsync in common cases, - // and won't be restrained to vsync if the app is doing a benchmark - // or doesn't want to be, based on how they've set up that window. - if ((callback_rate_increment == 0) || SDL_HasWindows()) { - next_iteration = 0; // just clear the timer and run at the pace the video subsystem allows. - } else { - const Uint64 now = SDL_GetTicksNS(); - if (next_iteration > now) { // Running faster than the limit, sleep a little. - SDL_DelayNS(next_iteration - now); + // !!! FIXME: maybe respect this hint even if there _is_ a window. + // if there's no window, try to run at about 60fps (or whatever rate + // the hint requested). This makes this not eat all the CPU in + // simple things like loopwave. If there's a window, we run as fast + // as possible, which means we'll clamp to vsync in common cases, + // and won't be restrained to vsync if the app is doing a benchmark + // or doesn't want to be, based on how they've set up that window. + if ((callback_rate_increment == 0) || SDL_HasWindows()) { + next_iteration = 0; // just clear the timer and run at the pace the video subsystem allows. } else { - next_iteration = now; // running behind (or just lost the window)...reset the timer. + const Uint64 now = SDL_GetTicksNS(); + if (next_iteration > now) { // Running faster than the limit, sleep a little. + SDL_DelayNS(next_iteration - now); + } else { + next_iteration = now; // running behind (or just lost the window)...reset the timer. + } + next_iteration += callback_rate_increment; } - next_iteration += callback_rate_increment; } - } - - SDL_DelHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); + SDL_DelHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); + } SDL_QuitMainCallbacks(); return (rc < 0) ? 1 : 0; From e0379c3b37cb71efb97719899d266d7ec9c1b435 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 21:47:44 -0700 Subject: [PATCH 206/725] Grab events in large chunks in SDL_IterateMainCallbacks() This is more efficient, especially since we're just going to discard them. --- src/main/SDL_main_callbacks.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 5d880066df243..a20f9f6ac8624 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -81,15 +81,22 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ int SDL_IterateMainCallbacks(void) { - SDL_Event event; + // Just pump events and empty the queue, EventWatcher sends the events to the app. SDL_PumpEvents(); - while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) == 1) { - // just empty the queue, EventWatcher sends the events to the app. - switch (event.type) { + + for (;;) { + SDL_Event events[32]; + int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); + if (count <= 0) { + break; + } + for (int i = 0; i < count; ++i) { + switch (events[i].type) { case SDL_EVENT_DROP_FILE: case SDL_EVENT_DROP_TEXT: - SDL_free(event.drop.file); + SDL_free(events[i].drop.file); break; + } } } From f439ccfc1a834eefe68ce33a3dad31dda0b617a5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 22:31:42 -0700 Subject: [PATCH 207/725] Updated return values for SDL event functions SDL_PollEvent(), SDL_WaitEvent(), and SDL_WaitEventTimeout() all return SDL_bool. SDL_AddEventWatch() returns an int result code. Also improved timeout accuracy in SDL_WaitEventTimeout() --- include/SDL3/SDL_events.h | 38 +++++++--------- src/SDL_internal.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 8 ++-- src/events/SDL_events.c | 83 ++++++++++++++++++++--------------- 4 files changed, 67 insertions(+), 64 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 4e93b0fb13053..8a7665ea62b42 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -731,9 +731,7 @@ typedef enum * \sa SDL_PumpEvents * \sa SDL_PushEvent */ -extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents, - SDL_eventaction action, - Uint32 minType, Uint32 maxType); +extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, Uint32 minType, Uint32 maxType); /* @} */ /** @@ -852,7 +850,7 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * * \param event the SDL_Event structure to be filled with the next event from * the queue, or NULL - * \returns 1 if there is a pending event or 0 if there are none available. + * \returns SDL_TRUE if this got an event or SDL_FALSE if there are none available. * * \since This function is available since SDL 3.0.0. * @@ -863,7 +861,7 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * \sa SDL_WaitEvent * \sa SDL_WaitEventTimeout */ -extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event); +extern DECLSPEC SDL_bool SDLCALL SDL_PollEvent(SDL_Event *event); /** * Wait indefinitely for the next available event. @@ -876,7 +874,7 @@ extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event); * * \param event the SDL_Event structure to be filled in with the next event * from the queue, or NULL - * \returns 1 on success or 0 if there was an error while waiting for events; + * \returns SDL_TRUE on success or SDL_FALSE if there was an error while waiting for events; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -885,7 +883,7 @@ extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event); * \sa SDL_PumpEvents * \sa SDL_WaitEventTimeout */ -extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event); +extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); /** * Wait until the specified timeout (in milliseconds) for the next available @@ -904,9 +902,7 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event); * from the queue, or NULL * \param timeoutMS the maximum number of milliseconds to wait for the next * available event - * \returns 1 on success or 0 if there was an error while waiting for events; - * call SDL_GetError() for more information. This also returns 0 if - * the timeout elapsed without an event arriving. + * \returns SDL_TRUE if this got an event or SDL_FALSE if the timeout elapsed without any events available. * * \since This function is available since SDL 3.0.0. * @@ -914,7 +910,7 @@ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event); * \sa SDL_PumpEvents * \sa SDL_WaitEvent */ -extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); +extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); /** * Add an event to the event queue. @@ -948,7 +944,7 @@ extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeou * \sa SDL_PollEvent * \sa SDL_RegisterEvents */ -extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event); +extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event *event); /** * A function pointer used for callbacks that watch the event queue. @@ -962,7 +958,7 @@ extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event); * \sa SDL_SetEventFilter * \sa SDL_AddEventWatch */ -typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event); +typedef int (SDLCALL *SDL_EventFilter)(void *userdata, SDL_Event *event); /** * Set up a filter to process all events before they change internal state and @@ -1006,8 +1002,7 @@ typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event); * \sa SDL_PeepEvents * \sa SDL_PushEvent */ -extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter, - void *userdata); +extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter, void *userdata); /** * Query the current event filter. @@ -1024,8 +1019,7 @@ extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter, * * \sa SDL_SetEventFilter */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter, - void **userdata); +extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata); /** * Add a callback to be triggered when an event is added to the event queue. @@ -1047,14 +1041,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter, * * \param filter an SDL_EventFilter function to call when an event happens. * \param userdata a pointer that is passed to `filter` + * \returns 0 on success, or a negative error code on failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_DelEventWatch * \sa SDL_SetEventFilter */ -extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter, - void *userdata); +extern DECLSPEC int SDLCALL SDL_AddEventWatch(SDL_EventFilter filter, void *userdata); /** * Remove an event watch callback added with SDL_AddEventWatch(). @@ -1069,8 +1063,7 @@ extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter, * * \sa SDL_AddEventWatch */ -extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter, - void *userdata); +extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter, void *userdata); /** * Run a specific filter function on the current event queue, removing any @@ -1088,8 +1081,7 @@ extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter, * \sa SDL_GetEventFilter * \sa SDL_SetEventFilter */ -extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter, - void *userdata); +extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter, void *userdata); /** * Set the state of processing events by type. diff --git a/src/SDL_internal.h b/src/SDL_internal.h index aa2d6c6271f1f..b0f2c296f64f4 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -200,7 +200,7 @@ extern "C" { extern DECLSPEC Uint32 SDLCALL SDL_GetNextObjectID(void); extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS); extern DECLSPEC int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); -extern DECLSPEC int SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); +extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 25ee29776f168..d2f40604b4f55 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -103,7 +103,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return) -SDL_DYNAPI_PROC(void,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromRW,(SDL_RWops *a, SDL_bool b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return) @@ -554,7 +554,7 @@ SDL_DYNAPI_PROC(SDL_Joystick*,SDL_OpenJoystick,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_Sensor*,SDL_OpenSensor,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(int,SDL_OpenURL,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_PeepEvents,(SDL_Event *a, int b, SDL_eventaction c, Uint32 d, Uint32 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_PollEvent,(SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_PollEvent,(SDL_Event *a),(a),return) SDL_DYNAPI_PROC(int,SDL_PostSemaphore,(SDL_Semaphore *a),(a),return) SDL_DYNAPI_PROC(int,SDL_PremultiplyAlpha,(int a, int b, Uint32 c, const void *d, int e, Uint32 f, void *g, int h),(a,b,c,d,e,f,g,h),return) SDL_DYNAPI_PROC(void,SDL_PumpEvents,(void),(),) @@ -725,8 +725,8 @@ SDL_DYNAPI_PROC(int,SDL_Vulkan_LoadLibrary,(const char *a),(a),return) SDL_DYNAPI_PROC(void,SDL_Vulkan_UnloadLibrary,(void),(),) SDL_DYNAPI_PROC(int,SDL_WaitCondition,(SDL_Condition *a, SDL_Mutex *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_WaitConditionTimeout,(SDL_Condition *a, SDL_Mutex *b, Sint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_WaitEvent,(SDL_Event *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_WaitEvent,(SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_WaitSemaphore,(SDL_Semaphore *a),(a),return) SDL_DYNAPI_PROC(int,SDL_WaitSemaphoreTimeout,(SDL_Semaphore *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_WaitThread,(SDL_Thread *a, int *b),(a,b),) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index bd926f3d7625f..031e660accbc2 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -903,7 +903,7 @@ void SDL_PumpEvents(void) /* Public functions */ -int SDL_PollEvent(SDL_Event *event) +SDL_bool SDL_PollEvent(SDL_Event *event) { return SDL_WaitEventTimeoutNS(event, 0); } @@ -1014,14 +1014,14 @@ static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this) return NULL; } -int SDL_WaitEvent(SDL_Event *event) +SDL_bool SDL_WaitEvent(SDL_Event *event) { return SDL_WaitEventTimeoutNS(event, -1); } -int SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) +SDL_bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) { - Uint64 timeoutNS; + Sint64 timeoutNS; if (timeoutMS > 0) { timeoutNS = SDL_MS_TO_NS(timeoutMS); @@ -1031,7 +1031,7 @@ int SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) return SDL_WaitEventTimeoutNS(event, timeoutNS); } -int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) +SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_Window *wakeup_window; @@ -1039,6 +1039,14 @@ int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) SDL_bool include_sentinel = (timeoutNS == 0); int result; + if (timeoutNS > 0) { + start = SDL_GetTicksNS(); + expiration = start + timeoutNS; + } else { + start = 0; + expiration = 0; + } + /* If there isn't a poll sentinel event pending, pump events and add one */ if (SDL_AtomicGet(&SDL_sentinel_pending) == 0) { SDL_PumpEventsInternal(SDL_TRUE); @@ -1047,13 +1055,13 @@ int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) /* First check for existing events */ result = SDL_PeepEventsInternal(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, include_sentinel); if (result < 0) { - return 0; + return SDL_FALSE; } if (include_sentinel) { if (event) { if (event->type == SDL_EVENT_POLL_SENTINEL) { /* Reached the end of a poll cycle, and not willing to wait */ - return 0; + return SDL_FALSE; } } else { /* Need to peek the next event to check for sentinel */ @@ -1063,60 +1071,56 @@ int SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) dummy.type == SDL_EVENT_POLL_SENTINEL) { SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, SDL_TRUE); /* Reached the end of a poll cycle, and not willing to wait */ - return 0; + return SDL_FALSE; } } } if (result == 0) { if (timeoutNS == 0) { /* No events available, and not willing to wait */ - return 0; + return SDL_FALSE; } } else { /* Has existing events */ - return 1; + return SDL_TRUE; } /* We should have completely handled timeoutNS == 0 above */ SDL_assert(timeoutNS != 0); - if (timeoutNS > 0) { - start = SDL_GetTicksNS(); - expiration = start + timeoutNS; - } else { - start = 0; - expiration = 0; - } - if (_this && _this->WaitEventTimeout && _this->SendWakeupEvent && !SDL_events_need_polling()) { /* Look if a shown window is available to send the wakeup event. */ wakeup_window = SDL_find_active_window(_this); if (wakeup_window) { - int status = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeoutNS); - - /* There may be implementation-defined conditions where the backend cannot - reliably wait for the next event. If that happens, fall back to polling. */ - if (status >= 0) { - return status; + result = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeoutNS); + if (result > 0) { + return SDL_TRUE; + } else if (result == 0) { + return SDL_FALSE; + } else { + /* There may be implementation-defined conditions where the backend cannot + * reliably wait for the next event. If that happens, fall back to polling. + */ } } } for (;;) { SDL_PumpEventsInternal(SDL_TRUE); - switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST)) { - case -1: - return 0; - case 0: - if (timeoutNS > 0 && SDL_GetTicksNS() >= expiration) { + + if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) { + return SDL_TRUE; + } + + Uint64 delay = SDL_MS_TO_NS(1); + if (timeoutNS > 0) { + Uint64 now = SDL_GetTicksNS(); + if (now >= expiration) { /* Timeout expired and no events */ - return 0; + return SDL_FALSE; } - SDL_Delay(1); - break; - default: - /* Has events */ - return 1; + delay = SDL_min((expiration - now), delay); } + SDL_DelayNS(delay); } } @@ -1200,8 +1204,10 @@ SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) return event_ok.callback ? SDL_TRUE : SDL_FALSE; } -void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) +int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { + int result = 0; + SDL_LockMutex(SDL_event_watchers_lock); { SDL_EventWatcher *event_watchers; @@ -1216,9 +1222,14 @@ void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) watcher->userdata = userdata; watcher->removed = SDL_FALSE; ++SDL_event_watchers_count; + } else { + SDL_OutOfMemory(); + result = -1; } } SDL_UnlockMutex(SDL_event_watchers_lock); + + return result; } void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) From 3ab6670cb13a49e46e33182e82b915dde1cc5fc5 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sat, 4 Nov 2023 05:36:15 +0000 Subject: [PATCH 208/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_events.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 8a7665ea62b42..48746d545281b 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -850,7 +850,8 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * * \param event the SDL_Event structure to be filled with the next event from * the queue, or NULL - * \returns SDL_TRUE if this got an event or SDL_FALSE if there are none available. + * \returns SDL_TRUE if this got an event or SDL_FALSE if there are none + * available. * * \since This function is available since SDL 3.0.0. * @@ -874,8 +875,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PollEvent(SDL_Event *event); * * \param event the SDL_Event structure to be filled in with the next event * from the queue, or NULL - * \returns SDL_TRUE on success or SDL_FALSE if there was an error while waiting for events; - * call SDL_GetError() for more information. + * \returns SDL_TRUE on success or SDL_FALSE if there was an error while + * waiting for events; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -902,7 +903,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); * from the queue, or NULL * \param timeoutMS the maximum number of milliseconds to wait for the next * available event - * \returns SDL_TRUE if this got an event or SDL_FALSE if the timeout elapsed without any events available. + * \returns SDL_TRUE if this got an event or SDL_FALSE if the timeout elapsed + * without any events available. * * \since This function is available since SDL 3.0.0. * @@ -1041,7 +1043,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter *filter, voi * * \param filter an SDL_EventFilter function to call when an event happens. * \param userdata a pointer that is passed to `filter` - * \returns 0 on success, or a negative error code on failure; call SDL_GetError() for more information. + * \returns 0 on success, or a negative error code on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * From a6b85c81cc92b6b3d39b6c682a9b0895a9a33b1d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 3 Nov 2023 22:37:53 -0700 Subject: [PATCH 209/725] Fixed build --- src/dynapi/SDL_dynapi_procs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d2f40604b4f55..d584067fb231e 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -103,7 +103,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromRW,(SDL_RWops *a, SDL_bool b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return) From 7f65ed6461e6ac6bde0b0f279e2b184c43b984d3 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Thu, 12 Oct 2023 12:37:35 +0300 Subject: [PATCH 210/725] Handle subsystem dependencies recursively Existing code is erroneous, because it adds or removes dependency's ref count based on number of InitSubSystem/QuitSubSystem calls, while ref count diff should depend on number of inited or quit dependents. Recursive approach seems to be simplest solution that guarantees proper ref count. --- src/SDL.c | 66 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/src/SDL.c b/src/SDL.c index 7ff9711cc2eac..46d668820d723 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -154,6 +154,22 @@ static SDL_bool SDL_ShouldQuitSubsystem(Uint32 subsystem) return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit); } +/* Private helper to either increment's existing ref counter, + * or fully init a new subsystem. */ +static SDL_bool SDL_InitOrIncrementSubsystem(Uint32 subsystem) +{ + int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); + SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); + if (subsystem_index < 0) { + return SDL_FALSE; + } + if (SDL_SubsystemRefCount[subsystem_index] > 0) { + ++SDL_SubsystemRefCount[subsystem_index]; + return SDL_TRUE; + } + return SDL_InitSubSystem(subsystem) == 0; +} + void SDL_SetMainReady(void) { SDL_MainIsReady = SDL_TRUE; @@ -177,16 +193,6 @@ int SDL_InitSubSystem(Uint32 flags) SDL_DBus_Init(); #endif - if (flags & SDL_INIT_GAMEPAD) { - /* game controller implies joystick */ - flags |= SDL_INIT_JOYSTICK; - } - - if (flags & (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO)) { - /* video or joystick or audio implies events */ - flags |= SDL_INIT_EVENTS; - } - #ifdef SDL_VIDEO_DRIVER_WINDOWS if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) { if (SDL_HelperWindowCreate() < 0) { @@ -241,6 +247,11 @@ int SDL_InitSubSystem(Uint32 flags) if (flags & SDL_INIT_VIDEO) { #ifndef SDL_VIDEO_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) { + /* video implies events */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { + goto quit_and_error; + } + SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); if (SDL_VideoInit(NULL) < 0) { SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); @@ -260,6 +271,11 @@ int SDL_InitSubSystem(Uint32 flags) if (flags & SDL_INIT_AUDIO) { #ifndef SDL_AUDIO_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) { + /* audio implies events */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { + goto quit_and_error; + } + SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); if (SDL_InitAudio(NULL) < 0) { SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); @@ -279,6 +295,11 @@ int SDL_InitSubSystem(Uint32 flags) if (flags & SDL_INIT_JOYSTICK) { #ifndef SDL_JOYSTICK_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) { + /* joystick implies events */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { + goto quit_and_error; + } + SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); if (SDL_InitJoysticks() < 0) { SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); @@ -297,6 +318,11 @@ int SDL_InitSubSystem(Uint32 flags) if (flags & SDL_INIT_GAMEPAD) { #ifndef SDL_JOYSTICK_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) { + /* game controller implies joystick */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) { + goto quit_and_error; + } + SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); if (SDL_InitGamepads() < 0) { SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); @@ -378,21 +404,19 @@ void SDL_QuitSubSystem(Uint32 flags) #ifndef SDL_JOYSTICK_DISABLED if (flags & SDL_INIT_GAMEPAD) { - /* game controller implies joystick */ - flags |= SDL_INIT_JOYSTICK; - if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) { SDL_QuitGamepads(); + /* game controller implies joystick */ + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); } if (flags & SDL_INIT_JOYSTICK) { - /* joystick implies events */ - flags |= SDL_INIT_EVENTS; - if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) { SDL_QuitJoysticks(); + /* joystick implies events */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); } @@ -409,11 +433,10 @@ void SDL_QuitSubSystem(Uint32 flags) #ifndef SDL_AUDIO_DISABLED if (flags & SDL_INIT_AUDIO) { - /* audio implies events */ - flags |= SDL_INIT_EVENTS; - if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) { SDL_QuitAudio(); + /* audio implies events */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); } @@ -421,11 +444,10 @@ void SDL_QuitSubSystem(Uint32 flags) #ifndef SDL_VIDEO_DISABLED if (flags & SDL_INIT_VIDEO) { - /* video implies events */ - flags |= SDL_INIT_EVENTS; - if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) { SDL_VideoQuit(); + /* video implies events */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); } From c4bf05fd9d0126cbdf4db09f11bc5737b38f5f76 Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Fri, 13 Oct 2023 19:43:18 +0300 Subject: [PATCH 211/725] Added subsystem refcount tests to testautomation --- .../testautomation/testautomation.vcxproj | 3 +- test/testautomation.c | 1 + test/testautomation_subsystems.c | 239 ++++++++++++++++++ test/testautomation_suites.h | 1 + 4 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 test/testautomation_subsystems.c diff --git a/VisualC/tests/testautomation/testautomation.vcxproj b/VisualC/tests/testautomation/testautomation.vcxproj index fd1f86c9b3f4f..f64b89be8db2d 100644 --- a/VisualC/tests/testautomation/testautomation.vcxproj +++ b/VisualC/tests/testautomation/testautomation.vcxproj @@ -221,6 +221,7 @@ + @@ -228,4 +229,4 @@ - + \ No newline at end of file diff --git a/test/testautomation.c b/test/testautomation.c index 8e5f002fe5c37..7cdd6be9337a9 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -45,6 +45,7 @@ static SDLTest_TestSuiteReference *testSuites[] = { &syswmTestSuite, &timerTestSuite, &videoTestSuite, + &subsystemsTestSuite, /* run last, not interfere with other test enviroment */ NULL }; diff --git a/test/testautomation_subsystems.c b/test/testautomation_subsystems.c new file mode 100644 index 0000000000000..1bbc6410da1a2 --- /dev/null +++ b/test/testautomation_subsystems.c @@ -0,0 +1,239 @@ +/** + * Events test suite + */ +#include "testautomation_suites.h" +#include +#include + +/* ================= Test Case Implementation ================== */ + +/* Fixture */ + +static void subsystemsSetUp(void *arg) +{ + /* Reset each one of the SDL subsystems */ + /* CHECKME: can we use SDL_Quit here, or this will break the flow of tests? */ + SDL_Quit(); + /* Alternate variant without SDL_Quit: + while (SDL_WasInit(SDL_INIT_EVERYTHING) != 0) { + SDL_QuitSubSystem(SDL_INIT_EVERYTHING); + } + */ + SDLTest_AssertPass("Reset all subsystems before subsystems test"); + SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_EVERYTHING) == 0, "Check result from SDL_WasInit(SDL_INIT_EVERYTHING)"); +} + +static void subsystemsTearDown(void *arg) +{ + /* Reset each one of the SDL subsystems */ + SDL_Quit(); + + SDLTest_AssertPass("Cleanup of subsystems test completed"); +} + +/* Test case functions */ + +/** + * \brief Inits and Quits particular subsystem, checking its Init status. + * + * \sa SDL_InitSubSystem + * \sa SDL_QuitSubSystem + * + */ +static int subsystems_referenceCount() +{ + const int system = SDL_INIT_VIDEO; + int result; + /* Ensure that we start with a non-initialized subsystem. */ + SDLTest_AssertCheck(SDL_WasInit(system) == 0, "Check result from SDL_WasInit(0x%x)", system); + + /* Init subsystem once, and quit once */ + SDL_InitSubSystem(system); + SDLTest_AssertPass("Call to SDL_InitSubSystem(0x%x)", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); + + SDL_QuitSubSystem(system); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x)", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(0x%x), expected: 0, got: 0x%x", system, result); + + /* Init subsystem number of times, then decrement reference count until it's disposed of. */ + SDL_InitSubSystem(system); + SDL_InitSubSystem(system); + SDL_InitSubSystem(system); + SDLTest_AssertPass("Call to SDL_InitSubSystem(0x%x) x3 times", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); + + SDL_QuitSubSystem(system); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x1", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); + SDL_QuitSubSystem(system); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x2", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); + SDL_QuitSubSystem(system); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x3", system); + result = SDL_WasInit(system); + SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(0x%x), expected: 0, got: 0x%x", system, result); + + return TEST_COMPLETED; +} + +/** + * \brief Inits and Quits subsystems that have another as dependency; + * check that the dependency is not removed before the last of its dependents. + * + * \sa SDL_InitSubSystem + * \sa SDL_QuitSubSystem + * + */ +static int subsystems_dependRefCountInitAllQuitByOne() +{ + int result; + /* Ensure that we start with reset subsystems. */ + SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, + "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); + + /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ + SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + + /* Quit systems one by one. */ + SDL_QuitSubSystem(SDL_INIT_VIDEO); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_JOYSTICK)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); + + return TEST_COMPLETED; +} + +/** + * \brief Inits and Quits subsystems that have another as dependency; + * check that the dependency is not removed before the last of its dependents. + * + * \sa SDL_InitSubSystem + * \sa SDL_QuitSubSystem + * + */ +static int subsystems_dependRefCountInitByOneQuitAll() +{ + int result; + /* Ensure that we start with reset subsystems. */ + SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, + "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); + + /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ + SDL_InitSubSystem(SDL_INIT_VIDEO); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + SDL_InitSubSystem(SDL_INIT_AUDIO); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)"); + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_JOYSTICK)"); + + /* Quit systems all at once. */ + SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); + + return TEST_COMPLETED; +} + +/** + * \brief Inits and Quits subsystems that have another as dependency, + * but also inits that dependency explicitly, giving it extra ref count. + * Check that the dependency is not removed before the last reference is gone. + * + * \sa SDL_InitSubSystem + * \sa SDL_QuitSubSystem + * + */ +static int subsystems_dependRefCountWithExtraInit() +{ + int result; + /* Ensure that we start with reset subsystems. */ + SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, + "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); + + /* Init EVENTS explicitly, +1 ref count. */ + SDL_InitSubSystem(SDL_INIT_EVENTS); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_EVENTS)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ + SDL_InitSubSystem(SDL_INIT_VIDEO); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO)"); + SDL_InitSubSystem(SDL_INIT_AUDIO); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)"); + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_JOYSTICK)"); + + /* Quit EVENTS explicitly, -1 ref count. */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_EVENTS)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + + /* Quit systems one by one. */ + SDL_QuitSubSystem(SDL_INIT_VIDEO); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_JOYSTICK)"); + result = SDL_WasInit(SDL_INIT_EVENTS); + SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); + + return TEST_COMPLETED; +} + +/* ================= Test References ================== */ + +/* Subsystems test cases */ +static const SDLTest_TestCaseReference subsystemsTest1 = { + (SDLTest_TestCaseFp)subsystems_referenceCount, "subsystems_referenceCount", "Makes sure that subsystem stays until number of quits matches inits.", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference subsystemsTest2 = { + (SDLTest_TestCaseFp)subsystems_dependRefCountInitAllQuitByOne, "subsystems_dependRefCountInitAllQuitByOne", "Check reference count of subsystem dependencies.", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference subsystemsTest3 = { + (SDLTest_TestCaseFp)subsystems_dependRefCountInitByOneQuitAll, "subsystems_dependRefCountInitByOneQuitAll", "Check reference count of subsystem dependencies.", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference subsystemsTest4 = { + (SDLTest_TestCaseFp)subsystems_dependRefCountWithExtraInit, "subsystems_dependRefCountWithExtraInit", "Check reference count of subsystem dependencies.", TEST_ENABLED +}; + +/* Sequence of Events test cases */ +static const SDLTest_TestCaseReference *subsystemsTests[] = { + &subsystemsTest1, &subsystemsTest2, &subsystemsTest3, &subsystemsTest4, NULL +}; + +/* Events test suite (global) */ +SDLTest_TestSuiteReference subsystemsTestSuite = { + "Subsystems", + subsystemsSetUp, + subsystemsTests, + subsystemsTearDown +}; diff --git a/test/testautomation_suites.h b/test/testautomation_suites.h index e1a29e0b70e20..9a562620a2d0e 100644 --- a/test/testautomation_suites.h +++ b/test/testautomation_suites.h @@ -28,6 +28,7 @@ extern SDLTest_TestSuiteReference renderTestSuite; extern SDLTest_TestSuiteReference rwopsTestSuite; extern SDLTest_TestSuiteReference sdltestTestSuite; extern SDLTest_TestSuiteReference stdlibTestSuite; +extern SDLTest_TestSuiteReference subsystemsTestSuite; extern SDLTest_TestSuiteReference surfaceTestSuite; extern SDLTest_TestSuiteReference syswmTestSuite; extern SDLTest_TestSuiteReference timerTestSuite; From 7e445da56990ce741e356ff7ed354abea129f288 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 00:55:55 -0700 Subject: [PATCH 212/725] Added SDL_CleanupEvent() This is used to free any dynamically allocated memory in events. --- docs/README-migration.md | 3 + include/SDL3/SDL_events.h | 78 +++++++++++++--------- include/SDL3/SDL_hints.h | 11 ---- src/core/linux/SDL_fcitx.c | 23 ++----- src/core/linux/SDL_ibus.c | 41 ++++-------- src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/events/SDL_dropevents.c | 10 ++- src/events/SDL_events.c | 95 ++++++++++----------------- src/events/SDL_keyboard.c | 25 ++++--- src/main/SDL_main_callbacks.c | 17 +---- src/test/SDL_test_common.c | 11 +--- src/video/wayland/SDL_waylandevents.c | 32 +++------ test/checkkeys.c | 8 +-- test/checkkeysthreads.c | 1 + test/testaudio.c | 6 +- test/testdropfile.c | 10 +-- test/testime.c | 1 + test/testwm.c | 3 - 20 files changed, 146 insertions(+), 232 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 494d69fce426b..e9ea328282388 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -298,6 +298,8 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). +You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, and SDL_EVENT_TEXT_EDITING. This cleans up the memory associated with those events, and you no longer have to free the data yourself. + Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. The SDL_DISPLAYEVENT_* events have been moved to top level events, and SDL_DISPLAYEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_DISPLAYEVENT and then checking for display events. You can compare the event >= SDL_EVENT_DISPLAY_FIRST and <= SDL_EVENT_DISPLAY_LAST if you need to see whether it's a display event. @@ -555,6 +557,7 @@ The following hints have been removed: * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend +* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has dynamically allocated text if needed, and should be freed with SDL_CleanupEvent() when processed * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 48746d545281b..312452444cd93 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -136,7 +136,6 @@ typedef enum SDL_EVENT_TEXT_INPUT, /**< Keyboard text input */ SDL_EVENT_KEYMAP_CHANGED, /**< Keymap changed due to a system event such as an input language or keyboard layout change. */ - SDL_EVENT_TEXT_EDITING_EXT, /**< Extended keyboard text editing (composition) */ /* Mouse events */ SDL_EVENT_MOUSE_MOTION = 0x400, /**< Mouse moved */ @@ -257,44 +256,35 @@ typedef struct SDL_KeyboardEvent SDL_Keysym keysym; /**< The key that was pressed or released */ } SDL_KeyboardEvent; -#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32) +#define SDL_TEXTEDITINGEVENT_TEXT_SIZE 64 /** * \brief Keyboard text editing event structure (event.edit.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextEditingEvent { Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */ + SDL_WindowID windowID; /**< The window with keyboard focus, if any */ + char *text; /**< The editing text */ + char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short editing text */ Sint32 start; /**< The start cursor of selected editing text */ Sint32 length; /**< The length of selected editing text */ } SDL_TextEditingEvent; -/** - * \brief Extended keyboard text editing event structure (event.editExt.*) when text would be - * truncated if stored in the text buffer SDL_TextEditingEvent - */ -typedef struct SDL_TextEditingExtEvent -{ - Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING_EXT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char* text; /**< The editing text, which should be freed with SDL_free(), and will not be NULL */ - Sint32 start; /**< The start cursor of selected editing text */ - Sint32 length; /**< The length of selected editing text */ -} SDL_TextEditingExtEvent; - -#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32) +#define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** * \brief Keyboard text input event structure (event.text.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextInputEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ + char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ } SDL_TextInputEvent; /** @@ -520,19 +510,21 @@ typedef struct SDL_TouchFingerEvent } SDL_TouchFingerEvent; +#define SDL_DROPEVENT_DATA_SIZE 64 /** - * \brief An event used to request a file open by the system (event.drop.*) - * This event is enabled by default, you can disable it with SDL_SetEventEnabled(). - * \note If this event is enabled, you must free the filename in the event. + * \brief An event used to drop text or request a file open by the system (event.drop.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_DropEvent { Uint32 type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE or ::SDL_EVENT_DROP_POSITION */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */ SDL_WindowID windowID; /**< The window that was dropped on, if any */ float x; /**< X coordinate, relative to window (not on begin) */ float y; /**< Y coordinate, relative to window (not on begin) */ + char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ + char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data */ } SDL_DropEvent; /** @@ -595,6 +587,8 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; * \brief A video driver dependent system event (event.syswm.*) * This event is disabled by default, you can enable it with SDL_SetEventEnabled() * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. + * * \note If you want to use this event, you should include SDL_syswm.h. */ typedef struct SDL_SysWMEvent @@ -615,7 +609,6 @@ typedef union SDL_Event SDL_WindowEvent window; /**< Window event data */ SDL_KeyboardEvent key; /**< Keyboard event data */ SDL_TextEditingEvent edit; /**< Text editing event data */ - SDL_TextEditingExtEvent editExt; /**< Extended text editing event data */ SDL_TextInputEvent text; /**< Text input event data */ SDL_MouseMotionEvent motion; /**< Mouse motion event data */ SDL_MouseButtonEvent button; /**< Mouse button event data */ @@ -855,10 +848,8 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetEventFilter - * \sa SDL_PeepEvents + * \sa SDL_CleanupEvent * \sa SDL_PushEvent - * \sa SDL_SetEventFilter * \sa SDL_WaitEvent * \sa SDL_WaitEventTimeout */ @@ -880,8 +871,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PollEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CleanupEvent * \sa SDL_PollEvent - * \sa SDL_PumpEvents + * \sa SDL_PushEvent * \sa SDL_WaitEventTimeout */ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); @@ -908,12 +900,34 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CleanupEvent * \sa SDL_PollEvent - * \sa SDL_PumpEvents + * \sa SDL_PushEvent * \sa SDL_WaitEvent */ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); +/** + * Clean up dynamically allocated memory for an event. + * + * Some events have dynamically allocated data that must be cleaned up when the event is processed. If you handle any of these events, you should call SDL_CleanupEvent() after processing them: + * SDL_EVENT_DROP_FILE + * SDL_EVENT_DROP_TEXT + * SDL_EVENT_SYSWM + * SDL_EVENT_TEXT_EDITING + * + * It is safe, but not necessary, to call this function for other event types. + * + * \param event a pointer to the event that should be cleaned up + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_WaitEvent + * \sa SDL_WaitEventTimeout + */ +extern DECLSPEC void SDLCALL SDL_CleanupEvent(SDL_Event *event); + /** * Add an event to the event queue. * diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 2af3c88fff89e..fd746553ce2c0 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -632,17 +632,6 @@ extern "C" { */ #define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI" -/** - * \brief A variable to control if extended IME text support is enabled. - * If enabled then SDL_TextEditingExtEvent will be issued if the text would be truncated otherwise. - * Additionally SDL_TextInputEvent will be dispatched multiple times so that it is not truncated. - * - * The variable can be set to the following values: - * "0" - Legacy behavior. Text can be truncated, no heap allocations. (default) - * "1" - Modern behavior. - */ -#define SDL_HINT_IME_SUPPORT_EXTENDED_TEXT "SDL_IME_SUPPORT_EXTENDED_TEXT" - /** * \brief A variable controlling whether the home indicator bar on iPhone X * should be hidden. diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index d7cfe6be28a6e..bbf3f453764aa 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -212,26 +212,11 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m Sint32 start_pos, end_pos; size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text, &start_pos, &end_pos); if (text_bytes) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - if (start_pos == -1) { - Sint32 byte_pos = Fcitx_GetPreeditCursorByte(dbus, msg); - start_pos = byte_pos >= 0 ? SDL_utf8strnlen(text, byte_pos) : -1; - } - SDL_SendEditingText(text, start_pos, end_pos >= 0 ? end_pos - start_pos : -1); - } else { - char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; - size_t i = 0; - size_t cursor = 0; - while (i < text_bytes) { - const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const size_t chars = SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - - i += sz; - cursor += chars; - } + if (start_pos == -1) { + Sint32 byte_pos = Fcitx_GetPreeditCursorByte(dbus, msg); + start_pos = byte_pos >= 0 ? SDL_utf8strnlen(text, byte_pos) : -1; } + SDL_SendEditingText(text, start_pos, end_pos >= 0 ? end_pos - start_pos : -1); SDL_free(text); } else { SDL_SendEditingText("", 0, 0); diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 592dc9d49e764..4c1b838635fa6 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -252,38 +252,23 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * text = IBus_GetVariantText(conn, &iter, dbus); if (text) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - Uint32 pos, start_pos, end_pos; - SDL_bool has_pos = SDL_FALSE; - SDL_bool has_dec_pos = SDL_FALSE; + Uint32 pos, start_pos, end_pos; + SDL_bool has_pos = SDL_FALSE; + SDL_bool has_dec_pos = SDL_FALSE; + dbus->message_iter_init(msg, &iter); + has_dec_pos = IBus_GetDecorationPosition(conn, &iter, dbus, &start_pos, &end_pos); + if (!has_dec_pos) { dbus->message_iter_init(msg, &iter); - has_dec_pos = IBus_GetDecorationPosition(conn, &iter, dbus, &start_pos, &end_pos); - if (!has_dec_pos) { - dbus->message_iter_init(msg, &iter); - has_pos = IBus_GetVariantCursorPos(conn, &iter, dbus, &pos); - } + has_pos = IBus_GetVariantCursorPos(conn, &iter, dbus, &pos); + } - if (has_dec_pos) { - SDL_SendEditingText(text, start_pos, end_pos - start_pos); - } else if (has_pos) { - SDL_SendEditingText(text, pos, -1); - } else { - SDL_SendEditingText(text, -1, -1); - } + if (has_dec_pos) { + SDL_SendEditingText(text, start_pos, end_pos - start_pos); + } else if (has_pos) { + SDL_SendEditingText(text, pos, -1); } else { - char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; - size_t text_bytes = SDL_strlen(text), i = 0; - size_t cursor = 0; - - do { - const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const size_t chars = SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - i += sz; - cursor += chars; - } while (i < text_bytes); + SDL_SendEditingText(text, -1, -1); } } diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 6ee8a813a9791..75e19c3c1bf1a 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -921,6 +921,7 @@ SDL3_0.0.0 { SDL_GetWindowProperties; SDL_ClearProperty; SDL_EnterAppMainCallbacks; + SDL_CleanupEvent; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 09c6dbbd45712..4cfa591664665 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -946,3 +946,4 @@ #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL #define SDL_ClearProperty SDL_ClearProperty_REAL #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL +#define SDL_CleanupEvent SDL_CleanupEvent_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d584067fb231e..d73e3e312af6b 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -978,3 +978,4 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),r SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(void,SDL_CleanupEvent,(SDL_Event *a),(a),) diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index 5aa4a99236e46..211b8d3b37f30 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -58,7 +58,15 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch SDL_zero(event); event.type = evtype; event.common.timestamp = 0; - event.drop.file = data ? SDL_strdup(data) : NULL; + if (data) { + size_t len = SDL_strlen(data); + if (len < sizeof(event.drop.short_data)) { + SDL_memcpy(event.drop.short_data, data, len + 1); + event.drop.data = event.drop.short_data; + } else { + event.drop.data = SDL_strdup(data); + } + } event.drop.windowID = window ? window->id : 0; if (evtype == SDL_EVENT_DROP_POSITION) { diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 031e660accbc2..1ce42ad5756d6 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -75,17 +75,10 @@ static Uint32 SDL_userevents = SDL_EVENT_USER; typedef struct SDL_EventEntry { SDL_Event event; - SDL_SysWMmsg msg; struct SDL_EventEntry *prev; struct SDL_EventEntry *next; } SDL_EventEntry; -typedef struct SDL_SysWMEntry -{ - SDL_SysWMmsg msg; - struct SDL_SysWMEntry *next; -} SDL_SysWMEntry; - static struct { SDL_Mutex *lock; @@ -95,9 +88,7 @@ static struct SDL_EventEntry *head; SDL_EventEntry *tail; SDL_EventEntry *free; - SDL_SysWMEntry *wmmsg_used; - SDL_SysWMEntry *wmmsg_free; -} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }; +} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL }; #ifndef SDL_JOYSTICK_DISABLED @@ -419,7 +410,7 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_FINGER_EVENT -#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (file='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.file, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y) +#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y) SDL_EVENT_CASE(SDL_EVENT_DROP_FILE) PRINT_DROP_EVENT(event); break; @@ -484,7 +475,6 @@ void SDL_StopEventLoop(void) const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS"); int i; SDL_EventEntry *entry; - SDL_SysWMEntry *wmmsg; SDL_LockMutex(SDL_EventQ.lock); @@ -506,24 +496,12 @@ void SDL_StopEventLoop(void) SDL_free(entry); entry = next; } - for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg;) { - SDL_SysWMEntry *next = wmmsg->next; - SDL_free(wmmsg); - wmmsg = next; - } - for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg;) { - SDL_SysWMEntry *next = wmmsg->next; - SDL_free(wmmsg); - wmmsg = next; - } SDL_AtomicSet(&SDL_EventQ.count, 0); SDL_EventQ.max_events_seen = 0; SDL_EventQ.head = NULL; SDL_EventQ.tail = NULL; SDL_EventQ.free = NULL; - SDL_EventQ.wmmsg_used = NULL; - SDL_EventQ.wmmsg_free = NULL; SDL_AtomicSet(&SDL_sentinel_pending, 0); /* Clear disabled event state */ @@ -622,9 +600,6 @@ static int SDL_AddEvent(SDL_Event *event) entry->event = *event; if (event->type == SDL_EVENT_POLL_SENTINEL) { SDL_AtomicAdd(&SDL_sentinel_pending, 1); - } else if (event->type == SDL_EVENT_SYSWM) { - entry->msg = *event->syswm.msg; - entry->event.syswm.msg = &entry->msg; } if (SDL_EventQ.tail) { @@ -724,43 +699,14 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact } } else { SDL_EventEntry *entry, *next; - SDL_SysWMEntry *wmmsg, *wmmsg_next; Uint32 type; - if (action == SDL_GETEVENT) { - /* Clean out any used wmmsg data - FIXME: Do we want to retain the data for some period of time? - */ - for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) { - wmmsg_next = wmmsg->next; - wmmsg->next = SDL_EventQ.wmmsg_free; - SDL_EventQ.wmmsg_free = wmmsg; - } - SDL_EventQ.wmmsg_used = NULL; - } - for (entry = SDL_EventQ.head; entry && (events == NULL || used < numevents); entry = next) { next = entry->next; type = entry->event.type; if (minType <= type && type <= maxType) { if (events) { events[used] = entry->event; - if (entry->event.type == SDL_EVENT_SYSWM) { - /* We need to copy the wmmsg somewhere safe. - For now we'll guarantee it's valid at least until - the next call to SDL_PeepEvents() - */ - if (SDL_EventQ.wmmsg_free) { - wmmsg = SDL_EventQ.wmmsg_free; - SDL_EventQ.wmmsg_free = wmmsg->next; - } else { - wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg)); - } - wmmsg->msg = *entry->event.syswm.msg; - wmmsg->next = SDL_EventQ.wmmsg_used; - SDL_EventQ.wmmsg_used = wmmsg; - events[used].syswm.msg = &wmmsg->msg; - } if (action == SDL_GETEVENT) { SDL_CutEvent(entry); @@ -818,9 +764,6 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) { SDL_EventEntry *entry, *next; Uint32 type; - /* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and - drag'n'drop events if we're flushing them without passing them to the - app, but I don't know if this is the right place to do that. */ /* Make sure the events are current */ #if 0 @@ -842,6 +785,7 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) next = entry->next; type = entry->event.type; if (minType <= type && type <= maxType) { + SDL_CleanupEvent(&entry->event); SDL_CutEvent(entry); } } @@ -1124,6 +1068,33 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) } } +void SDL_CleanupEvent(SDL_Event *event) +{ + switch (event->type) { + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + if (event->drop.data && event->drop.data != event->drop.short_data) { + SDL_free(event->drop.data); + event->drop.data = NULL; + } + break; + case SDL_EVENT_SYSWM: + if (event->syswm.msg) { + SDL_free(event->syswm.msg); + event->syswm.msg = NULL; + } + break; + case SDL_EVENT_TEXT_EDITING: + if (event->edit.text && event->edit.text != event->edit.short_text) { + SDL_free(event->edit.text); + event->edit.text = NULL; + } + break; + default: + break; + } +} + int SDL_PushEvent(SDL_Event *event) { if (!event->common.timestamp) { @@ -1380,7 +1351,11 @@ int SDL_SendSysWMEvent(SDL_SysWMmsg *message) SDL_memset(&event, 0, sizeof(event)); event.type = SDL_EVENT_SYSWM; event.common.timestamp = 0; - event.syswm.msg = message; + event.syswm.msg = (SDL_SysWMmsg *)SDL_malloc(sizeof(*message)); + if (!event.syswm.msg) { + return 0; + } + SDL_copyp(event.syswm.msg, message); posted = (SDL_PushEvent(&event) > 0); } /* Update internal event state */ diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 59968b55fc6ab..49f38b9f490d0 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1098,21 +1098,18 @@ int SDL_SendEditingText(const char *text, int start, int length) if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) { SDL_Event event; - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE) && - SDL_strlen(text) >= SDL_arraysize(event.text.text)) { - event.type = SDL_EVENT_TEXT_EDITING_EXT; - event.common.timestamp = 0; - event.editExt.windowID = keyboard->focus ? keyboard->focus->id : 0; - event.editExt.text = text ? SDL_strdup(text) : NULL; - event.editExt.start = start; - event.editExt.length = length; + event.type = SDL_EVENT_TEXT_EDITING; + event.common.timestamp = 0; + event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; + event.edit.start = start; + event.edit.length = length; + + size_t len = SDL_strlen(text); + if (len < sizeof(event.edit.short_text)) { + SDL_memcpy(event.edit.short_text, text, len + 1); + event.edit.text = event.edit.short_text; } else { - event.type = SDL_EVENT_TEXT_EDITING; - event.common.timestamp = 0; - event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; - event.edit.start = start; - event.edit.length = length; - SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); + event.edit.text = SDL_strdup(text); } posted = (SDL_PushEvent(&event) > 0); diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index a20f9f6ac8624..2ac9abaf8f5aa 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -83,22 +83,7 @@ int SDL_IterateMainCallbacks(void) { // Just pump events and empty the queue, EventWatcher sends the events to the app. SDL_PumpEvents(); - - for (;;) { - SDL_Event events[32]; - int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); - if (count <= 0) { - break; - } - for (int i = 0; i < count; ++i) { - switch (events[i].type) { - case SDL_EVENT_DROP_FILE: - case SDL_EVENT_DROP_TEXT: - SDL_free(events[i].drop.file); - break; - } - } - } + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); int rc = SDL_main_iteration_callback(); if (!SDL_AtomicCAS(&apprc, 0, rc)) { diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index b10bc24255057..4e179829ce3ad 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1823,10 +1823,10 @@ static void SDLTest_PrintEvent(const SDL_Event *event) SDL_Log("SDL EVENT: Drag and drop beginning"); break; case SDL_EVENT_DROP_FILE: - SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.file); + SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.data); break; case SDL_EVENT_DROP_TEXT: - SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.file); + SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.data); break; case SDL_EVENT_DROP_COMPLETE: SDL_Log("SDL EVENT: Drag and drop ending"); @@ -2425,12 +2425,7 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done { *done = SDLTest_CommonEventMainCallbacks(state, event) ? 1 : 0; - switch (event->type) { - case SDL_EVENT_DROP_FILE: - case SDL_EVENT_DROP_TEXT: - SDL_free(event->drop.file); // SDL frees these if you use SDL_AppEvent, not us, so explicitly handle it here. - break; - } + SDL_CleanupEvent(event); } void SDLTest_CommonQuit(SDLTest_CommonState *state) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index b4700e8db48fe..c68b49c3c250f 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -2191,33 +2191,19 @@ static void text_input_preedit_string(void *data, char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; text_input->has_preedit = SDL_TRUE; if (text) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - int cursor_begin_utf8 = cursor_begin >= 0 ? (int)SDL_utf8strnlen(text, cursor_begin) : -1; - int cursor_end_utf8 = cursor_end >= 0 ? (int)SDL_utf8strnlen(text, cursor_end) : -1; - int cursor_size_utf8; - if (cursor_end_utf8 >= 0) { - if (cursor_begin_utf8 >= 0) { - cursor_size_utf8 = cursor_end_utf8 - cursor_begin_utf8; - } else { - cursor_size_utf8 = cursor_end_utf8; - } + int cursor_begin_utf8 = cursor_begin >= 0 ? (int)SDL_utf8strnlen(text, cursor_begin) : -1; + int cursor_end_utf8 = cursor_end >= 0 ? (int)SDL_utf8strnlen(text, cursor_end) : -1; + int cursor_size_utf8; + if (cursor_end_utf8 >= 0) { + if (cursor_begin_utf8 >= 0) { + cursor_size_utf8 = cursor_end_utf8 - cursor_begin_utf8; } else { - cursor_size_utf8 = -1; + cursor_size_utf8 = cursor_end_utf8; } - SDL_SendEditingText(text, cursor_begin_utf8, cursor_size_utf8); } else { - int text_bytes = (int)SDL_strlen(text), i = 0; - int cursor = 0; - do { - const int sz = (int)SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const int chars = (int)SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - - i += sz; - cursor += chars; - } while (i < text_bytes); + cursor_size_utf8 = -1; } + SDL_SendEditingText(text, cursor_begin_utf8, cursor_size_utf8); } else { buf[0] = '\0'; SDL_SendEditingText(buf, 0, 0); diff --git a/test/checkkeys.c b/test/checkkeys.c index 0db15282167e8..11fd5b6ced63d 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -181,10 +181,7 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.edit.text); - break; - case SDL_EVENT_TEXT_EDITING_EXT: - PrintText("EDIT_EXT", event.editExt.text); - SDL_free(event.editExt.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); @@ -261,9 +258,6 @@ int main(int argc, char *argv[]) /* Disable mouse emulation */ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - /* Enable extended text editing events */ - SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1"); - /* Initialize SDL */ if (!SDLTest_CommonInit(state)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index cca4740e4c0be..64e0dc418d34c 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -183,6 +183,7 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.text.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); diff --git a/test/testaudio.c b/test/testaudio.c index e6ee2c1e15571..210b9c29b29e7 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -1178,9 +1178,9 @@ int SDL_AppEvent(const SDL_Event *event) break; case SDL_EVENT_DROP_FILE: - SDL_Log("Drop file! '%s'", event->drop.file); - LoadWavThing(event->drop.file, event->drop.x, event->drop.y); - /* SDL frees event->drop.file for you when you use SDL_AppEvent(). */ + SDL_Log("Drop file! '%s'", event->drop.data); + LoadWavThing(event->drop.data, event->drop.x, event->drop.y); + /* SDL frees event->drop.data for you when you use SDL_AppEvent(). */ break; case SDL_EVENT_WINDOW_RESIZED: diff --git a/test/testdropfile.c b/test/testdropfile.c index 2e4efedbab98b..3da1a79126304 100644 --- a/test/testdropfile.c +++ b/test/testdropfile.c @@ -56,9 +56,6 @@ int main(int argc, char *argv[]) goto quit; } - - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_TRUE); - /* Main render loop */ done = 0; while (!done) { @@ -71,16 +68,15 @@ int main(int argc, char *argv[]) SDL_Log("Drop complete on window %u at (%f, %f)", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y); } else if ((event.type == SDL_EVENT_DROP_FILE) || (event.type == SDL_EVENT_DROP_TEXT)) { const char *typestr = (event.type == SDL_EVENT_DROP_FILE) ? "File" : "Text"; - char *dropped_filedir = event.drop.file; - SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, dropped_filedir, event.drop.x, event.drop.y); + SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, event.drop.data, event.drop.x, event.drop.y); /* Normally you'd have to do this, but this is freed in SDLTest_CommonEvent() */ - /*SDL_free(dropped_filedir);*/ + /*SDL_CleanupEvent(&event);*/ } else if (event.type == SDL_EVENT_DROP_POSITION) { is_hover = SDL_TRUE; x = event.drop.x; y = event.drop.y; windowID = event.drop.windowID; - SDL_Log("Drop position on window %u at (%f, %f) file = %s", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y, event.drop.file); + SDL_Log("Drop position on window %u at (%f, %f) data = %s", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y, event.drop.data); } SDLTest_CommonEvent(state, &event, &done); diff --git a/test/testime.c b/test/testime.c index 84d3aecbbdee9..58010bd485e2d 100644 --- a/test/testime.c +++ b/test/testime.c @@ -779,6 +779,7 @@ int main(int argc, char *argv[]) SDL_strlcpy(markedText, event.edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE); cursor = event.edit.start; Redraw(); + SDL_CleanupEvent(&event); break; } } diff --git a/test/testwm.c b/test/testwm.c index 9116700a2ebe0..7de55701ec4a8 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -265,9 +265,6 @@ int main(int argc, char *argv[]) return 1; } - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_TRUE); - for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); From 019468dc59ebb810ad705fc96577e210fe0c7657 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 4 Nov 2023 09:31:07 -0400 Subject: [PATCH 213/725] main: Check for SDL_AddEventWatch failure, now that it can report it. --- src/main/SDL_main_callbacks.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 2ac9abaf8f5aa..076c842597ba4 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -67,7 +67,11 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ total_pending_events++; } - SDL_AddEventWatch(EventWatcher, NULL); // !!! FIXME: this should really return an error. + if (SDL_AddEventWatch(EventWatcher, NULL) == -1) { + SDL_free(pending_events); + SDL_AtomicSet(&apprc, -1); + return -1; + } for (int i = 0; i < total_pending_events; i++) { SDL_PushEvent(&pending_events[i]); From a19029e3c14e8027019900de1311267693c198ac Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 4 Nov 2023 10:02:46 -0400 Subject: [PATCH 214/725] docs: Updated README-main-functions.md based on feedback. --- docs/README-main-functions.md | 32 +++++++++++--------------------- include/SDL3/SDL_main.h | 8 ++++++++ 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index cc4ca0c1441a0..7b6d79b906a0d 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -29,27 +29,12 @@ SDL's macro magic would quietly rename your function to `SDL_main`, and provide its own entry point that called it. Your app was none the wiser and your code worked everywhere without changes. -In SDL1, you linked with a static library that had startup code that _had_ to -run before you hit SDL_main(). For example, on macOS it would do various -magic to the process to make sure it was in the right state. Windows would -register win32 window classes and such. Things would break if you tried to -circumvent this, and you were in for a lot of trouble if you tried to use -SDL on a platform that needed this when you didn't control the entry point -(for example, as a plugin, or an SDL binding in a scripting language). - -In SDL2, the necessary support code moved into the main library, and the tiny -static library _only_ handled the basics of getting from the platform's real -entry point (like WinMain) to SDL_main; if the real entry was _already_ -standard main, the static library and macro magic was unnecessary. The goal -was to make it so you didn't have to change _your_ code to work on multiple -platforms and remove the original limitations. - -In SDL3, we've taken this much, much further. ## The main entry point in SDL3 -SDL3 still has the same macro tricks, but the static library is gone. Now it's -supplied by a "single-header library," which is to say you +Previous versions of SDL had a static library, SDLmain, that you would link +your app against. SDL3 still has the same macro tricks, but the static library +is gone. Now it's supplied by a "single-header library," which means you `#include ` and that header will insert a small amount of code into the source file that included it, so you no longer have to worry about linking against an extra library that you might need on some platforms. @@ -88,7 +73,7 @@ the SDL API when you are ready. ## Main callbacks in SDL3 There is a second option in SDL3 for how to structure your program. This is -completly optional and you can ignore it if you're happy using a standard +completely optional and you can ignore it if you're happy using a standard "main" function. Some platforms would rather your program operate in chunks. Most of the time, @@ -191,12 +176,18 @@ int SDL_AppEvent(const SDL_Event *event); This will be called once for each event pushed into the SDL queue. This may be called from any thread, and possibly in parallel to SDL_AppIterate. The fields -in `event` do not need to be free'd (as you would normally need to do for +in `event` should not be free'd (as you would normally need to do for SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the same as from SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. +One can still use their own event filters and watchers. Filters set with +SDL_SetEventFilter will run before SDL_AppEvent, and if it filters out the +event, SDL_AppEvent will not run at all. Watchers set with SDL_AddEventWatch +will run in serial to SDL_AppEvent, as SDL_AppEvent itself is built on top of +an event watcher; which one runs first is not guaranteed. + Finally: @@ -210,4 +201,3 @@ SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app to call it, too). Process termination proceeds as if the app returned normally from main(), so atexit handles will run, if your platform supports that. - diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 8c070b933d897..424d3deeb8148 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -24,6 +24,14 @@ #include +/* + * For details on how SDL_main works, and how to use it, please refer to: + * + * https://wiki.libsdl.org/SDL3/README/main-functions + * + * (or docs/README-main-functions.md in the SDL source tree) + */ + /** * \file SDL_main.h * From ad9dcdbbce4adf82b9af9cd0eef812ca3d49d24b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 09:58:35 -0700 Subject: [PATCH 215/725] Clarify that you should use the other field when reading the event --- include/SDL3/SDL_events.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 312452444cd93..ad87c5ccb4702 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -268,7 +268,7 @@ typedef struct SDL_TextEditingEvent Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ char *text; /**< The editing text */ - char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short editing text */ + char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short editing text, use 'text' instead */ Sint32 start; /**< The start cursor of selected editing text */ Sint32 length; /**< The length of selected editing text */ } SDL_TextEditingEvent; @@ -524,7 +524,7 @@ typedef struct SDL_DropEvent float x; /**< X coordinate, relative to window (not on begin) */ float y; /**< Y coordinate, relative to window (not on begin) */ char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ - char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data */ + char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data, use 'data' instead */ } SDL_DropEvent; /** From 274da8561c1578f05852f29b4d0d31201cc3820d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 10:42:28 -0700 Subject: [PATCH 216/725] Updated the migration guide to note that you can check the return value of SDL_AddEventWatch() --- docs/README-migration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/README-migration.md b/docs/README-migration.md index e9ea328282388..bbe1fe56d83f9 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -314,6 +314,8 @@ The gamepad event structures caxis, cbutton, cdevice, ctouchpad, and csensor hav SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state. +SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback. + The following symbols have been renamed: * SDL_APP_DIDENTERBACKGROUND => SDL_EVENT_DID_ENTER_BACKGROUND * SDL_APP_DIDENTERFOREGROUND => SDL_EVENT_DID_ENTER_FOREGROUND From 4481754359009b2e54e5786e17be489a216bd0c1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 11:06:42 -0700 Subject: [PATCH 217/725] Make sure we only dispatch events on the main thread when using application callbacks --- src/main/SDL_main_callbacks.c | 81 ++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 076c842597ba4..6fd0783a4cfb8 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -27,11 +27,57 @@ static SDL_AppIterate_func SDL_main_iteration_callback; static SDL_AppQuit_func SDL_main_quit_callback; static SDL_AtomicInt apprc; // use an atomic, since events might land from any thread and we don't want to wrap this all in a mutex. A CAS makes sure we only move from zero once. -static int SDLCALL EventWatcher(void *userdata, SDL_Event *event) +// Return true if this event needs to be processed before returning from the event watcher +static SDL_bool ShouldDispatchImmediately(SDL_Event *event) { - if (SDL_AtomicGet(&apprc) == 0) { // if already quitting, don't send the event to the app. + switch (event->type) { + case SDL_EVENT_TERMINATING: + case SDL_EVENT_LOW_MEMORY: + case SDL_EVENT_WILL_ENTER_BACKGROUND: + case SDL_EVENT_DID_ENTER_BACKGROUND: + case SDL_EVENT_WILL_ENTER_FOREGROUND: + case SDL_EVENT_DID_ENTER_FOREGROUND: + return SDL_TRUE; + default: + return SDL_FALSE; + } +} + +static void SDL_DispatchMainCallbackEvent(SDL_Event *event) +{ + if (SDL_AtomicGet(&apprc) == 0) { // if already quitting, don't send the event to the app. SDL_AtomicCAS(&apprc, 0, SDL_main_event_callback(event)); } + SDL_CleanupEvent(event); +} + +static void SDL_DispatchMainCallbackEvents() +{ + SDL_Event events[16]; + + for (;;) { + int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); + if (count <= 0) { + break; + } + for (int i = 0; i < count; ++i) { + SDL_Event *event = &events[i]; + if (!ShouldDispatchImmediately(event)) { + SDL_DispatchMainCallbackEvent(event); + } + } + } +} + +static int SDLCALL SDL_MainCallbackEventWatcher(void *userdata, SDL_Event *event) +{ + if (ShouldDispatchImmediately(event)) { + // Make sure any currently queued events are processed then dispatch this before continuing + SDL_DispatchMainCallbackEvents(); + SDL_DispatchMainCallbackEvent(event); + } else { + // We'll process this event later from the main event queue + } return 0; } @@ -50,34 +96,10 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ return -1; } - // drain any initial events that might have arrived before we added a watcher. - SDL_Event event; - SDL_Event *pending_events = NULL; - int total_pending_events = 0; - while (SDL_PollEvent(&event)) { - void *ptr = SDL_realloc(pending_events, sizeof (SDL_Event) * (total_pending_events + 1)); - if (!ptr) { - SDL_OutOfMemory(); - SDL_free(pending_events); - SDL_AtomicSet(&apprc, -1); - return -1; - } - pending_events = (SDL_Event *) ptr; - SDL_copyp(&pending_events[total_pending_events], &event); - total_pending_events++; - } - - if (SDL_AddEventWatch(EventWatcher, NULL) == -1) { - SDL_free(pending_events); + if (SDL_AddEventWatch(SDL_MainCallbackEventWatcher, NULL) < 0) { SDL_AtomicSet(&apprc, -1); return -1; } - - for (int i = 0; i < total_pending_events; i++) { - SDL_PushEvent(&pending_events[i]); - } - - SDL_free(pending_events); } return SDL_AtomicGet(&apprc); @@ -85,9 +107,8 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ int SDL_IterateMainCallbacks(void) { - // Just pump events and empty the queue, EventWatcher sends the events to the app. SDL_PumpEvents(); - SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); + SDL_DispatchMainCallbackEvents(); int rc = SDL_main_iteration_callback(); if (!SDL_AtomicCAS(&apprc, 0, rc)) { @@ -99,7 +120,7 @@ int SDL_IterateMainCallbacks(void) void SDL_QuitMainCallbacks(void) { - SDL_DelEventWatch(EventWatcher, NULL); + SDL_DelEventWatch(SDL_MainCallbackEventWatcher, NULL); SDL_main_quit_callback(); // for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow. From 46b940d571e5db008237409f1e10ef8a60047a48 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 11:31:54 -0700 Subject: [PATCH 218/725] Updated documentation to note that the event callback is called on the same thread as the main iteration callback --- docs/README-main-functions.md | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 7b6d79b906a0d..598560f7ee908 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -174,19 +174,11 @@ Next: int SDL_AppEvent(const SDL_Event *event); ``` -This will be called once for each event pushed into the SDL queue. This may be -called from any thread, and possibly in parallel to SDL_AppIterate. The fields -in `event` should not be free'd (as you would normally need to do for -SDL_EVENT_DROP_FILE, etc), and your app should not call SDL_PollEvent, -SDL_PumpEvent, etc, as SDL will manage this for you. Return values are the -same as from SDL_AppIterate(), so you can terminate in response to -SDL_EVENT_QUIT, etc. - -One can still use their own event filters and watchers. Filters set with -SDL_SetEventFilter will run before SDL_AppEvent, and if it filters out the -event, SDL_AppEvent will not run at all. Watchers set with SDL_AddEventWatch -will run in serial to SDL_AppEvent, as SDL_AppEvent itself is built on top of -an event watcher; which one runs first is not guaranteed. +This will be called whenever an SDL event arrives, on the thread that runs +SDL_AppIterate. You don't need to call SDL_CleanupEvent(), and your app +should not call SDL_PollEvent, SDL_PumpEvent, etc, as SDL will manage this +for you. Return values are the same as from SDL_AppIterate(), so you can +terminate in response to SDL_EVENT_QUIT, etc. Finally: From 780b6612a925abb5c2c2020c44c2a54f53100801 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 4 Nov 2023 14:53:24 -0400 Subject: [PATCH 219/725] wayland: Wayland_Vulkan_GetInstanceExtensions didn't set the count variable. Fixes #8468. --- src/video/wayland/SDL_waylandvulkan.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 3e372bd2a66a3..b07aaf95e895d 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -118,12 +118,16 @@ void Wayland_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) } } -char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - Uint32 *count) +char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count) { static const char *const extensionsForWayland[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME }; + + if (count) { + *count = SDL_arraysize(extensionsForWayland); + } + return extensionsForWayland; } From d07a264a9bc42bd2d92ce12fab55f1855d0e8277 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 12:00:38 -0700 Subject: [PATCH 220/725] Use the default UCS2/UCS4 conversion rather than non-portable INTERNAL encoding Fxies https://github.com/libsdl-org/SDL/issues/1497 --- include/SDL3/SDL_stdinc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 43aaafc03adcd..a660f03befd9d 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -680,8 +680,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *inbuf, size_t inbytesleft); #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime From 1a8bf31a699b14cf9215cde6ff1b934daa15d731 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 4 Nov 2023 15:06:25 -0400 Subject: [PATCH 221/725] include: Fixing whitespace on SDL_MixAudioFormat. --- include/SDL3/SDL_audio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 2287259352f8e..c6e5526d321d9 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -1427,9 +1427,9 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV(const char *path, SDL_AudioSpec * spec, * \since This function is available since SDL 3.0.0. */ extern DECLSPEC int SDLCALL SDL_MixAudioFormat(Uint8 * dst, - const Uint8 * src, - SDL_AudioFormat format, - Uint32 len, int volume); + const Uint8 * src, + SDL_AudioFormat format, + Uint32 len, int volume); /** * Convert some audio data of one format to another format. From 91f045639160dece14ece8d404816d8e9b8a61e9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 12:40:52 -0700 Subject: [PATCH 222/725] Add the source application for drag and drop events (thanks Nathan!) This is only implemented on iOS, but is useful for third party application integrations. Fixes https://github.com/libsdl-org/SDL/issues/2024 --- include/SDL3/SDL_events.h | 1 + src/core/android/SDL_android.c | 2 +- src/core/haiku/SDL_BeApp.cc | 2 +- src/events/SDL_dropevents.c | 18 ++++++++++-------- src/events/SDL_dropevents_c.h | 4 ++-- src/events/SDL_events.c | 4 ++++ src/video/cocoa/SDL_cocoaevents.m | 4 ++-- src/video/cocoa/SDL_cocoawindow.m | 4 ++-- src/video/uikit/SDL_uikitappdelegate.m | 15 ++++++++------- src/video/wayland/SDL_waylandevents.c | 6 +++--- src/video/windows/SDL_windowsevents.c | 2 +- src/video/x11/SDL_x11events.c | 4 ++-- 12 files changed, 37 insertions(+), 29 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index ad87c5ccb4702..2afa92f3e58d7 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -523,6 +523,7 @@ typedef struct SDL_DropEvent SDL_WindowID windowID; /**< The window that was dropped on, if any */ float x; /**< X coordinate, relative to window (not on begin) */ float y; /**< Y coordinate, relative to window (not on begin) */ + char *source; /**< The source app that sent this drop event, or NULL if that isn't available */ char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data, use 'data' instead */ } SDL_DropEvent; diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 99ebd7492de7e..8626a6b6f56f4 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -878,7 +878,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)( jstring filename) { const char *path = (*env)->GetStringUTFChars(env, filename, NULL); - SDL_SendDropFile(NULL, path); + SDL_SendDropFile(NULL, NULL, path); (*env)->ReleaseStringUTFChars(env, filename, path); SDL_SendDropComplete(NULL); } diff --git a/src/core/haiku/SDL_BeApp.cc b/src/core/haiku/SDL_BeApp.cc index 16eb58aff485f..8403f9a18c6b8 100644 --- a/src/core/haiku/SDL_BeApp.cc +++ b/src/core/haiku/SDL_BeApp.cc @@ -69,7 +69,7 @@ class SDL_BApp : public BApplication { entry_ref entryRef; for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) { BPath referencePath = BPath(&entryRef); - SDL_SendDropFile(NULL, referencePath.Path()); + SDL_SendDropFile(NULL, NULL, referencePath.Path()); } return; } diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index 211b8d3b37f30..a7b9fa7a79a7f 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -27,7 +27,7 @@ #include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */ -static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *data, float x, float y) +static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *source, const char *data, float x, float y) { static SDL_bool app_is_dropping = SDL_FALSE; static float last_drop_x = 0; @@ -58,6 +58,9 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch SDL_zero(event); event.type = evtype; event.common.timestamp = 0; + if (source) { + event.drop.source = SDL_strdup(source); + } if (data) { size_t len = SDL_strlen(data); if (len < sizeof(event.drop.short_data)) { @@ -91,23 +94,22 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch return posted; } -int SDL_SendDropFile(SDL_Window *window, const char *file) +int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file) { - return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, file, 0, 0); + return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, source, file, 0, 0); } -int SDL_SendDropPosition(SDL_Window *window, const char *file, float x, float y) +int SDL_SendDropPosition(SDL_Window *window, float x, float y) { - /* Don't send 'file' since this is an malloc per position, which may be forgotten to be freed */ - return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, x, y); + return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, NULL, x, y); } int SDL_SendDropText(SDL_Window *window, const char *text) { - return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, text, 0, 0); + return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, NULL, text, 0, 0); } int SDL_SendDropComplete(SDL_Window *window) { - return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, 0, 0); + return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, NULL, 0, 0); } diff --git a/src/events/SDL_dropevents_c.h b/src/events/SDL_dropevents_c.h index 9a485cd0b2ec7..f2396d5d30c0a 100644 --- a/src/events/SDL_dropevents_c.h +++ b/src/events/SDL_dropevents_c.h @@ -23,8 +23,8 @@ #ifndef SDL_dropevents_c_h_ #define SDL_dropevents_c_h_ -extern int SDL_SendDropFile(SDL_Window *window, const char *file); -extern int SDL_SendDropPosition(SDL_Window *window, const char *file, float x, float y); +extern int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file); +extern int SDL_SendDropPosition(SDL_Window *window, float x, float y); extern int SDL_SendDropText(SDL_Window *window, const char *text); extern int SDL_SendDropComplete(SDL_Window *window); diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 1ce42ad5756d6..3f18641a7496b 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -1073,6 +1073,10 @@ void SDL_CleanupEvent(SDL_Event *event) switch (event->type) { case SDL_EVENT_DROP_FILE: case SDL_EVENT_DROP_TEXT: + if (event->drop.source) { + SDL_free(event->drop.source); + event->drop.data = NULL; + } if (event->drop.data && event->drop.data != event->drop.short_data) { SDL_free(event->drop.data); event->drop.data = NULL; diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 221a61d91bb24..3674965c8b56e 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -287,7 +287,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { - return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL); + return (BOOL)SDL_SendDropFile(NULL, NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL); } - (void)applicationDidFinishLaunching:(NSNotification *)notification @@ -315,7 +315,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { NSString *path = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; - SDL_SendDropFile(NULL, [path UTF8String]); + SDL_SendDropFile(NULL, NULL, [path UTF8String]); SDL_SendDropComplete(NULL); } diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index f86027e0e768b..970e8e1f17cdd 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -177,7 +177,7 @@ - (NSDragOperation)draggingUpdated:(id)sender float x, y; x = point.x; y = (sdlwindow->h - point.y); - SDL_SendDropPosition(sdlwindow, NULL, x, y); /* FIXME, should we get the filename */ + SDL_SendDropPosition(sdlwindow, x, y); return NSDragOperationGeneric; } @@ -242,7 +242,7 @@ - (BOOL)performDragOperation:(id)sender } } - if (!SDL_SendDropFile(sdlwindow, [[fileURL path] UTF8String])) { + if (!SDL_SendDropFile(sdlwindow, NULL, [[fileURL path] UTF8String])) { return NO; } } diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index e9d6ca33793bb..8a4c0e4605b59 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -212,7 +212,7 @@ - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibB NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"]; NSString *imagename = nil; UIImage *image = nil; - + #if TARGET_OS_XR int screenw = SDL_XR_SCREENWIDTH; int screenh = SDL_XR_SCREENHEIGHT; @@ -221,7 +221,7 @@ - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibB int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5); #endif - + #if !TARGET_OS_TV && !TARGET_OS_XR UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation; @@ -505,13 +505,14 @@ - (void)setWindow:(UIWindow *)window /* Do nothing. */ } -- (void)sendDropFileForURL:(NSURL *)url +- (void)sendDropFileForURL:(NSURL *)url fromSourceApplication:(NSString *)sourceApplication { NSURL *fileURL = url.filePathURL; + char *sourceApplicationCString = sourceApplication ? [sourceApplication UTF8String] : NULL; if (fileURL != nil) { - SDL_SendDropFile(NULL, fileURL.path.UTF8String); + SDL_SendDropFile(NULL, sourceApplicationCString, fileURL.path.UTF8String); } else { - SDL_SendDropFile(NULL, url.absoluteString.UTF8String); + SDL_SendDropFile(NULL, sourceApplicationCString, url.absoluteString.UTF8String); } SDL_SendDropComplete(NULL); } @@ -521,7 +522,7 @@ - (void)sendDropFileForURL:(NSURL *)url - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { /* TODO: Handle options */ - [self sendDropFileForURL:url]; + [self sendDropFileForURL:url fromSourceApplication:NULL]; return YES; } @@ -529,7 +530,7 @@ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDiction - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { - [self sendDropFileForURL:url]; + [self sendDropFileForURL:url fromSourceApplication:sourceApplication]; return YES; } diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index c68b49c3c250f..2e9583cc7b76f 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -1909,7 +1909,7 @@ static void data_device_handle_motion(void *data, struct wl_data_device *wl_data * Any future implementation should cache the filenames, as otherwise this could * hammer the DBus interface hundreds or even thousands of times per second. */ - SDL_SendDropPosition(data_device->dnd_window, NULL, dx, dy); + SDL_SendDropPosition(data_device->dnd_window, dx, dy); } } @@ -2055,7 +2055,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d /* If dropped files contain a directory the list is empty */ if (paths && path_count > 0) { for (int i = 0; i < path_count; i++) { - SDL_SendDropFile(data_device->dnd_window, paths[i]); + SDL_SendDropFile(data_device->dnd_window, NULL, paths[i]); } dbus->free_string_array(paths); SDL_SendDropComplete(data_device->dnd_window); @@ -2080,7 +2080,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d while (token != NULL) { char *fn = Wayland_URIToLocal(token); if (fn) { - SDL_SendDropFile(data_device->dnd_window, fn); + SDL_SendDropFile(data_device->dnd_window, NULL, fn); } token = SDL_strtok_r(NULL, "\r\n", &saveptr); } diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index f2e747ee9c920..042667c84b44d 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1478,7 +1478,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (buffer) { if (DragQueryFile(drop, i, buffer, size)) { char *file = WIN_StringToUTF8(buffer); - SDL_SendDropFile(data->window, file); + SDL_SendDropFile(data->window, NULL, file); SDL_free(file); } SDL_small_free(buffer, isstack); diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index d414ee66a1af3..9c7afcf445208 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1327,7 +1327,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow, root_x, root_y, &window_x, &window_y, &ChildReturn); - SDL_SendDropPosition(data->window, NULL, (float)window_x, (float)window_y); /* FIXME, can we get the filename ? */ + SDL_SendDropPosition(data->window, (float)window_x, (float)window_y); } /* reply with status */ @@ -1629,7 +1629,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } else if (SDL_strcmp("text/uri-list", name) == 0) { char *fn = X11_URIToLocal(token); if (fn) { - SDL_SendDropFile(data->window, fn); + SDL_SendDropFile(data->window, NULL, fn); } } token = SDL_strtok_r(NULL, "\r\n", &saveptr); From 52c4e3eab3bef2ffc30f7ad6d6a451587d3be9df Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 4 Nov 2023 18:03:53 -0400 Subject: [PATCH 223/725] events: Update self-referential pointers when copying event objects Pointers to static internal data need to be updated when copying events, or the cleanup code will attempt to free old stack data that went out of scope. --- src/events/SDL_events.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 3f18641a7496b..c6616fe462b81 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -468,6 +468,18 @@ static void SDL_LogEvent(const SDL_Event *event) #undef uint } +static void SDL_CopyEvent(SDL_Event *dst, SDL_Event *src) +{ + *dst = *src; + + /* Pointers to internal static data must be updated when copying. */ + if (src->type == SDL_EVENT_TEXT_EDITING && src->edit.text == src->edit.short_text) { + dst->edit.text = dst->edit.short_text; + } else if (src->type == SDL_EVENT_DROP_TEXT && src->drop.data == src->drop.short_data) { + dst->drop.data = dst->drop.short_data; + } +} + /* Public functions */ void SDL_StopEventLoop(void) @@ -597,7 +609,7 @@ static int SDL_AddEvent(SDL_Event *event) SDL_LogEvent(event); } - entry->event = *event; + SDL_CopyEvent(&entry->event, event); if (event->type == SDL_EVENT_POLL_SENTINEL) { SDL_AtomicAdd(&SDL_sentinel_pending, 1); } @@ -706,7 +718,7 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact type = entry->event.type; if (minType <= type && type <= maxType) { if (events) { - events[used] = entry->event; + SDL_CopyEvent(&events[used], &entry->event); if (action == SDL_GETEVENT) { SDL_CutEvent(entry); From f9d11807c01ddde40f8f218b9cbb6021405d9018 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 13:57:16 -0700 Subject: [PATCH 224/725] Added SDL_RWprintf() and SDL_RWvprintf() to do formatted printing to an SDL_rwops stream Fixes https://github.com/libsdl-org/SDL/issues/2390 --- include/SDL3/SDL_rwops.h | 45 +++++++++++++++++++++++++++++++ src/dynapi/SDL_dynapi.c | 20 ++++++++++++++ src/dynapi/SDL_dynapi.sym | 2 ++ src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ src/file/SDL_rwops.c | 29 ++++++++++++++++++++ test/testautomation_rwops.c | 35 ++++++++++++++++++++++-- 7 files changed, 133 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 26fd5299f471f..8ecd75f1d6844 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -490,11 +490,56 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t * \sa SDL_RWFromConstMem * \sa SDL_RWFromFile * \sa SDL_RWFromMem + * \sa SDL_RWprint * \sa SDL_RWread * \sa SDL_RWseek */ extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size); +/** + * Print to an SDL_RWops data stream. + * + * This function does formatted printing to the stream. + * + * \param context a pointer to an SDL_RWops structure + * \param fmt a printf() style format string + * \param ... additional parameters matching % tokens in the `fmt` string, if any + * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWwrite + */ +extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...); + +/** + * Print to an SDL_RWops data stream. + * + * This function does formatted printing to the stream. + * + * \param context a pointer to an SDL_RWops structure + * \param fmt a printf() style format string + * \param ap a variable argument list + * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWwrite + */ +extern DECLSPEC size_t SDLCALL SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap); + /** * Close and free an allocated SDL_RWops structure. * diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 603ea36a3df2b..23cf60432e301 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -144,6 +144,16 @@ static void SDL_InitDynamicAPI(void); va_end(ap); \ return retval; \ } \ + _static size_t SDLCALL SDL_RWprintf##name(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ + { \ + size_t retval; \ + va_list ap; \ + initcall; \ + va_start(ap, fmt); \ + retval = jump_table.SDL_RWvprintf(context, fmt, ap); \ + va_end(ap); \ + return retval; \ + } \ _static void SDLCALL SDL_Log##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ va_list ap; \ @@ -285,6 +295,16 @@ static int SDLCALL SDL_swprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) wchar_t *buf, va_end(ap); return retval; } +_static size_t SDLCALL SDL_RWprintf_LOGSDLCALLS(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +{ + size_t retval; + va_list ap; + SDL_Log_REAL("SDL3CALL SDL_RWprintf"); + va_start(ap, fmt); + retval = SDL_RWvprintf_REAL(context, fmt, ap); + va_end(ap); + return retval; +} static void SDLCALL SDL_Log_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { va_list ap; diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 75e19c3c1bf1a..fb0a2f38e6b9e 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -922,6 +922,8 @@ SDL3_0.0.0 { SDL_ClearProperty; SDL_EnterAppMainCallbacks; SDL_CleanupEvent; + SDL_RWprintf; + SDL_RWvprintf; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 4cfa591664665..84d0d91f7663c 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -947,3 +947,5 @@ #define SDL_ClearProperty SDL_ClearProperty_REAL #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL #define SDL_CleanupEvent SDL_CleanupEvent_REAL +#define SDL_RWprintf SDL_RWprintf_REAL +#define SDL_RWvprintf SDL_RWvprintf_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d73e3e312af6b..5b9dace0ffdd0 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -43,6 +43,7 @@ SDL_DYNAPI_PROC(int,SDL_asprintf,(char **a, SDL_PRINTF_FORMAT_STRING const char SDL_DYNAPI_PROC(int,SDL_snprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_swprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, SDL_PRINTF_FORMAT_STRING const wchar_t *c, ...),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_sscanf,(const char *a, SDL_SCANF_FORMAT_STRING const char *b, ...),(a,b),return) +SDL_DYNAPI_PROC(size_t,SDL_RWprintf,(SDL_RWops *a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),return) #endif #ifdef SDL_CreateThread @@ -979,3 +980,4 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),ret SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(void,SDL_CleanupEvent,(SDL_Event *a),(a),) +SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return) diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 049cf51206de5..b6f943f1c68cd 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -808,6 +808,35 @@ size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size) return bytes; } +size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +{ + va_list ap; + int size; + char *string = NULL; + size_t bytes; + + va_start(ap, fmt); + size = SDL_vasprintf(&string, fmt, ap); + va_end(ap); + + bytes = SDL_RWwrite(context, string, size); + SDL_free(string); + return bytes; +} + +size_t SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap) +{ + int size; + char *string = NULL; + size_t bytes; + + size = SDL_vasprintf(&string, fmt, ap); + + bytes = SDL_RWwrite(context, string, size); + SDL_free(string); + return bytes; +} + int SDL_RWclose(SDL_RWops *context) { if (!context) { diff --git a/test/testautomation_rwops.c b/test/testautomation_rwops.c index a8cdb903f20f8..59487e36463bf 100644 --- a/test/testautomation_rwops.c +++ b/test/testautomation_rwops.c @@ -110,11 +110,11 @@ static void testGenericRWopsValidations(SDL_RWops *rw, SDL_bool write) SDLTest_AssertPass("Call to SDL_RWseek succeeded"); SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i); - /* Test write. */ + /* Test write */ s = SDL_RWwrite(rw, RWopsHelloWorldTestString, sizeof(RWopsHelloWorldTestString) - 1); SDLTest_AssertPass("Call to SDL_RWwrite succeeded"); if (write) { - SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing one byte with SDL_RWwrite, expected 1, got %i", (int)s); + SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing with SDL_RWwrite, expected %i, got %i", (int)sizeof(RWopsHelloWorldTestString) - 1, (int)s); } else { SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_RWwrite, expected: 0, got %i", (int)s); } @@ -129,6 +129,37 @@ static void testGenericRWopsValidations(SDL_RWops *rw, SDL_bool write) SDLTest_AssertPass("Call to SDL_RWseek succeeded"); SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i); + /* Test read */ + s = SDL_RWread(rw, buf, sizeof(RWopsHelloWorldTestString) - 1); + SDLTest_AssertPass("Call to SDL_RWread succeeded"); + SDLTest_AssertCheck( + s == (sizeof(RWopsHelloWorldTestString) - 1), + "Verify result from SDL_RWread, expected %i, got %i", + (int)(sizeof(RWopsHelloWorldTestString) - 1), + (int)s); + SDLTest_AssertCheck( + SDL_memcmp(buf, RWopsHelloWorldTestString, sizeof(RWopsHelloWorldTestString) - 1) == 0, + "Verify read bytes match expected string, expected '%s', got '%s'", RWopsHelloWorldTestString, buf); + + /* Test seek back to start */ + i = SDL_RWseek(rw, 0, SDL_RW_SEEK_SET); + SDLTest_AssertPass("Call to SDL_RWseek succeeded"); + SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i); + + /* Test printf */ + s = SDL_RWprintf(rw, "%s", RWopsHelloWorldTestString); + SDLTest_AssertPass("Call to SDL_RWprintf succeeded"); + if (write) { + SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing with SDL_RWprintf, expected %i, got %i", (int)sizeof(RWopsHelloWorldTestString) - 1, (int)s); + } else { + SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_RWwrite, expected: 0, got %i", (int)s); + } + + /* Test seek back to start */ + i = SDL_RWseek(rw, 0, SDL_RW_SEEK_SET); + SDLTest_AssertPass("Call to SDL_RWseek succeeded"); + SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i); + /* Test read */ s = SDL_RWread(rw, buf, sizeof(RWopsHelloWorldTestString) - 1); SDLTest_AssertPass("Call to SDL_RWread succeeded"); From ad842dd5ad53eb6d5e9600c560177dd3df063670 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 13:56:31 -0700 Subject: [PATCH 225/725] Fixed a typo in SDL_log.h --- include/SDL3/SDL_log.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h index d56b05909f4d4..d4eb9545fe41c 100644 --- a/include/SDL3/SDL_log.h +++ b/include/SDL3/SDL_log.h @@ -163,8 +163,7 @@ extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void); /** * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO. * - * = * \param fmt a printf() style message format string - * + * \param fmt a printf() style message format string * \param ... additional parameters matching % tokens in the `fmt` string, if * any * From e5f2cea234946cfcb1f4819e9e700583ac375c4e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 4 Nov 2023 22:18:38 -0400 Subject: [PATCH 226/725] Sync wiki -> headers --- include/SDL3/SDL_events.h | 9 ++++----- include/SDL3/SDL_rwops.h | 9 ++++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 2afa92f3e58d7..ef847078aac54 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -911,11 +911,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 t /** * Clean up dynamically allocated memory for an event. * - * Some events have dynamically allocated data that must be cleaned up when the event is processed. If you handle any of these events, you should call SDL_CleanupEvent() after processing them: - * SDL_EVENT_DROP_FILE - * SDL_EVENT_DROP_TEXT - * SDL_EVENT_SYSWM - * SDL_EVENT_TEXT_EDITING + * Some events have dynamically allocated data that must be cleaned up when + * the event is processed. If you handle any of these events, you should call + * SDL_CleanupEvent() after processing them: SDL_EVENT_DROP_FILE + * SDL_EVENT_DROP_TEXT SDL_EVENT_SYSWM SDL_EVENT_TEXT_EDITING * * It is safe, but not necessary, to call this function for other event types. * diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 8ecd75f1d6844..73e655796365c 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -503,8 +503,10 @@ extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, * * \param context a pointer to an SDL_RWops structure * \param fmt a printf() style format string - * \param ... additional parameters matching % tokens in the `fmt` string, if any - * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information. + * \param ... additional parameters matching % tokens in the `fmt` string, if + * any + * \returns the number of bytes written, or 0 on error; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. * @@ -526,7 +528,8 @@ extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMA * \param context a pointer to an SDL_RWops structure * \param fmt a printf() style format string * \param ap a variable argument list - * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information. + * \returns the number of bytes written, or 0 on error; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. * From 2a1660ab51e3d7dc87986e043bd0fdcd4951bf99 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 20:47:08 -0700 Subject: [PATCH 227/725] Additional cleanup for SDL_RWprintf() (thanks @sezero!) --- include/SDL3/SDL_rwops.h | 2 +- src/file/SDL_rwops.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 73e655796365c..88495d1583611 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -518,7 +518,7 @@ extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, * \sa SDL_RWseek * \sa SDL_RWwrite */ -extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...); +extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Print to an SDL_RWops data stream. diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index b6f943f1c68cd..3bfb969b47b60 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -812,14 +812,17 @@ size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt { va_list ap; int size; - char *string = NULL; + char *string; size_t bytes; va_start(ap, fmt); size = SDL_vasprintf(&string, fmt, ap); va_end(ap); + if (size < 0) { + return 0; + } - bytes = SDL_RWwrite(context, string, size); + bytes = SDL_RWwrite(context, string, (size_t)size); SDL_free(string); return bytes; } @@ -827,12 +830,15 @@ size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt size_t SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap) { int size; - char *string = NULL; + char *string; size_t bytes; size = SDL_vasprintf(&string, fmt, ap); + if (size < 0) { + return 0; + } - bytes = SDL_RWwrite(context, string, size); + bytes = SDL_RWwrite(context, string, (size_t)size); SDL_free(string); return bytes; } From 75ea3a8d32dcdc3d8784c12e39719d8d4b403df4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 16:53:25 -0700 Subject: [PATCH 228/725] Dynamically allocate long text for SDL_EVENT_TEXT_INPUT events This prevents input text from being split across Unicode combining or modifier characters, and in practice allocations will rarely happen. --- docs/README-migration.md | 2 +- include/SDL3/SDL_events.h | 3 ++- src/events/SDL_events.c | 10 +++++++++- src/events/SDL_keyboard.c | 18 +++++++++--------- test/checkkeys.c | 1 + test/checkkeysthreads.c | 1 + test/testcontroller.c | 1 + test/testime.c | 1 + 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index bbe1fe56d83f9..26026372a5f81 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -298,7 +298,7 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). -You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, and SDL_EVENT_TEXT_EDITING. This cleans up the memory associated with those events, and you no longer have to free the data yourself. +You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, SDL_EVENT_TEXT_EDITING, and SDL_EVENT_TEXT_INPUT. This cleans up the memory associated with those events, and you no longer have to free the data yourself. Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index ef847078aac54..92be1352ba8bc 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -284,7 +284,8 @@ typedef struct SDL_TextInputEvent Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ + char *text; /**< The input text */ + char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short input text, use 'text' instead */ } SDL_TextInputEvent; /** diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index c6616fe462b81..baac6188b6b70 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -470,11 +470,13 @@ static void SDL_LogEvent(const SDL_Event *event) static void SDL_CopyEvent(SDL_Event *dst, SDL_Event *src) { - *dst = *src; + SDL_copyp(dst, src); /* Pointers to internal static data must be updated when copying. */ if (src->type == SDL_EVENT_TEXT_EDITING && src->edit.text == src->edit.short_text) { dst->edit.text = dst->edit.short_text; + } else if (src->type == SDL_EVENT_TEXT_INPUT && src->text.text == src->text.short_text) { + dst->text.text = dst->text.short_text; } else if (src->type == SDL_EVENT_DROP_TEXT && src->drop.data == src->drop.short_data) { dst->drop.data = dst->drop.short_data; } @@ -1106,6 +1108,12 @@ void SDL_CleanupEvent(SDL_Event *event) event->edit.text = NULL; } break; + case SDL_EVENT_TEXT_INPUT: + if (event->text.text && event->text.text != event->text.short_text) { + SDL_free(event->text.text); + event->text.text = NULL; + } + break; default: break; } diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 49f38b9f490d0..2e69aac027cd4 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1071,19 +1071,19 @@ int SDL_SendKeyboardText(const char *text) posted = 0; if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { SDL_Event event; - size_t pos = 0, advance, length = SDL_strlen(text); - event.type = SDL_EVENT_TEXT_INPUT; event.common.timestamp = 0; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; - while (pos < length) { - advance = SDL_utf8strlcpy(event.text.text, text + pos, SDL_arraysize(event.text.text)); - if (!advance) { - break; - } - pos += advance; - posted |= (SDL_PushEvent(&event) > 0); + + size_t len = SDL_strlen(text); + if (len < sizeof(event.text.short_text)) { + SDL_memcpy(event.text.short_text, text, len + 1); + event.text.text = event.text.short_text; + } else { + event.text.text = SDL_strdup(text); } + + posted = (SDL_PushEvent(&event) > 0); } return posted; } diff --git a/test/checkkeys.c b/test/checkkeys.c index 11fd5b6ced63d..4894f6436874b 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -186,6 +186,7 @@ static void loop(void) case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); SDLTest_TextWindowAddText(textwin, "%s", event.text.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_FINGER_DOWN: if (SDL_TextInputActive()) { diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index 64e0dc418d34c..cae8f48e849c9 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -187,6 +187,7 @@ static void loop(void) break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_MOUSE_BUTTON_DOWN: /* Left button quits the app, other buttons toggles text input */ diff --git a/test/testcontroller.c b/test/testcontroller.c index dd4b9819d95f0..cdcd28ed2fbca 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1728,6 +1728,7 @@ static void loop(void *arg) AddControllerNameText(event.text.text); } } + SDL_CleanupEvent(&event); break; case SDL_EVENT_QUIT: done = SDL_TRUE; diff --git a/test/testime.c b/test/testime.c index 58010bd485e2d..e2353db211719 100644 --- a/test/testime.c +++ b/test/testime.c @@ -770,6 +770,7 @@ int main(int argc, char *argv[]) /* is committed */ markedText[0] = 0; Redraw(); + SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_EDITING: From b9784feb2467dbb4cdc2474aa78098cd4f0b1630 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 21:10:10 -0700 Subject: [PATCH 229/725] Fixed potential uninitialized memory access (thanks Mathieu!) GetRawInputDeviceList() can return a different number of devices than was allocated. Fixes https://github.com/libsdl-org/SDL/issues/2759 --- src/joystick/windows/SDL_rawinputjoystick.c | 3 ++- src/joystick/windows/SDL_windows_gaming_input.c | 3 ++- src/joystick/windows/SDL_xinputjoystick.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 4bdb3cf3a5772..4cc274d8ac3c2 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -991,7 +991,8 @@ static void RAWINPUT_DetectDevices(void) devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count); if (devices) { - if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) { + device_count = GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)); + if (device_count != (UINT)-1) { for (i = 0; i < device_count; ++i) { RAWINPUT_AddDevice(devices[i].hDevice); } diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 675e21537cd59..d939ea6cc5459 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -132,7 +132,8 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) return SDL_FALSE; } - if (GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) { + raw_device_count = GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST)); + if (raw_device_count == (UINT)-1) { SDL_free(raw_devices); raw_devices = NULL; return SDL_FALSE; /* oh well. */ diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index fe45ed61f8685..91ad48590b08b 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -132,7 +132,8 @@ static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 * return; } - if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) { + device_count = GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)); + if (device_count == (UINT)-1) { SDL_free(devices); return; /* oh well. */ } From 3a482ebae062cbc127e4e0faf9a07f69b54b7419 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 21:18:16 -0700 Subject: [PATCH 230/725] Add createSDLMainRunnable() to SDLActivity (thanks Cole!) This patch adds a new createSDLMainRunnable() method to SDLActivity. Currently, SDL on Android expects to find SDL_main somewhere in native code. When using SDL in a Xamarin application, however, what we really want to do is write our entrypoint in managed code. The easiest way to do this is to allow subclasses of SDLActivity to provide their own Runnable to the SDL thread, as in the attached patch. Fixes https://github.com/libsdl-org/SDL/issues/2785 --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index a80b4941fb9d9..41497a71e68e0 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -238,6 +238,15 @@ protected static SDLGenericMotionListener_API12 getMotionListener() { return mMotionListener; } + /** + * This method creates a Runnable which invokes SDL_main. The default implementation + * uses the getMainSharedObject() and getMainFunction() methods to invoke native + * code from the specified shared library. + */ + protected Runnable createSDLMainRunnable() { + return new SDLMain(); + } + /** * This method returns the name of the shared object with the application entry point * It can be overridden by derived classes. @@ -783,7 +792,7 @@ public static void handleNativeState() { // Start up the C app thread and enable sensor input for the first time // FIXME: Why aren't we enabling sensor input at start? - mSDLThread = new Thread(new SDLMain(), "SDLThread"); + mSDLThread = new Thread(SDLActivity.mSingleton.createSDLMainRunnable(), "SDLThread"); mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true); mSDLThread.start(); From d3f2eb2aba7d7a072e3ef475f2da864f1ee1c0c7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 22:24:55 -0700 Subject: [PATCH 231/725] Use XINPUT_STATE instead of XINPUT_STATE_EX (thanks Andrew!) XINPUT_STATE_EX isn't actually a thing, we can just use the normal XINPUT_STATE Fixes https://github.com/libsdl-org/SDL/issues/2797 (cherry picked from commit e8f4045d0bccacbf8f4b716d0dde17140e9f2cc4) --- CMakeLists.txt | 10 ------- include/build_config/SDL_build_config.h.cmake | 3 -- src/core/windows/SDL_xinput.h | 30 +++++-------------- src/joystick/windows/SDL_rawinputjoystick.c | 2 +- src/joystick/windows/SDL_xinputjoystick.c | 6 ++-- 5 files changed, 12 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2962ed177dd31..6d07d9ade658b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1806,16 +1806,6 @@ elseif(WINDOWS) #include #include int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_H) - check_c_source_compiles(" - #include - #include - XINPUT_GAMEPAD_EX x1; - int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_GAMEPAD_EX) - check_c_source_compiles(" - #include - #include - XINPUT_STATE_EX s1; - int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_STATE_EX) check_c_source_compiles(" #define COBJMACROS #include diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 35b5e58579f45..32f6486af295a 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -242,9 +242,6 @@ #cmakedefine HAVE_ROAPI_H @HAVE_ROAPI_H@ #cmakedefine HAVE_SHELLSCALINGAPI_H @HAVE_SHELLSCALINGAPI_H@ -#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@ -#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@ - #cmakedefine USE_POSIX_SPAWN @USE_POSIX_SPAWN@ /* SDL internal assertion support */ diff --git a/src/core/windows/SDL_xinput.h b/src/core/windows/SDL_xinput.h index 1d59a8796d05f..a92cb8b8cb8ff 100644 --- a/src/core/windows/SDL_xinput.h +++ b/src/core/windows/SDL_xinput.h @@ -163,28 +163,8 @@ extern "C" { /* typedef's for XInput structs we use */ -#ifndef HAVE_XINPUT_GAMEPAD_EX -typedef struct -{ - WORD wButtons; - BYTE bLeftTrigger; - BYTE bRightTrigger; - SHORT sThumbLX; - SHORT sThumbLY; - SHORT sThumbRX; - SHORT sThumbRY; - DWORD dwPaddingReserved; -} XINPUT_GAMEPAD_EX; -#endif - -#ifndef HAVE_XINPUT_STATE_EX -typedef struct -{ - DWORD dwPacketNumber; - XINPUT_GAMEPAD_EX Gamepad; -} XINPUT_STATE_EX; -#endif +/* This is the same as XINPUT_BATTERY_INFORMATION, but always defined instead of just if WIN32_WINNT >= _WIN32_WINNT_WIN8 */ typedef struct { BYTE BatteryType; @@ -204,6 +184,12 @@ typedef struct SHORT sThumbRY; } XINPUT_GAMEPAD; +typedef struct +{ + DWORD dwPacketNumber; + XINPUT_GAMEPAD Gamepad; +} XINPUT_STATE; + typedef struct { WORD wLeftMotorSpeed; @@ -224,7 +210,7 @@ typedef struct /* Forward decl's for XInput API's we load dynamically and use if available */ typedef DWORD(WINAPI *XInputGetState_t)( DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ - XINPUT_STATE_EX *pState /* [out] Receives the current state */ + XINPUT_STATE *pState /* [out] Receives the current state */ ); typedef DWORD(WINAPI *XInputSetState_t)( diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 4cc274d8ac3c2..2d8d1aa860c8a 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -316,7 +316,7 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint64 match_state static struct { - XINPUT_STATE_EX state; + XINPUT_STATE state; XINPUT_BATTERY_INFORMATION_EX battery; SDL_bool connected; /* Currently has an active XInput device */ SDL_bool used; /* Is currently mapped to an SDL device */ diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 91ad48590b08b..b5369bb616cd8 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -421,7 +421,7 @@ static void UpdateXInputJoystickBatteryInformation(SDL_Joystick *joystick, XINPU } } -static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) +static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) { static WORD s_XInputButtons[] = { XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT, @@ -448,7 +448,7 @@ static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE_E UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation); } -static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) +static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) { static WORD s_XInputButtons[] = { XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y, @@ -513,7 +513,7 @@ Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick) { HRESULT result; - XINPUT_STATE_EX XInputState; + XINPUT_STATE XInputState; XINPUT_BATTERY_INFORMATION_EX XBatteryInformation; if (!XINPUTGETSTATE) { From 5dce4bc7166c1e0295665f6acda9f74736d72097 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Nov 2023 23:22:55 -0700 Subject: [PATCH 232/725] Makes SDLInputConnection and DummyEdit public classes (thanks Cole!) I've added an additional patch that expands on the same basic idea as the first one; it makes SDLInputConnection and DummyEdit into public classes so that they can be overridden from the Xamarin end if their functionality needs to be extended. (In my case, I need to change the type of software keyboard that's displayed.) Fixes https://github.com/libsdl-org/SDL/issues/2785 --- .../main/java/org/libsdl/app/SDLActivity.java | 190 +----------------- .../java/org/libsdl/app/SDLDummyEdit.java | 62 ++++++ .../org/libsdl/app/SDLInputConnection.java | 136 +++++++++++++ 3 files changed, 200 insertions(+), 188 deletions(-) create mode 100644 android-project/app/src/main/java/org/libsdl/app/SDLDummyEdit.java create mode 100644 android-project/app/src/main/java/org/libsdl/app/SDLInputConnection.java diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 41497a71e68e0..82ba742a429c2 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -23,9 +23,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.text.Editable; -import android.text.InputType; -import android.text.Selection; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; @@ -39,12 +36,9 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; -import android.view.inputmethod.BaseInputConnection; -import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.Button; -import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; @@ -210,7 +204,7 @@ public enum NativeState { // Main components protected static SDLActivity mSingleton; protected static SDLSurface mSurface; - protected static DummyEdit mTextEdit; + protected static SDLDummyEdit mTextEdit; protected static boolean mScreenKeyboardShown; protected static ViewGroup mLayout; protected static SDLClipboardHandler mClipboardHandler; @@ -1353,7 +1347,7 @@ public void run() { params.topMargin = y; if (mTextEdit == null) { - mTextEdit = new DummyEdit(SDL.getContext()); + mTextEdit = new SDLDummyEdit(SDL.getContext()); mLayout.addView(mTextEdit, params); } else { @@ -1975,186 +1969,6 @@ public void run() { } } -/* This is a fake invisible editor view that receives the input and defines the - * pan&scan region - */ -class DummyEdit extends View implements View.OnKeyListener { - InputConnection ic; - - public DummyEdit(Context context) { - super(context); - setFocusableInTouchMode(true); - setFocusable(true); - setOnKeyListener(this); - } - - @Override - public boolean onCheckIsTextEditor() { - return true; - } - - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - return SDLActivity.handleKeyEvent(v, keyCode, event, ic); - } - - // - @Override - public boolean onKeyPreIme (int keyCode, KeyEvent event) { - // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event - // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639 - // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not - // FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout - // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android - // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :) - if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { - if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) { - SDLActivity.onNativeKeyboardFocusLost(); - } - } - return super.onKeyPreIme(keyCode, event); - } - - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - ic = new SDLInputConnection(this, true); - - outAttrs.inputType = InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_FLAG_MULTI_LINE; - outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | - EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */; - - return ic; - } -} - -class SDLInputConnection extends BaseInputConnection { - - protected EditText mEditText; - protected String mCommittedText = ""; - - public SDLInputConnection(View targetView, boolean fullEditor) { - super(targetView, fullEditor); - mEditText = new EditText(SDL.getContext()); - } - - @Override - public Editable getEditable() { - return mEditText.getEditableText(); - } - - @Override - public boolean sendKeyEvent(KeyEvent event) { - /* - * This used to handle the keycodes from soft keyboard (and IME-translated input from hardkeyboard) - * However, as of Ice Cream Sandwich and later, almost all soft keyboard doesn't generate key presses - * and so we need to generate them ourselves in commitText. To avoid duplicates on the handful of keys - * that still do, we empty this out. - */ - - /* - * Return DOES still generate a key event, however. So rather than using it as the 'click a button' key - * as we do with physical keyboards, let's just use it to hide the keyboard. - */ - - if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { - if (SDLActivity.onNativeSoftReturnKey()) { - return true; - } - } - - return super.sendKeyEvent(event); - } - - @Override - public boolean commitText(CharSequence text, int newCursorPosition) { - if (!super.commitText(text, newCursorPosition)) { - return false; - } - updateText(); - return true; - } - - @Override - public boolean setComposingText(CharSequence text, int newCursorPosition) { - if (!super.setComposingText(text, newCursorPosition)) { - return false; - } - updateText(); - return true; - } - - @Override - public boolean deleteSurroundingText(int beforeLength, int afterLength) { - if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) { - // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection - // and https://bugzilla.libsdl.org/show_bug.cgi?id=2265 - if (beforeLength > 0 && afterLength == 0) { - // backspace(s) - while (beforeLength-- > 0) { - nativeGenerateScancodeForUnichar('\b'); - } - return true; - } - } - - if (!super.deleteSurroundingText(beforeLength, afterLength)) { - return false; - } - updateText(); - return true; - } - - protected void updateText() { - final Editable content = getEditable(); - if (content == null) { - return; - } - - String text = content.toString(); - int compareLength = Math.min(text.length(), mCommittedText.length()); - int matchLength, offset; - - /* Backspace over characters that are no longer in the string */ - for (matchLength = 0; matchLength < compareLength; ) { - int codePoint = mCommittedText.codePointAt(matchLength); - if (codePoint != text.codePointAt(matchLength)) { - break; - } - matchLength += Character.charCount(codePoint); - } - /* FIXME: This doesn't handle graphemes, like '🌬️' */ - for (offset = matchLength; offset < mCommittedText.length(); ) { - int codePoint = mCommittedText.codePointAt(offset); - nativeGenerateScancodeForUnichar('\b'); - offset += Character.charCount(codePoint); - } - - if (matchLength < text.length()) { - String pendingText = text.subSequence(matchLength, text.length()).toString(); - for (offset = 0; offset < pendingText.length(); ) { - int codePoint = pendingText.codePointAt(offset); - if (codePoint == '\n') { - if (SDLActivity.onNativeSoftReturnKey()) { - return; - } - } - /* Higher code points don't generate simulated scancodes */ - if (codePoint < 128) { - nativeGenerateScancodeForUnichar((char)codePoint); - } - offset += Character.charCount(codePoint); - } - SDLInputConnection.nativeCommitText(pendingText, 0); - } - mCommittedText = text; - } - - public static native void nativeCommitText(String text, int newCursorPosition); - - public static native void nativeGenerateScancodeForUnichar(char c); -} - class SDLClipboardHandler implements ClipboardManager.OnPrimaryClipChangedListener { diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLDummyEdit.java b/android-project/app/src/main/java/org/libsdl/app/SDLDummyEdit.java new file mode 100644 index 0000000000000..dca28145ec19c --- /dev/null +++ b/android-project/app/src/main/java/org/libsdl/app/SDLDummyEdit.java @@ -0,0 +1,62 @@ +package org.libsdl.app; + +import android.content.*; +import android.text.InputType; +import android.view.*; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; + +/* This is a fake invisible editor view that receives the input and defines the + * pan&scan region + */ +public class SDLDummyEdit extends View implements View.OnKeyListener +{ + InputConnection ic; + + public SDLDummyEdit(Context context) { + super(context); + setFocusableInTouchMode(true); + setFocusable(true); + setOnKeyListener(this); + } + + @Override + public boolean onCheckIsTextEditor() { + return true; + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + return SDLActivity.handleKeyEvent(v, keyCode, event, ic); + } + + // + @Override + public boolean onKeyPreIme (int keyCode, KeyEvent event) { + // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event + // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639 + // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not + // FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout + // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android + // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :) + if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) { + SDLActivity.onNativeKeyboardFocusLost(); + } + } + return super.onKeyPreIme(keyCode, event); + } + + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + ic = new SDLInputConnection(this, true); + + outAttrs.inputType = InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_FLAG_MULTI_LINE; + outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | + EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */; + + return ic; + } +} + diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLInputConnection.java b/android-project/app/src/main/java/org/libsdl/app/SDLInputConnection.java new file mode 100644 index 0000000000000..e1d29a8890e2d --- /dev/null +++ b/android-project/app/src/main/java/org/libsdl/app/SDLInputConnection.java @@ -0,0 +1,136 @@ +package org.libsdl.app; + +import android.content.*; +import android.os.Build; +import android.text.Editable; +import android.view.*; +import android.view.inputmethod.BaseInputConnection; +import android.widget.EditText; + +public class SDLInputConnection extends BaseInputConnection +{ + protected EditText mEditText; + protected String mCommittedText = ""; + + public SDLInputConnection(View targetView, boolean fullEditor) { + super(targetView, fullEditor); + mEditText = new EditText(SDL.getContext()); + } + + @Override + public Editable getEditable() { + return mEditText.getEditableText(); + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + /* + * This used to handle the keycodes from soft keyboard (and IME-translated input from hardkeyboard) + * However, as of Ice Cream Sandwich and later, almost all soft keyboard doesn't generate key presses + * and so we need to generate them ourselves in commitText. To avoid duplicates on the handful of keys + * that still do, we empty this out. + */ + + /* + * Return DOES still generate a key event, however. So rather than using it as the 'click a button' key + * as we do with physical keyboards, let's just use it to hide the keyboard. + */ + + if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { + if (SDLActivity.onNativeSoftReturnKey()) { + return true; + } + } + + return super.sendKeyEvent(event); + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (!super.commitText(text, newCursorPosition)) { + return false; + } + updateText(); + return true; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + if (!super.setComposingText(text, newCursorPosition)) { + return false; + } + updateText(); + return true; + } + + @Override + public boolean deleteSurroundingText(int beforeLength, int afterLength) { + if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) { + // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection + // and https://bugzilla.libsdl.org/show_bug.cgi?id=2265 + if (beforeLength > 0 && afterLength == 0) { + // backspace(s) + while (beforeLength-- > 0) { + nativeGenerateScancodeForUnichar('\b'); + } + return true; + } + } + + if (!super.deleteSurroundingText(beforeLength, afterLength)) { + return false; + } + updateText(); + return true; + } + + protected void updateText() { + final Editable content = getEditable(); + if (content == null) { + return; + } + + String text = content.toString(); + int compareLength = Math.min(text.length(), mCommittedText.length()); + int matchLength, offset; + + /* Backspace over characters that are no longer in the string */ + for (matchLength = 0; matchLength < compareLength; ) { + int codePoint = mCommittedText.codePointAt(matchLength); + if (codePoint != text.codePointAt(matchLength)) { + break; + } + matchLength += Character.charCount(codePoint); + } + /* FIXME: This doesn't handle graphemes, like '🌬️' */ + for (offset = matchLength; offset < mCommittedText.length(); ) { + int codePoint = mCommittedText.codePointAt(offset); + nativeGenerateScancodeForUnichar('\b'); + offset += Character.charCount(codePoint); + } + + if (matchLength < text.length()) { + String pendingText = text.subSequence(matchLength, text.length()).toString(); + for (offset = 0; offset < pendingText.length(); ) { + int codePoint = pendingText.codePointAt(offset); + if (codePoint == '\n') { + if (SDLActivity.onNativeSoftReturnKey()) { + return; + } + } + /* Higher code points don't generate simulated scancodes */ + if (codePoint < 128) { + nativeGenerateScancodeForUnichar((char)codePoint); + } + offset += Character.charCount(codePoint); + } + SDLInputConnection.nativeCommitText(pendingText, 0); + } + mCommittedText = text; + } + + public static native void nativeCommitText(String text, int newCursorPosition); + + public static native void nativeGenerateScancodeForUnichar(char c); +} + From 4ab31ca6784a49f87afe7b189ab39a2e7230c58f Mon Sep 17 00:00:00 2001 From: kanjitalk755 Date: Sun, 5 Nov 2023 15:21:17 +0900 Subject: [PATCH 233/725] Fix dropping file event --- src/events/SDL_events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index baac6188b6b70..ce9e6de5fcda7 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -477,7 +477,7 @@ static void SDL_CopyEvent(SDL_Event *dst, SDL_Event *src) dst->edit.text = dst->edit.short_text; } else if (src->type == SDL_EVENT_TEXT_INPUT && src->text.text == src->text.short_text) { dst->text.text = dst->text.short_text; - } else if (src->type == SDL_EVENT_DROP_TEXT && src->drop.data == src->drop.short_data) { + } else if ((src->type == SDL_EVENT_DROP_FILE || src->type == SDL_EVENT_DROP_TEXT) && src->drop.data == src->drop.short_data) { dst->drop.data = dst->drop.short_data; } } From 2b62f25a6fc623d0704af91007963bc9466cff0b Mon Sep 17 00:00:00 2001 From: kanjitalk755 Date: Sun, 5 Nov 2023 14:50:14 +0900 Subject: [PATCH 234/725] Add SDL_sysmain_callbacks.c to the Xcode project --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index bd32ee428903b..be5ba5ac43c4f 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */; }; 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; 007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; platformFilters = (macos, ); }; @@ -368,6 +369,7 @@ A7D8BBE923E2574800DCD162 /* SDL_uikitvulkan.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A62523E2513D00DCD162 /* SDL_uikitvulkan.m */; }; A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A62723E2513D00DCD162 /* SDL_uikitwindow.h */; }; A7D8BBEB23E2574800DCD162 /* SDL_uikitwindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A61A23E2513D00DCD162 /* SDL_uikitwindow.m */; }; + E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */; }; E4F7981A2AD8D84800669F54 /* SDL_core_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */; }; E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */; }; E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */; }; @@ -477,8 +479,6 @@ F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E72933074E00816151 /* SDL_begin_code.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E52933074E00816151 /* SDL_system.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E82933074E00816151 /* SDL_system.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; - 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */; }; - 0000C3B22D46279F99170000 /* SDL_main_callbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 00003260407E1002EAC10000 /* SDL_main_callbacks.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -505,7 +505,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 00003260407E1002EAC10000 /* SDL_main_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_main_callbacks.h; sourceTree = ""; }; 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hashtable.c; sourceTree = ""; }; + 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_main_callbacks.c; sourceTree = ""; }; 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hashtable.h; sourceTree = ""; }; 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_sysmain_callbacks.m; sourceTree = ""; }; 0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; @@ -855,6 +857,7 @@ BECDF66B0761BA81005FE872 /* Info-Framework.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = ""; }; BECDF66C0761BA81005FE872 /* SDL3.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL3.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2D187D228A5673500D2B4F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysmain_callbacks.c; sourceTree = ""; }; E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_core_unsupported.c; sourceTree = ""; }; E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_unsupported.h; sourceTree = ""; }; E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_unsupported.c; sourceTree = ""; }; @@ -981,8 +984,6 @@ F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; }; F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; }; FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; - 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_main_callbacks.c; path = SDL_main_callbacks.c; sourceTree = ""; }; - 00003260407E1002EAC10000 /* SDL_main_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_main_callbacks.h; path = SDL_main_callbacks.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1011,6 +1012,7 @@ 000082EF09C89B62BD840000 /* main */ = { isa = PBXGroup; children = ( + E4A568B42AF763940062EEC4 /* generic */, 00008B5A0CB83D2069E80000 /* ios */, 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */, 00003260407E1002EAC10000 /* SDL_main_callbacks.h */, @@ -2047,6 +2049,14 @@ path = SDL3; sourceTree = ""; }; + E4A568B42AF763940062EEC4 /* generic */ = { + isa = PBXGroup; + children = ( + E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */, + ); + path = generic; + sourceTree = ""; + }; F36C7ACF294B9F5E004D61C3 /* core */ = { isa = PBXGroup; children = ( @@ -2487,6 +2497,7 @@ F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */, A7D8B9DD23E2514400DCD162 /* SDL_blendpoint.c in Sources */, A7D8B4EE23E2514300DCD162 /* SDL_gamepad.c in Sources */, + E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */, A7D8AB3723E2514100DCD162 /* SDL_systimer.c in Sources */, A7D8BA1323E2514400DCD162 /* SDL_render_sw.c in Sources */, A7D8B42223E2514300DCD162 /* SDL_syssem.c in Sources */, From c56583fe45ecc71a4acd4a67f3eb44dea61e076b Mon Sep 17 00:00:00 2001 From: kanjitalk755 Date: Sun, 5 Nov 2023 15:57:15 +0900 Subject: [PATCH 235/725] Fix duplicate symbol on iOS/tvOS --- src/main/generic/SDL_sysmain_callbacks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index 9a0bab3e6e1e8..d8742efca50cf 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -23,6 +23,8 @@ #include "../SDL_main_callbacks.h" #include "../../video/SDL_sysvideo.h" +#ifndef __IOS__ + static int callback_rate_increment = 0; static void SDLCALL MainCallbackRateHintChanged(void *userdata, const char *name, const char *oldValue, const char *newValue) @@ -78,3 +80,4 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, return (rc < 0) ? 1 : 0; } +#endif From 930438dfb7408a6104325cdf4d6796f26acb06a4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 00:33:08 -0700 Subject: [PATCH 236/725] Added note that the #ifdef is for !__IOS__ --- src/main/generic/SDL_sysmain_callbacks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index d8742efca50cf..1fcb7d767f8f3 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -80,4 +80,4 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, return (rc < 0) ? 1 : 0; } -#endif +#endif // !__IOS__ From 2ad22eeeb5f415d0d4a1789a622e1d6444811e58 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sun, 5 Nov 2023 14:02:06 +0000 Subject: [PATCH 237/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 598560f7ee908..996be41857ea9 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -64,7 +64,7 @@ they always have. If you have never controlled your process's entry point (you are using SDL as a module from a general-purpose scripting language interpreter, or you're -SDL in a plugin for some otherwise-unrelated app), then there is nothing +using SDL in a plugin for some otherwise-unrelated app), then there is nothing required of you here; there is no startup code in SDL's entry point code that is required, so using SDL_main.h is completely optional. Just start using the SDL API when you are ready. From 14d2471a8f5d4ed9e2204db39f8c4f0025012b37 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sun, 5 Nov 2023 14:04:05 +0000 Subject: [PATCH 238/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 996be41857ea9..b3de1e1e528df 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -99,7 +99,7 @@ Video targets like Wayland can notify the app when to draw a new frame, to save battery life and cooperate with the compositor more closely. In most cases, you can add special-case code to your program to deal with this -on different platforms, but SDL3 offers a system to handle transparently on +on different platforms, but SDL3 offers a system to handle this transparently on the app's behalf. To use this, you have to redesign the highest level of your app a little. Once From 17a0fe3a0c1cf1972ef427d5cbdc8cacb9a51829 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sun, 5 Nov 2023 14:06:05 +0000 Subject: [PATCH 239/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index b3de1e1e528df..d0d267e94eaf7 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -122,7 +122,7 @@ find you enjoy structuring your program like this more! ## How to use main callbacks in SDL3 -To enable the callback entry points, you include SDL_main with an extra define +To enable the callback entry points, you include SDL_main.h with an extra define, from a single source file in your project: ```c @@ -130,7 +130,7 @@ from a single source file in your project: #include ``` -Once you do this, you do not include a "main" function at all (and if you do, +Once you do this, you do not write a "main" function at all (and if you do, the app will likely fail to link). Instead, you provide the following functions: From ff3c20a799f0ddd49d65330461d2a8f3976b30d4 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sun, 5 Nov 2023 14:11:05 +0000 Subject: [PATCH 240/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index d0d267e94eaf7..a4811a3183d50 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -175,10 +175,10 @@ int SDL_AppEvent(const SDL_Event *event); ``` This will be called whenever an SDL event arrives, on the thread that runs -SDL_AppIterate. You don't need to call SDL_CleanupEvent(), and your app -should not call SDL_PollEvent, SDL_PumpEvent, etc, as SDL will manage this -for you. Return values are the same as from SDL_AppIterate(), so you can -terminate in response to SDL_EVENT_QUIT, etc. +SDL_AppIterate. You should not call SDL_CleanupEvent() on the provided +event, and your app should also not call SDL_PollEvent, SDL_PumpEvent, etc, +as SDL will manage all this for you. Return values are the same as from +SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. Finally: From 9302d7732dfbb3c6364da142efd06ea9846206c1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 00:03:23 -0700 Subject: [PATCH 241/725] Fixed touch normalized coordinates When converting normalized coordinates to pixel coordinates, the valid range is 0 to (width or height) - 1, and the pixel coordinate of width or height is past the edge of the window. Fixes https://github.com/libsdl-org/SDL/issues/2913 --- .../main/java/org/libsdl/app/SDLSurface.java | 30 +++++++++++++++---- src/video/emscripten/SDL_emscriptenevents.c | 12 ++++++-- src/video/n3ds/SDL_n3dstouch.c | 4 +-- src/video/vita/SDL_vitatouch.c | 14 +++++++-- src/video/wayland/SDL_waylandevents.c | 14 +++++++-- src/video/windows/SDL_windowsevents.c | 14 +++++++-- 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java index c4c14491455c8..fb98f1b624fa6 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java @@ -196,6 +196,24 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { return SDLActivity.handleKeyEvent(v, keyCode, event, null); } + private float getNormalizedX(float x) + { + if (mWidth <= 1) { + return 0.5f; + } else { + return (x / (mWidth - 1)); + } + } + + private float getNormalizedY(float y) + { + if (mHeight <= 1) { + return 0.5f; + } else { + return (y / (mHeight - 1)); + } + } + // Touch events @Override public boolean onTouch(View v, MotionEvent event) { @@ -242,8 +260,8 @@ public boolean onTouch(View v, MotionEvent event) { case MotionEvent.ACTION_MOVE: for (i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); - x = event.getX(i) / mWidth; - y = event.getY(i) / mHeight; + x = getNormalizedX(event.getX(i)); + y = getNormalizedY(event.getY(i)); p = event.getPressure(i); if (p > 1.0f) { // may be larger than 1.0f on some devices @@ -267,8 +285,8 @@ public boolean onTouch(View v, MotionEvent event) { } pointerFingerId = event.getPointerId(i); - x = event.getX(i) / mWidth; - y = event.getY(i) / mHeight; + x = getNormalizedX(event.getX(i)); + y = getNormalizedY(event.getY(i)); p = event.getPressure(i); if (p > 1.0f) { // may be larger than 1.0f on some devices @@ -281,8 +299,8 @@ public boolean onTouch(View v, MotionEvent event) { case MotionEvent.ACTION_CANCEL: for (i = 0; i < pointerCount; i++) { pointerFingerId = event.getPointerId(i); - x = event.getX(i) / mWidth; - y = event.getY(i) / mHeight; + x = getNormalizedX(event.getX(i)); + y = getNormalizedY(event.getY(i)); p = event.getPressure(i); if (p > 1.0f) { // may be larger than 1.0f on some devices diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index e862bbc897788..e25dff184d51c 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -759,8 +759,16 @@ static EM_BOOL Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent } id = touchEvent->touches[i].identifier; - x = touchEvent->touches[i].targetX / client_w; - y = touchEvent->touches[i].targetY / client_h; + if (client_w <= 1) { + x = 0.5f; + } else { + x = touchEvent->touches[i].targetX / (client_w - 1); + } + if (client_h <= 1) { + y = 0.5f; + } else { + y = touchEvent->touches[i].targetY / (client_h - 1); + } if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) { SDL_SendTouch(0, deviceId, id, window_data->window, SDL_TRUE, x, y, 1.0f); diff --git a/src/video/n3ds/SDL_n3dstouch.c b/src/video/n3ds/SDL_n3dstouch.c index 1bc42578ee480..c0e5c07c23484 100644 --- a/src/video/n3ds/SDL_n3dstouch.c +++ b/src/video/n3ds/SDL_n3dstouch.c @@ -36,8 +36,8 @@ internally in a portrait disposition so the GSP_SCREEN constants are flipped. */ -#define TOUCHSCREEN_SCALE_X 1.0f / GSP_SCREEN_HEIGHT_BOTTOM -#define TOUCHSCREEN_SCALE_Y 1.0f / GSP_SCREEN_WIDTH +#define TOUCHSCREEN_SCALE_X 1.0f / (GSP_SCREEN_HEIGHT_BOTTOM - 1) +#define TOUCHSCREEN_SCALE_Y 1.0f / (GSP_SCREEN_WIDTH - 1) void N3DS_InitTouch(void) { diff --git a/src/video/vita/SDL_vitatouch.c b/src/video/vita/SDL_vitatouch.c index bdc041a3a2ac9..cef1ffc9cf768 100644 --- a/src/video/vita/SDL_vitatouch.c +++ b/src/video/vita/SDL_vitatouch.c @@ -173,8 +173,18 @@ void VITA_PollTouch(void) void VITA_ConvertTouchXYToSDLXY(float *sdl_x, float *sdl_y, int vita_x, int vita_y, int port) { - float x = (vita_x - area_info[port].x) / area_info[port].w; - float y = (vita_y - area_info[port].y) / area_info[port].h; + float x, y; + + if (area_info[port].w <= 1) { + x = 0.5f; + } else { + x = (vita_x - area_info[port].x) / (area_info[port].w - 1); + } + if (area_info[port].h <= 1) { + y = 0.5f; + } else { + y = (vita_y - area_info[port].y) / (area_info[port].h - 1); + } x = SDL_max(x, 0.0); x = SDL_min(x, 1.0); diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 2e9583cc7b76f..e5b0e0a833bc6 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -953,8 +953,18 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri window_data = (SDL_WindowData *)wl_surface_get_user_data(surface); if (window_data) { - const float x = wl_fixed_to_double(fx) / window_data->wl_window_width; - const float y = wl_fixed_to_double(fy) / window_data->wl_window_height; + float x, y; + + if (window_data->wl_window_width <= 1) { + x = 0.5f; + } else { + x = wl_fixed_to_double(fx) / (window_data->wl_window_width - 1); + } + if (window_data->wl_window_height <= 1) { + y = 0.5f; + } else { + y = wl_fixed_to_double(fy) / (window_data->wl_window_height - 1); + } SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f); diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 042667c84b44d..41d94182225f5 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1419,6 +1419,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) for (i = 0; i < num_inputs; ++i) { PTOUCHINPUT input = &inputs[i]; + const int w = (rect.right - rect.left); + const int h = (rect.right - rect.left); const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource); @@ -1430,8 +1432,16 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } /* Get the normalized coordinates for the window */ - x = (float)(input->x - rect.left) / (rect.right - rect.left); - y = (float)(input->y - rect.top) / (rect.bottom - rect.top); + if (w <= 1) { + x = 0.5f; + } else { + x = (float)(input->x - rect.left) / (w - 1); + } + if (h <= 1) { + y = 0.5f; + } else { + y = (float)(input->y - rect.top) / (h - 1); + } /* FIXME: Should we use the input->dwTime field for the tick source of the timestamp? */ if (input->dwFlags & TOUCHEVENTF_DOWN) { From 59b37d0e5b449adf5adbdf65ba7067de505db330 Mon Sep 17 00:00:00 2001 From: Jamie Madill Date: Sun, 5 Nov 2023 11:28:22 -0500 Subject: [PATCH 242/725] cmake: fix Windows unrecognized option link warning This fixes a warning that could show up on some MS linkers which use a slightly different warning message than expected. Amends check_linker_supports_version_file to include the "unrecognized option" warning message. --- cmake/macros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros.cmake b/cmake/macros.cmake index de9680047bc95..fa9690f85af6d 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -86,7 +86,7 @@ function(check_linker_supports_version_file VAR) cmake_push_check_state() file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n") list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym") - check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error)") + check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)") cmake_pop_check_state() set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE) endfunction() From 1a83bf2399c29f3028477225067bf6a106068f08 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Sun, 5 Nov 2023 20:01:02 +0300 Subject: [PATCH 243/725] fix a possible memory leak in SDL_vasprintf() --- src/stdlib/SDL_string.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 0c97cc0248f8a..9f434a46cbe03 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -2201,6 +2201,7 @@ int SDL_vasprintf(char **strp, const char *fmt, va_list ap) /* Check error code */ if (retval < 0) { + SDL_free(p); return retval; } From 70c149c88f05e469f07b7e5fff58b7e16e4d1bea Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 08:48:37 -0800 Subject: [PATCH 244/725] Automatically clean up memory associated with events --- docs/README-main-functions.md | 5 +- docs/README-migration.md | 4 +- include/SDL3/SDL_events.h | 86 +++++++---------- src/dynapi/SDL_dynapi.sym | 2 +- src/dynapi/SDL_dynapi_overrides.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 2 +- src/events/SDL_dropevents.c | 11 +-- src/events/SDL_events.c | 154 +++++++++++++++++++----------- src/events/SDL_keyboard.c | 22 ++--- src/main/SDL_main_callbacks.c | 1 - src/test/SDL_test_common.c | 2 - test/checkkeys.c | 2 - test/checkkeysthreads.c | 2 - test/testcontroller.c | 1 - test/testdropfile.c | 2 - test/testime.c | 2 - 16 files changed, 152 insertions(+), 148 deletions(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index a4811a3183d50..072bf826d5694 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -175,9 +175,8 @@ int SDL_AppEvent(const SDL_Event *event); ``` This will be called whenever an SDL event arrives, on the thread that runs -SDL_AppIterate. You should not call SDL_CleanupEvent() on the provided -event, and your app should also not call SDL_PollEvent, SDL_PumpEvent, etc, -as SDL will manage all this for you. Return values are the same as from +SDL_AppIterate. Your app should also not call SDL_PollEvent, SDL_PumpEvent, +etc, as SDL will manage all this for you. Return values are the same as from SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. diff --git a/docs/README-migration.md b/docs/README-migration.md index 26026372a5f81..acddcf00b7499 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -298,7 +298,7 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). -You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, SDL_EVENT_TEXT_EDITING, and SDL_EVENT_TEXT_INPUT. This cleans up the memory associated with those events, and you no longer have to free the data yourself. +You should not call SDL_free() on the data in SDL_EVENT_DROP_FILE, SDL manages the memory for events internally, you no longer have to free the data yourself. Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. @@ -559,7 +559,7 @@ The following hints have been removed: * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend -* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has dynamically allocated text if needed, and should be freed with SDL_CleanupEvent() when processed +* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 92be1352ba8bc..6aa8b9aeb510b 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -236,7 +236,7 @@ typedef struct SDL_WindowEvent { Uint32 type; /**< ::SDL_WINDOWEVENT_* */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The associated window */ + SDL_WindowID windowID; /**< The associated window */ Sint32 data1; /**< event dependent data */ Sint32 data2; /**< event dependent data */ } SDL_WindowEvent; @@ -248,7 +248,7 @@ typedef struct SDL_KeyboardEvent { Uint32 type; /**< ::SDL_EVENT_KEY_DOWN or ::SDL_EVENT_KEY_UP */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The window with keyboard focus, if any */ + SDL_WindowID windowID; /**< The window with keyboard focus, if any */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 repeat; /**< Non-zero if this is a key repeat */ Uint8 padding2; @@ -259,33 +259,27 @@ typedef struct SDL_KeyboardEvent #define SDL_TEXTEDITINGEVENT_TEXT_SIZE 64 /** * \brief Keyboard text editing event structure (event.edit.*) - * - * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextEditingEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char *text; /**< The editing text */ - char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short editing text, use 'text' instead */ - Sint32 start; /**< The start cursor of selected editing text */ - Sint32 length; /**< The length of selected editing text */ + Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_WindowID windowID; /**< The window with keyboard focus, if any */ + char *text; /**< The editing text */ + Sint32 start; /**< The start cursor of selected editing text */ + Sint32 length; /**< The length of selected editing text */ } SDL_TextEditingEvent; #define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** * \brief Keyboard text input event structure (event.text.*) - * - * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextInputEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char *text; /**< The input text */ - char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short input text, use 'text' instead */ + Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_WindowID windowID; /**< The window with keyboard focus, if any */ + char *text; /**< The input text */ } SDL_TextInputEvent; /** @@ -295,7 +289,7 @@ typedef struct SDL_MouseMotionEvent { Uint32 type; /**< ::SDL_EVENT_MOUSE_MOTION */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The window with mouse focus, if any */ + SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint32 state; /**< The current button state */ float x; /**< X coordinate, relative to window */ @@ -311,7 +305,7 @@ typedef struct SDL_MouseButtonEvent { Uint32 type; /**< ::SDL_EVENT_MOUSE_BUTTON_DOWN or ::SDL_EVENT_MOUSE_BUTTON_UP */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The window with mouse focus, if any */ + SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint8 button; /**< The mouse button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ @@ -328,7 +322,7 @@ typedef struct SDL_MouseWheelEvent { Uint32 type; /**< ::SDL_EVENT_MOUSE_WHEEL */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The window with mouse focus, if any */ + SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */ @@ -507,15 +501,13 @@ typedef struct SDL_TouchFingerEvent float dx; /**< Normalized in the range -1...1 */ float dy; /**< Normalized in the range -1...1 */ float pressure; /**< Normalized in the range 0...1 */ - SDL_WindowID windowID;/**< The window underneath the finger, if any */ + SDL_WindowID windowID; /**< The window underneath the finger, if any */ } SDL_TouchFingerEvent; #define SDL_DROPEVENT_DATA_SIZE 64 /** * \brief An event used to drop text or request a file open by the system (event.drop.*) - * - * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_DropEvent { @@ -526,7 +518,6 @@ typedef struct SDL_DropEvent float y; /**< Y coordinate, relative to window (not on begin) */ char *source; /**< The source app that sent this drop event, or NULL if that isn't available */ char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ - char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data, use 'data' instead */ } SDL_DropEvent; /** @@ -545,7 +536,7 @@ typedef struct SDL_SensorEvent { Uint32 type; /**< ::SDL_EVENT_SENSOR_UPDATE */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_SensorID which; /**< The instance ID of the sensor */ + SDL_SensorID which; /**< The instance ID of the sensor */ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_GetSensorData() */ Uint64 sensor_timestamp; /**< The timestamp of the sensor reading in nanoseconds, not necessarily synchronized with the system clock */ } SDL_SensorEvent; @@ -575,7 +566,7 @@ typedef struct SDL_UserEvent { Uint32 type; /**< ::SDL_EVENT_USER through ::SDL_EVENT_LAST-1 */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID;/**< The associated window if any */ + SDL_WindowID windowID; /**< The associated window if any */ Sint32 code; /**< User defined event code */ void *data1; /**< User defined data pointer */ void *data2; /**< User defined data pointer */ @@ -589,8 +580,6 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; * \brief A video driver dependent system event (event.syswm.*) * This event is disabled by default, you can enable it with SDL_SetEventEnabled() * - * \note This event should be cleaned up with SDL_CleanupEvent() after processing. - * * \note If you want to use this event, you should include SDL_syswm.h. */ typedef struct SDL_SysWMEvent @@ -641,7 +630,7 @@ typedef union SDL_Event largest datatype within the union, which is 8 bytes on 64-bit architectures. - So... we'll add padding to force the size to be 56 bytes for both. + So... we'll add padding to force the size to be the same for both. On architectures where pointers are 16 bytes, this needs rounding up to the next multiple of 16, 64, and on architectures where pointers are @@ -850,7 +839,6 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CleanupEvent * \sa SDL_PushEvent * \sa SDL_WaitEvent * \sa SDL_WaitEventTimeout @@ -873,7 +861,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PollEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CleanupEvent * \sa SDL_PollEvent * \sa SDL_PushEvent * \sa SDL_WaitEventTimeout @@ -902,33 +889,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CleanupEvent * \sa SDL_PollEvent * \sa SDL_PushEvent * \sa SDL_WaitEvent */ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); -/** - * Clean up dynamically allocated memory for an event. - * - * Some events have dynamically allocated data that must be cleaned up when - * the event is processed. If you handle any of these events, you should call - * SDL_CleanupEvent() after processing them: SDL_EVENT_DROP_FILE - * SDL_EVENT_DROP_TEXT SDL_EVENT_SYSWM SDL_EVENT_TEXT_EDITING - * - * It is safe, but not necessary, to call this function for other event types. - * - * \param event a pointer to the event that should be cleaned up - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_PollEvent - * \sa SDL_WaitEvent - * \sa SDL_WaitEventTimeout - */ -extern DECLSPEC void SDLCALL SDL_CleanupEvent(SDL_Event *event); - /** * Add an event to the event queue. * @@ -1145,6 +1111,20 @@ extern DECLSPEC SDL_bool SDLCALL SDL_EventEnabled(Uint32 type); */ extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); +/** + * Allocate dynamic memory for an SDL event + * + * You can use this to allocate memory for user events that will be automatically freed after the event is processed. + * + * \param size the amount of memory to allocate + * \returns a pointer to the memory allocated or NULL on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_FlushEventMemory + */ +extern DECLSPEC void * SDLCALL SDL_AllocateEventMemory(size_t size); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index fb0a2f38e6b9e..2ca77c901f2e2 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -921,9 +921,9 @@ SDL3_0.0.0 { SDL_GetWindowProperties; SDL_ClearProperty; SDL_EnterAppMainCallbacks; - SDL_CleanupEvent; SDL_RWprintf; SDL_RWvprintf; + SDL_AllocateEventMemory; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 84d0d91f7663c..f21ee321b5676 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -946,6 +946,6 @@ #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL #define SDL_ClearProperty SDL_ClearProperty_REAL #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL -#define SDL_CleanupEvent SDL_CleanupEvent_REAL #define SDL_RWprintf SDL_RWprintf_REAL #define SDL_RWvprintf SDL_RWvprintf_REAL +#define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 5b9dace0ffdd0..c3cdbc3bad10f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -979,5 +979,5 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),r SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(void,SDL_CleanupEvent,(SDL_Event *a),(a),) SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return) +SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index a7b9fa7a79a7f..b6544dc80685b 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -62,13 +62,12 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch event.drop.source = SDL_strdup(source); } if (data) { - size_t len = SDL_strlen(data); - if (len < sizeof(event.drop.short_data)) { - SDL_memcpy(event.drop.short_data, data, len + 1); - event.drop.data = event.drop.short_data; - } else { - event.drop.data = SDL_strdup(data); + size_t size = SDL_strlen(data) + 1; + event.drop.data = (char *)SDL_AllocateEventMemory(size); + if (!event.drop.data) { + return 0; } + SDL_memcpy(event.drop.data, data, size); } event.drop.windowID = window ? window->id : 0; diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index ce9e6de5fcda7..337180dbc7947 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -62,6 +62,7 @@ static int SDL_event_watchers_count = 0; static SDL_bool SDL_event_watchers_dispatching = SDL_FALSE; static SDL_bool SDL_event_watchers_removed = SDL_FALSE; static SDL_AtomicInt SDL_sentinel_pending; +static Uint32 SDL_last_event_id = 0; typedef struct { @@ -90,6 +91,77 @@ static struct SDL_EventEntry *free; } SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL }; +typedef struct SDL_EventMemory +{ + Uint32 eventID; + void *memory; + struct SDL_EventMemory *next; +} SDL_EventMemory; + +static SDL_Mutex *SDL_event_memory_lock; +static SDL_EventMemory *SDL_event_memory_head; +static SDL_EventMemory *SDL_event_memory_tail; + +void *SDL_AllocateEventMemory(size_t size) +{ + void *memory = SDL_malloc(size); + if (!memory) { + SDL_OutOfMemory(); + return NULL; + } + + SDL_LockMutex(SDL_event_memory_lock); + { + SDL_EventMemory *entry = (SDL_EventMemory *)SDL_malloc(sizeof(*entry)); + if (entry) { + entry->eventID = SDL_last_event_id; + entry->memory = memory; + entry->next = NULL; + + if (SDL_event_memory_tail) { + SDL_event_memory_tail->next = entry; + } else { + SDL_event_memory_head = entry; + } + SDL_event_memory_tail = entry; + } else { + SDL_free(memory); + memory = NULL; + SDL_OutOfMemory(); + } + } + SDL_UnlockMutex(SDL_event_memory_lock); + + return memory; +} + +static void SDL_FlushEventMemory(Uint32 eventID) +{ + SDL_LockMutex(SDL_event_memory_lock); + { + if (SDL_event_memory_head) { + while (SDL_event_memory_head) { + SDL_EventMemory *entry = SDL_event_memory_head; + + if (eventID && (Sint32)(eventID - entry->eventID) < 0) { + break; + } + + /* If you crash here, your application has memory corruption + * or freed memory in an event, which is no longer necessary. + */ + SDL_event_memory_head = entry->next; + SDL_free(entry->memory); + SDL_free(entry); + } + if (!SDL_event_memory_head) { + SDL_event_memory_tail = NULL; + } + } + } + SDL_UnlockMutex(SDL_event_memory_lock); +} + #ifndef SDL_JOYSTICK_DISABLED static SDL_bool SDL_update_joysticks = SDL_TRUE; @@ -468,22 +540,6 @@ static void SDL_LogEvent(const SDL_Event *event) #undef uint } -static void SDL_CopyEvent(SDL_Event *dst, SDL_Event *src) -{ - SDL_copyp(dst, src); - - /* Pointers to internal static data must be updated when copying. */ - if (src->type == SDL_EVENT_TEXT_EDITING && src->edit.text == src->edit.short_text) { - dst->edit.text = dst->edit.short_text; - } else if (src->type == SDL_EVENT_TEXT_INPUT && src->text.text == src->text.short_text) { - dst->text.text = dst->text.short_text; - } else if ((src->type == SDL_EVENT_DROP_FILE || src->type == SDL_EVENT_DROP_TEXT) && src->drop.data == src->drop.short_data) { - dst->drop.data = dst->drop.short_data; - } -} - -/* Public functions */ - void SDL_StopEventLoop(void) { const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS"); @@ -518,12 +574,18 @@ void SDL_StopEventLoop(void) SDL_EventQ.free = NULL; SDL_AtomicSet(&SDL_sentinel_pending, 0); + SDL_FlushEventMemory(0); + /* Clear disabled event state */ for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) { SDL_free(SDL_disabled_events[i]); SDL_disabled_events[i] = NULL; } + if (SDL_event_memory_lock) { + SDL_DestroyMutex(SDL_event_memory_lock); + SDL_event_memory_lock = NULL; + } if (SDL_event_watchers_lock) { SDL_DestroyMutex(SDL_event_watchers_lock); SDL_event_watchers_lock = NULL; @@ -569,6 +631,14 @@ int SDL_StartEventLoop(void) return -1; } } + + if (SDL_event_memory_lock == NULL) { + SDL_event_memory_lock = SDL_CreateMutex(); + if (SDL_event_memory_lock == NULL) { + SDL_UnlockMutex(SDL_EventQ.lock); + return -1; + } + } #endif /* !SDL_THREADS_DISABLED */ /* Process most event types */ @@ -611,7 +681,7 @@ static int SDL_AddEvent(SDL_Event *event) SDL_LogEvent(event); } - SDL_CopyEvent(&entry->event, event); + SDL_copyp(&entry->event, event); if (event->type == SDL_EVENT_POLL_SENTINEL) { SDL_AtomicAdd(&SDL_sentinel_pending, 1); } @@ -634,6 +704,8 @@ static int SDL_AddEvent(SDL_Event *event) SDL_EventQ.max_events_seen = final_count; } + ++SDL_last_event_id; + return 1; } @@ -720,7 +792,7 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact type = entry->event.type; if (minType <= type && type <= maxType) { if (events) { - SDL_CopyEvent(&events[used], &entry->event); + SDL_copyp(&events[used], &entry->event); if (action == SDL_GETEVENT) { SDL_CutEvent(entry); @@ -799,7 +871,6 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) next = entry->next; type = entry->event.type; if (minType <= type && type <= maxType) { - SDL_CleanupEvent(&entry->event); SDL_CutEvent(entry); } } @@ -812,6 +883,12 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); + /* Free old event memory */ + /*SDL_FlushEventMemory(SDL_last_event_id - SDL_MAX_QUEUED_EVENTS);*/ + if (SDL_AtomicGet(&SDL_EventQ.count) == 0) { + SDL_FlushEventMemory(SDL_last_event_id); + } + /* Release any keys held down from last frame */ SDL_ReleaseAutoReleaseKeys(); @@ -1082,43 +1159,6 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) } } -void SDL_CleanupEvent(SDL_Event *event) -{ - switch (event->type) { - case SDL_EVENT_DROP_FILE: - case SDL_EVENT_DROP_TEXT: - if (event->drop.source) { - SDL_free(event->drop.source); - event->drop.data = NULL; - } - if (event->drop.data && event->drop.data != event->drop.short_data) { - SDL_free(event->drop.data); - event->drop.data = NULL; - } - break; - case SDL_EVENT_SYSWM: - if (event->syswm.msg) { - SDL_free(event->syswm.msg); - event->syswm.msg = NULL; - } - break; - case SDL_EVENT_TEXT_EDITING: - if (event->edit.text && event->edit.text != event->edit.short_text) { - SDL_free(event->edit.text); - event->edit.text = NULL; - } - break; - case SDL_EVENT_TEXT_INPUT: - if (event->text.text && event->text.text != event->text.short_text) { - SDL_free(event->text.text); - event->text.text = NULL; - } - break; - default: - break; - } -} - int SDL_PushEvent(SDL_Event *event) { if (!event->common.timestamp) { @@ -1375,7 +1415,7 @@ int SDL_SendSysWMEvent(SDL_SysWMmsg *message) SDL_memset(&event, 0, sizeof(event)); event.type = SDL_EVENT_SYSWM; event.common.timestamp = 0; - event.syswm.msg = (SDL_SysWMmsg *)SDL_malloc(sizeof(*message)); + event.syswm.msg = (SDL_SysWMmsg *)SDL_AllocateEventMemory(sizeof(*message)); if (!event.syswm.msg) { return 0; } diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 2e69aac027cd4..c1f27bc466456 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1075,13 +1075,12 @@ int SDL_SendKeyboardText(const char *text) event.common.timestamp = 0; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; - size_t len = SDL_strlen(text); - if (len < sizeof(event.text.short_text)) { - SDL_memcpy(event.text.short_text, text, len + 1); - event.text.text = event.text.short_text; - } else { - event.text.text = SDL_strdup(text); + size_t size = SDL_strlen(text) + 1; + event.text.text = (char *)SDL_AllocateEventMemory(size); + if (!event.text.text) { + return 0; } + SDL_memcpy(event.text.text, text, size); posted = (SDL_PushEvent(&event) > 0); } @@ -1104,13 +1103,12 @@ int SDL_SendEditingText(const char *text, int start, int length) event.edit.start = start; event.edit.length = length; - size_t len = SDL_strlen(text); - if (len < sizeof(event.edit.short_text)) { - SDL_memcpy(event.edit.short_text, text, len + 1); - event.edit.text = event.edit.short_text; - } else { - event.edit.text = SDL_strdup(text); + size_t size = SDL_strlen(text) + 1; + event.edit.text = (char *)SDL_AllocateEventMemory(size); + if (!event.edit.text) { + return 0; } + SDL_memcpy(event.edit.text, text, size); posted = (SDL_PushEvent(&event) > 0); } diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 6fd0783a4cfb8..0c091323f03ee 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -48,7 +48,6 @@ static void SDL_DispatchMainCallbackEvent(SDL_Event *event) if (SDL_AtomicGet(&apprc) == 0) { // if already quitting, don't send the event to the app. SDL_AtomicCAS(&apprc, 0, SDL_main_event_callback(event)); } - SDL_CleanupEvent(event); } static void SDL_DispatchMainCallbackEvents() diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 4e179829ce3ad..0a3360f81679c 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -2424,8 +2424,6 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done) { *done = SDLTest_CommonEventMainCallbacks(state, event) ? 1 : 0; - - SDL_CleanupEvent(event); } void SDLTest_CommonQuit(SDLTest_CommonState *state) diff --git a/test/checkkeys.c b/test/checkkeys.c index 4894f6436874b..cdba94157cf95 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -181,12 +181,10 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.edit.text); - SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); SDLTest_TextWindowAddText(textwin, "%s", event.text.text); - SDL_CleanupEvent(&event); break; case SDL_EVENT_FINGER_DOWN: if (SDL_TextInputActive()) { diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index cae8f48e849c9..cca4740e4c0be 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -183,11 +183,9 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.text.text); - SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); - SDL_CleanupEvent(&event); break; case SDL_EVENT_MOUSE_BUTTON_DOWN: /* Left button quits the app, other buttons toggles text input */ diff --git a/test/testcontroller.c b/test/testcontroller.c index cdcd28ed2fbca..dd4b9819d95f0 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1728,7 +1728,6 @@ static void loop(void *arg) AddControllerNameText(event.text.text); } } - SDL_CleanupEvent(&event); break; case SDL_EVENT_QUIT: done = SDL_TRUE; diff --git a/test/testdropfile.c b/test/testdropfile.c index 3da1a79126304..a24547bb20cbe 100644 --- a/test/testdropfile.c +++ b/test/testdropfile.c @@ -69,8 +69,6 @@ int main(int argc, char *argv[]) } else if ((event.type == SDL_EVENT_DROP_FILE) || (event.type == SDL_EVENT_DROP_TEXT)) { const char *typestr = (event.type == SDL_EVENT_DROP_FILE) ? "File" : "Text"; SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, event.drop.data, event.drop.x, event.drop.y); - /* Normally you'd have to do this, but this is freed in SDLTest_CommonEvent() */ - /*SDL_CleanupEvent(&event);*/ } else if (event.type == SDL_EVENT_DROP_POSITION) { is_hover = SDL_TRUE; x = event.drop.x; diff --git a/test/testime.c b/test/testime.c index e2353db211719..84d3aecbbdee9 100644 --- a/test/testime.c +++ b/test/testime.c @@ -770,7 +770,6 @@ int main(int argc, char *argv[]) /* is committed */ markedText[0] = 0; Redraw(); - SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_EDITING: @@ -780,7 +779,6 @@ int main(int argc, char *argv[]) SDL_strlcpy(markedText, event.edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE); cursor = event.edit.start; Redraw(); - SDL_CleanupEvent(&event); break; } } From 21ff699251f84e5f915188b69f05a4bd64a81920 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 5 Nov 2023 12:04:49 -0500 Subject: [PATCH 245/725] test: Fix popup test crash on exit If the done signal is emitted by the common event handler, the window and all of its children have already been destroyed, so don't try to render with invalid renderer objects. --- test/testpopup.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/testpopup.c b/test/testpopup.c index a8ecabe065bda..9631536ffa16d 100644 --- a/test/testpopup.c +++ b/test/testpopup.c @@ -188,6 +188,10 @@ static void loop(void) SDLTest_CommonEvent(state, &event, &done); } + if (done) { + return; + } + /* Show the tooltip if the delay period has elapsed */ if (SDL_GetTicks() > tooltip_timer) { if (tooltip.win == NULL) { From d2e005ee13a35cb6b11bb8966b491b194251a6c4 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Sun, 5 Nov 2023 20:32:50 +0300 Subject: [PATCH 246/725] dynapi: remove duplicated SDL_LoadWAV entries --- src/dynapi/SDL_dynapi.sym | 1 - src/dynapi/SDL_dynapi_overrides.h | 1 - src/dynapi/SDL_dynapi_procs.h | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 2ca77c901f2e2..4d1999c23937c 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -879,7 +879,6 @@ SDL3_0.0.0 { SDL_MixAudioFormat; SDL_ConvertAudioSamples; SDL_GetSilenceValueForFormat; - SDL_LoadWAV; SDL_PauseAudioDevice; SDL_ResumeAudioDevice; SDL_AudioDevicePaused; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index f21ee321b5676..799e29f2f2388 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -904,7 +904,6 @@ #define SDL_MixAudioFormat SDL_MixAudioFormat_REAL #define SDL_ConvertAudioSamples SDL_ConvertAudioSamples_REAL #define SDL_GetSilenceValueForFormat SDL_GetSilenceValueForFormat_REAL -#define SDL_LoadWAV SDL_LoadWAV_REAL #define SDL_PauseAudioDevice SDL_PauseAudioDevice_REAL #define SDL_ResumeAudioDevice SDL_ResumeAudioDevice_REAL #define SDL_AudioDevicePaused SDL_AudioDevicePaused_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index c3cdbc3bad10f..48a999e32c710 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -932,10 +932,10 @@ SDL_DYNAPI_PROC(int,SDL_SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_Audio SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),) SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_OpenAudioDeviceStream,(SDL_AudioDeviceID a, const SDL_AudioSpec *b, SDL_AudioStreamCallback c, void *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_LoadWAV_RW,(SDL_RWops *a, SDL_bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(int,SDL_LoadWAV,(const char *a, SDL_AudioSpec *b, Uint8 **c, Uint32 *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(const SDL_AudioSpec *a, const Uint8 *b, int c, const SDL_AudioSpec *d, Uint8 **e, int *f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(int,SDL_GetSilenceValueForFormat,(SDL_AudioFormat a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LoadWAV,(const char *a, SDL_AudioSpec *b, Uint8 **c, Uint32 *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_PauseAudioDevice,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(int,SDL_ResumeAudioDevice,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return) From 761390b62f641256a80a4e25a4e295eb3f8c47fd Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 6 Nov 2023 00:40:41 +0100 Subject: [PATCH 247/725] cmake: detect linker id, and assume MSVC does not support version scripts --- cmake/macros.cmake | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/cmake/macros.cmake b/cmake/macros.cmake index fa9690f85af6d..69d37ae5fc88b 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -82,19 +82,42 @@ if(APPLE) enable_language(OBJC) endif() +function(SDL_detect_linker) + if(CMAKE_VERSION VERSION_LESS 3.29) + if(NOT DEFINED SDL_CMAKE_C_COMPILER_LINKER_ID) + execute_process(COMMAND ${CMAKE_LINKER} -v OUTPUT_VARIABLE LINKER_OUTPUT ERROR_VARIABLE LINKER_OUTPUT) + string(REGEX REPLACE "[\r\n]" " " LINKER_OUTPUT "${LINKER_OUTPUT}") + if(LINKER_OUTPUT MATCHES ".*Microsoft.*") + set(linker MSVC) + else() + set(linker GNUlike) + endif() + message(STATUS "Linker identification: ${linker}") + set(SDL_CMAKE_C_COMPILER_LINKER_ID "${linker}" CACHE STRING "Linker identification") + mark_as_advanced(SDL_CMAKE_C_COMPILER_LINKER_ID) + endif() + set(CMAKE_C_COMPILER_LINKER_ID "${SDL_CMAKE_C_COMPILER_LINKER_ID}") + endif() +endfunction() + function(check_linker_supports_version_file VAR) - cmake_push_check_state() - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n") - list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym") - check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)") - cmake_pop_check_state() + SDL_detect_linker() + if(CMAKE_C_COMPILER_LINKER_ID MATCHES "^(MSVC)$") + set(LINKER_SUPPORTS_VERSION_SCRIPT FALSE) + else() + cmake_push_check_state(RESET) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n") + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym") + check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)") + cmake_pop_check_state() + endif() set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE) endfunction() if(CMAKE_VERSION VERSION_LESS 3.18) function(check_linker_flag LANG FLAG VAR) - cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${FLAG} ) + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${FLAG}) if(LANG STREQUAL "C") include(CheckCSourceCompiles) check_c_source_compiles("int main(int argc,char*argv[]){(void)argc;(void)argv;return 0;}" ${VAR} FAIL_REGEX "(unsupported|syntax error)") From 459f17257c35fb8c67506f0d1bf495470f402e7d Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 6 Nov 2023 01:58:26 +0100 Subject: [PATCH 248/725] cmake: fix MSVC unrecognized option link warning --- cmake/macros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros.cmake b/cmake/macros.cmake index 69d37ae5fc88b..f91946425d2fe 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -96,7 +96,7 @@ function(SDL_detect_linker) set(SDL_CMAKE_C_COMPILER_LINKER_ID "${linker}" CACHE STRING "Linker identification") mark_as_advanced(SDL_CMAKE_C_COMPILER_LINKER_ID) endif() - set(CMAKE_C_COMPILER_LINKER_ID "${SDL_CMAKE_C_COMPILER_LINKER_ID}") + set(CMAKE_C_COMPILER_LINKER_ID "${SDL_CMAKE_C_COMPILER_LINKER_ID}" PARENT_SCOPE) endif() endfunction() From 20cd789babdaf5edfc5f66033ff1701ad0d796bb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 21:20:48 -0800 Subject: [PATCH 249/725] Improved migration documentation for the event memory change. --- docs/README-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index acddcf00b7499..ab156c3e65458 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -298,7 +298,7 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). -You should not call SDL_free() on the data in SDL_EVENT_DROP_FILE, SDL manages the memory for events internally, you no longer have to free the data yourself. +Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. From 04dfca958a9f5bfa2760a220e33e0ce97f94a334 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 21:25:43 -0800 Subject: [PATCH 250/725] Added a note to events indicating that memory is owned by SDL --- include/SDL3/SDL_events.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 6aa8b9aeb510b..760c6ca75b76d 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -259,6 +259,9 @@ typedef struct SDL_KeyboardEvent #define SDL_TEXTEDITINGEVENT_TEXT_SIZE 64 /** * \brief Keyboard text editing event structure (event.edit.*) + * + * The `text` is owned by SDL and should be copied if the application + * wants to hold onto it beyond the scope of handling this event. */ typedef struct SDL_TextEditingEvent { @@ -273,6 +276,9 @@ typedef struct SDL_TextEditingEvent #define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** * \brief Keyboard text input event structure (event.text.*) + * + * The `text` is owned by SDL and should be copied if the application + * wants to hold onto it beyond the scope of handling this event. */ typedef struct SDL_TextInputEvent { @@ -508,6 +514,9 @@ typedef struct SDL_TouchFingerEvent #define SDL_DROPEVENT_DATA_SIZE 64 /** * \brief An event used to drop text or request a file open by the system (event.drop.*) + * + * The `data` is owned by SDL and should be copied if the application + * wants to hold onto it beyond the scope of handling this event. */ typedef struct SDL_DropEvent { @@ -580,6 +589,9 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; * \brief A video driver dependent system event (event.syswm.*) * This event is disabled by default, you can enable it with SDL_SetEventEnabled() * + * The `msg` is owned by SDL and should be copied if the application + * wants to hold onto it beyond the scope of handling this event. + * * \note If you want to use this event, you should include SDL_syswm.h. */ typedef struct SDL_SysWMEvent From bc3d9e99f381072820d29e75e6cc28fe40572c42 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 5 Nov 2023 22:12:37 -0800 Subject: [PATCH 251/725] Only save ibus_addr_file after we've successfully read an address from it. Fixes https://github.com/libsdl-org/SDL/issues/3359 --- src/core/linux/SDL_ibus.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 4c1b838635fa6..237c300fcd91e 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -560,15 +560,17 @@ SDL_bool SDL_IBus_Init(void) return SDL_FALSE; } - /* !!! FIXME: if ibus_addr_file != NULL, this will overwrite it and leak (twice!) */ - ibus_addr_file = SDL_strdup(addr_file); - addr = IBus_ReadAddressFromFile(addr_file); if (addr == NULL) { SDL_free(addr_file); return SDL_FALSE; } + if (ibus_addr_file) { + SDL_free(ibus_addr_file); + } + ibus_addr_file = SDL_strdup(addr_file); + if (inotify_fd < 0) { inotify_fd = inotify_init(); fcntl(inotify_fd, F_SETFL, O_NONBLOCK); From 3e4d7e48b0a87b2c1df26ad62c8152ba6c064024 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 00:40:19 -0800 Subject: [PATCH 252/725] Fixed memory leak in XInput code Fixes https://github.com/libsdl-org/SDL/issues/3597 --- src/joystick/windows/SDL_xinputjoystick.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index b5369bb616cd8..253e7e1086825 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -552,6 +552,12 @@ void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick) void SDL_XINPUT_JoystickQuit(void) { + int iuserid; + + for (iuserid = 0; iuserid < XUSER_MAX_COUNT; ++iuserid) { + DelXInputDevice(iuserid); + } + if (s_bXInputEnabled) { WIN_UnloadXInputDLL(); } From f7d40b7594848e5386df7f246a28aca2cb23bed3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 00:21:26 -0800 Subject: [PATCH 253/725] Added 10-bit pixel formats in addition to SDL_PIXELFORMAT_ARGB2101010 Added SDL_PIXELFORMAT_XRGB2101010, SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ABGR2101010 Fixes https://github.com/libsdl-org/SDL/issues/3553 --- include/SDL3/SDL_pixels.h | 13 +++++++++++ src/video/SDL_blit.h | 15 ++++++++++++ src/video/SDL_blit_N.c | 24 +++++++++---------- src/video/SDL_blit_slow.c | 44 +++++++++++++++++++++++++++++++---- src/video/SDL_pixels.c | 36 ++++++++++++++++++++++++++++ test/testautomation_pixels.c | 6 +++++ test/testautomation_surface.c | 3 +++ 7 files changed, 124 insertions(+), 17 deletions(-) diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 82d4feb338006..8f7086d9af519 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -190,6 +190,10 @@ typedef enum (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA)))) +#define SDL_ISPIXELFORMAT_10BIT(format) \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32) && \ + (SDL_PIXELLAYOUT(format) == SDL_PACKEDLAYOUT_2101010)) + /* The flag is set to 1 because 0x1? is not in the printable ASCII range */ #define SDL_ISPIXELFORMAT_FOURCC(format) \ ((format) && (SDL_PIXELFLAG(format) != 1)) @@ -291,9 +295,18 @@ typedef enum SDL_PIXELFORMAT_BGRA8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_8888, 32, 4), + SDL_PIXELFORMAT_XRGB2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_2101010, 32, 4), + SDL_PIXELFORMAT_XBGR2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, + SDL_PACKEDLAYOUT_2101010, 32, 4), SDL_PIXELFORMAT_ARGB2101010 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010, 32, 4), + SDL_PIXELFORMAT_ABGR2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, + SDL_PACKEDLAYOUT_2101010, 32, 4), /* Aliases for RGBA byte arrays of color data, for the current platform */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index 0568dce3f0cf2..759d005b8b236 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -260,6 +260,14 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface); a = (a * 3) / 255; \ Pixel = (a << 30) | (r << 20) | (g << 10) | b; \ } +#define ABGR2101010_FROM_RGBA(Pixel, r, g, b, a) \ + { \ + r = r ? ((r << 2) | 0x3) : 0; \ + g = g ? ((g << 2) | 0x3) : 0; \ + b = b ? ((b << 2) | 0x3) : 0; \ + a = (a * 3) / 255; \ + Pixel = (a << 30) | (b << 20) | (g << 10) | r; \ + } #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ { \ switch (bpp) { \ @@ -352,6 +360,13 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface); b = ((Pixel >> 2) & 0xFF); \ a = SDL_expand_byte[6][(Pixel >> 30)]; \ } +#define RGBA_FROM_ABGR2101010(Pixel, r, g, b, a) \ + { \ + r = ((Pixel >> 2) & 0xFF); \ + g = ((Pixel >> 12) & 0xFF); \ + b = ((Pixel >> 22) & 0xFF); \ + a = SDL_expand_byte[6][(Pixel >> 30)]; \ + } #define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \ do { \ switch (bpp) { \ diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index bf7c910763613..4c1f8c3e3997c 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -2327,8 +2327,8 @@ static void BlitNtoN(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2356,7 +2356,7 @@ static void BlitNtoN(SDL_BlitInfo *info) /* Blit with permutation: 4->3 */ if (srcbpp == 4 && dstbpp == 3 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2382,7 +2382,7 @@ static void BlitNtoN(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 3->4 */ if (srcbpp == 3 && dstbpp == 4 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2445,8 +2445,8 @@ static void BlitNtoNCopyAlpha(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2651,8 +2651,8 @@ static void BlitNtoNKey(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2760,7 +2760,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info) /* Blit with permutation: 4->3 */ if (srcbpp == 4 && dstbpp == 3 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2789,7 +2789,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 3->4 */ if (srcbpp == 3 && dstbpp == 4 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN Uint8 k0 = ckey & 0xFF; @@ -2909,8 +2909,8 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index 3c2730c05a378..d4d3d43bac847 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -30,7 +30,7 @@ #define FORMAT_HAS_NO_ALPHA(format) format < 0 static int detect_format(SDL_PixelFormat *pf) { - if (pf->format == SDL_PIXELFORMAT_ARGB2101010) { + if (SDL_ISPIXELFORMAT_10BIT(pf->format)) { return FORMAT_2101010; } else if (pf->Amask) { return FORMAT_ALPHA; @@ -88,9 +88,27 @@ void SDL_Blit_Slow(SDL_BlitInfo *info) DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB); srcA = 0xFF; } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ + /* 10-bit pixel format */ srcpixel = *((Uint32 *)(src)); - RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + switch (src_fmt->format) { + case SDL_PIXELFORMAT_XRGB2101010: + RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + srcA = 0xFF; + break; + case SDL_PIXELFORMAT_XBGR2101010: + RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA); + srcA = 0xFF; + break; + case SDL_PIXELFORMAT_ARGB2101010: + RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + break; + case SDL_PIXELFORMAT_ABGR2101010: + RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA); + break; + default: + srcR = srcG = srcB = srcA = 0; + break; + } } if (flags & SDL_COPY_COLORKEY) { @@ -189,9 +207,25 @@ void SDL_Blit_Slow(SDL_BlitInfo *info) } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB); } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ + /* 10-bit pixel format */ Uint32 pixel; - ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + switch (dst_fmt->format) { + case SDL_PIXELFORMAT_XRGB2101010: + dstA = 0xFF; + SDL_FALLTHROUGH; + case SDL_PIXELFORMAT_ARGB2101010: + ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + break; + case SDL_PIXELFORMAT_XBGR2101010: + dstA = 0xFF; + SDL_FALLTHROUGH; + case SDL_PIXELFORMAT_ABGR2101010: + ABGR2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + break; + default: + pixel = 0; + break; + } *(Uint32 *)dst = pixel; } posx += incx; diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 7c31a24b4f0b3..f9e79bfd42ae0 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -117,7 +117,10 @@ const char *SDL_GetPixelFormatName(Uint32 format) CASE(SDL_PIXELFORMAT_RGBA8888) CASE(SDL_PIXELFORMAT_ABGR8888) CASE(SDL_PIXELFORMAT_BGRA8888) + CASE(SDL_PIXELFORMAT_XRGB2101010) + CASE(SDL_PIXELFORMAT_XBGR2101010) CASE(SDL_PIXELFORMAT_ARGB2101010) + CASE(SDL_PIXELFORMAT_ABGR2101010) CASE(SDL_PIXELFORMAT_YV12) CASE(SDL_PIXELFORMAT_IYUV) CASE(SDL_PIXELFORMAT_YUY2) @@ -440,6 +443,20 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3 #endif } break; + case 30: + if (Rmask == 0x3FF00000 && + Gmask == 0x000FFC00 && + Bmask == 0x000003FF && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XRGB2101010; + } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XBGR2101010; + } + break; case 32: if (Rmask == 0) { return SDL_PIXELFORMAT_XRGB8888; @@ -492,12 +509,31 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3 Amask == 0x000000FF) { return SDL_PIXELFORMAT_BGRA8888; } + if (Rmask == 0x3FF00000 && + Gmask == 0x000FFC00 && + Bmask == 0x000003FF && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XRGB2101010; + } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XBGR2101010; + } if (Rmask == 0x3FF00000 && Gmask == 0x000FFC00 && Bmask == 0x000003FF && Amask == 0xC0000000) { return SDL_PIXELFORMAT_ARGB2101010; } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0xC0000000) { + return SDL_PIXELFORMAT_ABGR2101010; + } + break; } return SDL_PIXELFORMAT_UNKNOWN; } diff --git a/test/testautomation_pixels.c b/test/testautomation_pixels.c index 9980b561b28d1..f05c9a981398b 100644 --- a/test/testautomation_pixels.c +++ b/test/testautomation_pixels.c @@ -39,7 +39,10 @@ static const Uint32 g_AllFormats[] = { SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_XRGB2101010, + SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ARGB2101010, + SDL_PIXELFORMAT_ABGR2101010, SDL_PIXELFORMAT_YV12, SDL_PIXELFORMAT_IYUV, SDL_PIXELFORMAT_YUY2, @@ -81,7 +84,10 @@ static const char *g_AllFormatsVerbose[] = { "SDL_PIXELFORMAT_RGBA8888", "SDL_PIXELFORMAT_ABGR8888", "SDL_PIXELFORMAT_BGRA8888", + "SDL_PIXELFORMAT_XRGB2101010", + "SDL_PIXELFORMAT_XBGR2101010", "SDL_PIXELFORMAT_ARGB2101010", + "SDL_PIXELFORMAT_ABGR2101010", "SDL_PIXELFORMAT_YV12", "SDL_PIXELFORMAT_IYUV", "SDL_PIXELFORMAT_YUY2", diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index acde6396c561f..e338927e74790 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -327,7 +327,10 @@ static int surface_testCompleteSurfaceConversion(void *arg) SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_XRGB2101010, + SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ARGB2101010, + SDL_PIXELFORMAT_ABGR2101010, }; SDL_Surface *face = NULL, *cvt1, *cvt2, *final; SDL_PixelFormat *fmt1, *fmt2; From 7ac281f8009f6df620f57e60ca3c16bc82d4810b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 09:33:05 -0500 Subject: [PATCH 254/725] Sync wiki -> headers. --- include/SDL3/SDL_events.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 760c6ca75b76d..00bc35ecff75e 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -1126,10 +1126,12 @@ extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); /** * Allocate dynamic memory for an SDL event * - * You can use this to allocate memory for user events that will be automatically freed after the event is processed. + * You can use this to allocate memory for user events that will be + * automatically freed after the event is processed. * * \param size the amount of memory to allocate - * \returns a pointer to the memory allocated or NULL on failure; call SDL_GetError() for more information. + * \returns a pointer to the memory allocated or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * From c132295ad72a21aab1902f6714eabb4a003cbaad Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Mon, 6 Nov 2023 17:40:56 +0300 Subject: [PATCH 255/725] SDL_FlushEventMemory is not a public procedure. --- include/SDL3/SDL_events.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 00bc35ecff75e..4c6b6efdc172e 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -1134,8 +1134,6 @@ extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_FlushEventMemory */ extern DECLSPEC void * SDLCALL SDL_AllocateEventMemory(size_t size); From c53843a961add42c06a99f5f26980fe3072159c3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 10:26:06 -0500 Subject: [PATCH 256/725] docs: Remove Doxygen `\brief` tags. Doxygen and the wiki bridge don't need them; they'll both just use the first line/sentence instead. Fixes #8446. --- include/SDL3/SDL_assert.h | 2 +- include/SDL3/SDL_atomic.h | 11 +- include/SDL3/SDL_audio.h | 4 +- include/SDL3/SDL_bits.h | 2 +- include/SDL3/SDL_blendmode.h | 8 +- include/SDL3/SDL_clipboard.h | 2 +- include/SDL3/SDL_copying.h | 2 +- include/SDL3/SDL_cpuinfo.h | 2 +- include/SDL3/SDL_egl.h | 2 +- include/SDL3/SDL_endian.h | 2 +- include/SDL3/SDL_events.h | 68 ++-- include/SDL3/SDL_filesystem.h | 2 +- include/SDL3/SDL_gamepad.h | 2 +- include/SDL3/SDL_guid.h | 2 +- include/SDL3/SDL_haptic.h | 71 ++-- include/SDL3/SDL_hidapi.h | 8 +- include/SDL3/SDL_hints.h | 358 +++++++++--------- include/SDL3/SDL_init.h | 4 +- include/SDL3/SDL_intrin.h | 2 +- include/SDL3/SDL_joystick.h | 4 +- include/SDL3/SDL_keyboard.h | 4 +- include/SDL3/SDL_keycode.h | 6 +- include/SDL3/SDL_loadso.h | 2 +- include/SDL3/SDL_locale.h | 2 +- include/SDL3/SDL_log.h | 8 +- include/SDL3/SDL_main.h | 2 +- include/SDL3/SDL_metal.h | 4 +- include/SDL3/SDL_misc.h | 2 +- include/SDL3/SDL_mouse.h | 6 +- include/SDL3/SDL_mutex.h | 2 +- include/SDL3/SDL_oldnames.h | 2 +- include/SDL3/SDL_opengl.h | 2 +- include/SDL3/SDL_opengles.h | 2 +- include/SDL3/SDL_opengles2.h | 2 +- include/SDL3/SDL_pixels.h | 2 +- include/SDL3/SDL_platform.h | 2 +- include/SDL3/SDL_platform_defines.h | 2 +- include/SDL3/SDL_power.h | 2 +- include/SDL3/SDL_properties.h | 2 +- include/SDL3/SDL_quit.h | 2 +- include/SDL3/SDL_rect.h | 2 +- include/SDL3/SDL_render.h | 2 +- include/SDL3/SDL_revision.h | 2 +- include/SDL3/SDL_scancode.h | 4 +- include/SDL3/SDL_sensor.h | 4 +- include/SDL3/SDL_shape.h | 22 +- include/SDL3/SDL_stdinc.h | 20 +- include/SDL3/SDL_surface.h | 8 +- include/SDL3/SDL_system.h | 22 +- include/SDL3/SDL_syswm.h | 4 +- include/SDL3/SDL_test.h | 2 +- include/SDL3/SDL_test_assert.h | 18 +- include/SDL3/SDL_test_common.h | 18 +- include/SDL3/SDL_test_compare.h | 6 +- include/SDL3/SDL_test_crc32.h | 8 +- include/SDL3/SDL_test_font.h | 22 +- include/SDL3/SDL_test_fuzzer.h | 2 +- include/SDL3/SDL_test_harness.h | 6 +- include/SDL3/SDL_test_log.h | 6 +- include/SDL3/SDL_test_md5.h | 8 +- include/SDL3/SDL_test_memory.h | 8 +- include/SDL3/SDL_test_random.h | 8 +- include/SDL3/SDL_thread.h | 2 +- include/SDL3/SDL_timer.h | 2 +- include/SDL3/SDL_touch.h | 2 +- include/SDL3/SDL_version.h | 2 +- include/SDL3/SDL_video.h | 26 +- include/SDL3/SDL_vulkan.h | 2 +- include/build_config/SDL_build_config.h | 2 +- include/build_config/SDL_build_config.h.cmake | 2 +- include/build_config/SDL_revision.h.cmake | 2 +- src/core/linux/SDL_udev.h | 2 +- src/hidapi/doxygen/Doxyfile | 2 +- src/render/software/SDL_rotate.c | 16 +- src/test/SDL_test_assert.c | 4 +- src/test/SDL_test_font.c | 2 +- src/test/SDL_test_harness.c | 10 +- test/testautomation_audio.c | 36 +- test/testautomation_clipboard.c | 6 +- test/testautomation_events.c | 6 +- test/testautomation_guid.c | 4 +- test/testautomation_hints.c | 4 +- test/testautomation_images.c | 22 +- test/testautomation_intrinsics.c | 8 +- test/testautomation_joystick.c | 2 +- test/testautomation_keyboard.c | 28 +- test/testautomation_main.c | 2 +- test/testautomation_math.c | 10 +- test/testautomation_mouse.c | 24 +- test/testautomation_pixels.c | 6 +- test/testautomation_platform.c | 24 +- test/testautomation_properties.c | 6 +- test/testautomation_rect.c | 78 ++-- test/testautomation_render.c | 36 +- test/testautomation_rwops.c | 16 +- test/testautomation_sdltest.c | 30 +- test/testautomation_stdlib.c | 14 +- test/testautomation_subsystems.c | 8 +- test/testautomation_surface.c | 20 +- test/testautomation_syswm.c | 2 +- test/testautomation_timer.c | 8 +- test/testautomation_video.c | 36 +- test/testhaptic.c | 2 +- test/testrumble.c | 2 +- 104 files changed, 669 insertions(+), 667 deletions(-) diff --git a/include/SDL3/SDL_assert.h b/include/SDL3/SDL_assert.h index e0addc2ee7658..cdf1da17774bd 100644 --- a/include/SDL3/SDL_assert.h +++ b/include/SDL3/SDL_assert.h @@ -22,7 +22,7 @@ /** * \file SDL_assert.h * - * \brief Header file for assertion SDL API functions + * Header file for assertion SDL API functions */ #ifndef SDL_assert_h_ diff --git a/include/SDL3/SDL_atomic.h b/include/SDL3/SDL_atomic.h index f0c652aa31e19..ece4ac5a3613e 100644 --- a/include/SDL3/SDL_atomic.h +++ b/include/SDL3/SDL_atomic.h @@ -22,7 +22,7 @@ /** * \file SDL_atomic.h * - * \brief Atomic operations. + * Atomic operations. * * IMPORTANT: * If you are not an expert in concurrent lockless programming, you should @@ -263,8 +263,9 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); /** - * \brief A type representing an atomic integer value. It is a struct - * so people don't accidentally use numeric operations on it. + * A type representing an atomic integer value. + * + * It is a struct so people don't accidentally use numeric operations on it. */ typedef struct { int value; } SDL_AtomicInt; @@ -340,14 +341,14 @@ extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_AtomicInt *a); extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_AtomicInt *a, int v); /** - * \brief Increment an atomic variable used as a reference count. + * Increment an atomic variable used as a reference count. */ #ifndef SDL_AtomicIncRef #define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1) #endif /** - * \brief Decrement an atomic variable used as a reference count. + * Decrement an atomic variable used as a reference count. * * \return SDL_TRUE if the variable reached zero after decrementing, * SDL_FALSE otherwise diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index c6e5526d321d9..7ce55ef206090 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -22,7 +22,7 @@ /** * \file SDL_audio.h * - * \brief Audio functionality for the SDL library. + * Audio functionality for the SDL library. */ #ifndef SDL_audio_h_ @@ -54,7 +54,7 @@ extern "C" { */ /** - * \brief Audio format flags. + * Audio format flags. * * These are what the 16 bits in SDL_AudioFormat currently mean... * (Unspecified bits are always zero). diff --git a/include/SDL3/SDL_bits.h b/include/SDL3/SDL_bits.h index ffee5ad7cf872..1d7c09c173aa8 100644 --- a/include/SDL3/SDL_bits.h +++ b/include/SDL3/SDL_bits.h @@ -22,7 +22,7 @@ /** * \file SDL_bits.h * - * \brief Functions for fiddling with bits and bitmasks. + * Functions for fiddling with bits and bitmasks. */ #ifndef SDL_bits_h_ diff --git a/include/SDL3/SDL_blendmode.h b/include/SDL3/SDL_blendmode.h index 7276c9237ec8e..d84d2ba926c06 100644 --- a/include/SDL3/SDL_blendmode.h +++ b/include/SDL3/SDL_blendmode.h @@ -22,7 +22,7 @@ /** * \file SDL_blendmode.h * - * \brief Header file declaring the SDL_BlendMode enumeration + * Header file declaring the SDL_BlendMode enumeration */ #ifndef SDL_blendmode_h_ @@ -35,7 +35,7 @@ extern "C" { #endif /** - * \brief The blend mode used in SDL_RenderTexture() and drawing operations. + * The blend mode used in SDL_RenderTexture() and drawing operations. */ typedef enum { @@ -60,7 +60,7 @@ typedef enum } SDL_BlendMode; /** - * \brief The blend operation used when combining source and destination pixel components + * The blend operation used when combining source and destination pixel components */ typedef enum { @@ -72,7 +72,7 @@ typedef enum } SDL_BlendOperation; /** - * \brief The normalized factor used to multiply pixel components + * The normalized factor used to multiply pixel components */ typedef enum { diff --git a/include/SDL3/SDL_clipboard.h b/include/SDL3/SDL_clipboard.h index e5979646ea265..5f05034bfaee2 100644 --- a/include/SDL3/SDL_clipboard.h +++ b/include/SDL3/SDL_clipboard.h @@ -22,7 +22,7 @@ /** * \file SDL_clipboard.h * - * \brief Include file for SDL clipboard handling + * Include file for SDL clipboard handling */ #ifndef SDL_clipboard_h_ diff --git a/include/SDL3/SDL_copying.h b/include/SDL3/SDL_copying.h index 4b9c1dea94922..4fd0ca11f2b04 100644 --- a/include/SDL3/SDL_copying.h +++ b/include/SDL3/SDL_copying.h @@ -22,5 +22,5 @@ /** * \file SDL_copying.h * - * \brief Header file containing SDL's license. + * Header file containing SDL's license. */ diff --git a/include/SDL3/SDL_cpuinfo.h b/include/SDL3/SDL_cpuinfo.h index 50b889f6d5573..0813c4d283d02 100644 --- a/include/SDL3/SDL_cpuinfo.h +++ b/include/SDL3/SDL_cpuinfo.h @@ -22,7 +22,7 @@ /** * \file SDL_cpuinfo.h * - * \brief CPU feature detection for SDL. + * CPU feature detection for SDL. */ #ifndef SDL_cpuinfo_h_ diff --git a/include/SDL3/SDL_egl.h b/include/SDL3/SDL_egl.h index d9c5d679102ec..1053b4c31448f 100644 --- a/include/SDL3/SDL_egl.h +++ b/include/SDL3/SDL_egl.h @@ -22,7 +22,7 @@ /** * \file SDL_egl.h * - * \brief This is a simple file to encapsulate the EGL API headers. + * This is a simple file to encapsulate the EGL API headers. */ #if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) diff --git a/include/SDL3/SDL_endian.h b/include/SDL3/SDL_endian.h index b77580df3abc6..d670265f1cc39 100644 --- a/include/SDL3/SDL_endian.h +++ b/include/SDL3/SDL_endian.h @@ -22,7 +22,7 @@ /** * \file SDL_endian.h * - * \brief Functions for reading and writing endian-specific values + * Functions for reading and writing endian-specific values */ #ifndef SDL_endian_h_ diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 4c6b6efdc172e..ee4e43d9626dd 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -210,7 +210,7 @@ typedef enum } SDL_EventType; /** - * \brief Fields shared by every event + * Fields shared by every event */ typedef struct SDL_CommonEvent { @@ -219,7 +219,7 @@ typedef struct SDL_CommonEvent } SDL_CommonEvent; /** - * \brief Display state change event data (event.display.*) + * Display state change event data (event.display.*) */ typedef struct SDL_DisplayEvent { @@ -230,7 +230,7 @@ typedef struct SDL_DisplayEvent } SDL_DisplayEvent; /** - * \brief Window state change event data (event.window.*) + * Window state change event data (event.window.*) */ typedef struct SDL_WindowEvent { @@ -242,7 +242,7 @@ typedef struct SDL_WindowEvent } SDL_WindowEvent; /** - * \brief Keyboard button event structure (event.key.*) + * Keyboard button event structure (event.key.*) */ typedef struct SDL_KeyboardEvent { @@ -258,7 +258,7 @@ typedef struct SDL_KeyboardEvent #define SDL_TEXTEDITINGEVENT_TEXT_SIZE 64 /** - * \brief Keyboard text editing event structure (event.edit.*) + * Keyboard text editing event structure (event.edit.*) * * The `text` is owned by SDL and should be copied if the application * wants to hold onto it beyond the scope of handling this event. @@ -275,7 +275,7 @@ typedef struct SDL_TextEditingEvent #define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** - * \brief Keyboard text input event structure (event.text.*) + * Keyboard text input event structure (event.text.*) * * The `text` is owned by SDL and should be copied if the application * wants to hold onto it beyond the scope of handling this event. @@ -289,7 +289,7 @@ typedef struct SDL_TextInputEvent } SDL_TextInputEvent; /** - * \brief Mouse motion event structure (event.motion.*) + * Mouse motion event structure (event.motion.*) */ typedef struct SDL_MouseMotionEvent { @@ -305,7 +305,7 @@ typedef struct SDL_MouseMotionEvent } SDL_MouseMotionEvent; /** - * \brief Mouse button event structure (event.button.*) + * Mouse button event structure (event.button.*) */ typedef struct SDL_MouseButtonEvent { @@ -322,7 +322,7 @@ typedef struct SDL_MouseButtonEvent } SDL_MouseButtonEvent; /** - * \brief Mouse wheel event structure (event.wheel.*) + * Mouse wheel event structure (event.wheel.*) */ typedef struct SDL_MouseWheelEvent { @@ -338,7 +338,7 @@ typedef struct SDL_MouseWheelEvent } SDL_MouseWheelEvent; /** - * \brief Joystick axis motion event structure (event.jaxis.*) + * Joystick axis motion event structure (event.jaxis.*) */ typedef struct SDL_JoyAxisEvent { @@ -354,7 +354,7 @@ typedef struct SDL_JoyAxisEvent } SDL_JoyAxisEvent; /** - * \brief Joystick hat position change event structure (event.jhat.*) + * Joystick hat position change event structure (event.jhat.*) */ typedef struct SDL_JoyHatEvent { @@ -374,7 +374,7 @@ typedef struct SDL_JoyHatEvent } SDL_JoyHatEvent; /** - * \brief Joystick button event structure (event.jbutton.*) + * Joystick button event structure (event.jbutton.*) */ typedef struct SDL_JoyButtonEvent { @@ -388,7 +388,7 @@ typedef struct SDL_JoyButtonEvent } SDL_JoyButtonEvent; /** - * \brief Joystick device event structure (event.jdevice.*) + * Joystick device event structure (event.jdevice.*) */ typedef struct SDL_JoyDeviceEvent { @@ -398,7 +398,7 @@ typedef struct SDL_JoyDeviceEvent } SDL_JoyDeviceEvent; /** - * \brief Joysick battery level change event structure (event.jbattery.*) + * Joysick battery level change event structure (event.jbattery.*) */ typedef struct SDL_JoyBatteryEvent { @@ -409,7 +409,7 @@ typedef struct SDL_JoyBatteryEvent } SDL_JoyBatteryEvent; /** - * \brief Gamepad axis motion event structure (event.gaxis.*) + * Gamepad axis motion event structure (event.gaxis.*) */ typedef struct SDL_GamepadAxisEvent { @@ -426,7 +426,7 @@ typedef struct SDL_GamepadAxisEvent /** - * \brief Gamepad button event structure (event.gbutton.*) + * Gamepad button event structure (event.gbutton.*) */ typedef struct SDL_GamepadButtonEvent { @@ -441,7 +441,7 @@ typedef struct SDL_GamepadButtonEvent /** - * \brief Gamepad device event structure (event.gdevice.*) + * Gamepad device event structure (event.gdevice.*) */ typedef struct SDL_GamepadDeviceEvent { @@ -451,7 +451,7 @@ typedef struct SDL_GamepadDeviceEvent } SDL_GamepadDeviceEvent; /** - * \brief Gamepad touchpad event structure (event.gtouchpad.*) + * Gamepad touchpad event structure (event.gtouchpad.*) */ typedef struct SDL_GamepadTouchpadEvent { @@ -466,7 +466,7 @@ typedef struct SDL_GamepadTouchpadEvent } SDL_GamepadTouchpadEvent; /** - * \brief Gamepad sensor event structure (event.gsensor.*) + * Gamepad sensor event structure (event.gsensor.*) */ typedef struct SDL_GamepadSensorEvent { @@ -479,7 +479,7 @@ typedef struct SDL_GamepadSensorEvent } SDL_GamepadSensorEvent; /** - * \brief Audio device event structure (event.adevice.*) + * Audio device event structure (event.adevice.*) */ typedef struct SDL_AudioDeviceEvent { @@ -494,7 +494,7 @@ typedef struct SDL_AudioDeviceEvent /** - * \brief Touch finger event structure (event.tfinger.*) + * Touch finger event structure (event.tfinger.*) */ typedef struct SDL_TouchFingerEvent { @@ -513,7 +513,7 @@ typedef struct SDL_TouchFingerEvent #define SDL_DROPEVENT_DATA_SIZE 64 /** - * \brief An event used to drop text or request a file open by the system (event.drop.*) + * An event used to drop text or request a file open by the system (event.drop.*) * * The `data` is owned by SDL and should be copied if the application * wants to hold onto it beyond the scope of handling this event. @@ -530,7 +530,7 @@ typedef struct SDL_DropEvent } SDL_DropEvent; /** - * \brief An event triggered when the clipboard contents have changed (event.clipboard.*) + * An event triggered when the clipboard contents have changed (event.clipboard.*) */ typedef struct SDL_ClipboardEvent { @@ -539,7 +539,7 @@ typedef struct SDL_ClipboardEvent } SDL_ClipboardEvent; /** - * \brief Sensor event structure (event.sensor.*) + * Sensor event structure (event.sensor.*) */ typedef struct SDL_SensorEvent { @@ -551,7 +551,7 @@ typedef struct SDL_SensorEvent } SDL_SensorEvent; /** - * \brief The "quit requested" event + * The "quit requested" event */ typedef struct SDL_QuitEvent { @@ -560,7 +560,7 @@ typedef struct SDL_QuitEvent } SDL_QuitEvent; /** - * \brief OS Specific event + * OS Specific event */ typedef struct SDL_OSEvent { @@ -569,7 +569,7 @@ typedef struct SDL_OSEvent } SDL_OSEvent; /** - * \brief A user-defined event type (event.user.*) + * A user-defined event type (event.user.*) */ typedef struct SDL_UserEvent { @@ -586,13 +586,15 @@ struct SDL_SysWMmsg; typedef struct SDL_SysWMmsg SDL_SysWMmsg; /** - * \brief A video driver dependent system event (event.syswm.*) - * This event is disabled by default, you can enable it with SDL_SetEventEnabled() + * A video driver dependent system event (event.syswm.*) * - * The `msg` is owned by SDL and should be copied if the application - * wants to hold onto it beyond the scope of handling this event. + * This event is disabled by default, you can enable it with + * SDL_SetEventEnabled() + * + * The `msg` is owned by SDL and should be copied if the application + * wants to hold onto it beyond the scope of handling this event. * - * \note If you want to use this event, you should include SDL_syswm.h. + * \note If you want to use this event, you should include SDL_syswm.h. */ typedef struct SDL_SysWMEvent { @@ -602,7 +604,7 @@ typedef struct SDL_SysWMEvent } SDL_SysWMEvent; /** - * \brief General event structure + * General event structure */ typedef union SDL_Event { diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index ae8139c1bc67f..996030662ea0e 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -22,7 +22,7 @@ /** * \file SDL_filesystem.h * - * \brief Include file for filesystem SDL API functions + * Include file for filesystem SDL API functions */ #ifndef SDL_filesystem_h_ diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 5f409432d9688..04b27671805da 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -22,7 +22,7 @@ /** * \file SDL_gamepad.h * - * \brief Include file for SDL gamepad event handling + * Include file for SDL gamepad event handling */ #ifndef SDL_gamepad_h_ diff --git a/include/SDL3/SDL_guid.h b/include/SDL3/SDL_guid.h index fbd70143fd070..11f1ffa6c27cf 100644 --- a/include/SDL3/SDL_guid.h +++ b/include/SDL3/SDL_guid.h @@ -22,7 +22,7 @@ /** * \file SDL_guid.h * - * \brief Include file for handling ::SDL_GUID values. + * Include file for handling ::SDL_GUID values. */ #ifndef SDL_guid_h_ diff --git a/include/SDL3/SDL_haptic.h b/include/SDL3/SDL_haptic.h index 7dbd3916a308f..1b336ffb53351 100644 --- a/include/SDL3/SDL_haptic.h +++ b/include/SDL3/SDL_haptic.h @@ -22,8 +22,7 @@ /** * \file SDL_haptic.h * - * \brief The SDL haptic subsystem allows you to control haptic (force feedback) - * devices. + * The SDL haptic subsystem manages haptic (force feedback) devices. * * The basic usage is as follows: * - Initialize the subsystem (::SDL_INIT_HAPTIC). @@ -131,7 +130,7 @@ extern "C" { /** * \typedef SDL_Haptic * - * \brief The haptic structure used to identify an SDL haptic. + * The haptic structure used to identify an SDL haptic. * * \sa SDL_HapticOpen * \sa SDL_HapticOpenFromJoystick @@ -154,7 +153,7 @@ typedef struct SDL_Haptic SDL_Haptic; /* @{ */ /** - * \brief Constant effect supported. + * Constant effect supported. * * Constant haptic effect. * @@ -163,7 +162,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_CONSTANT (1u<<0) /** - * \brief Sine wave effect supported. + * Sine wave effect supported. * * Periodic haptic effect that simulates sine waves. * @@ -172,7 +171,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_SINE (1u<<1) /** - * \brief Left/Right effect supported. + * Left/Right effect supported. * * Haptic effect for direct control over high/low frequency motors. * @@ -186,7 +185,7 @@ typedef struct SDL_Haptic SDL_Haptic; /* #define SDL_HAPTIC_SQUARE (1<<2) */ /** - * \brief Triangle wave effect supported. + * Triangle wave effect supported. * * Periodic haptic effect that simulates triangular waves. * @@ -195,7 +194,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_TRIANGLE (1u<<3) /** - * \brief Sawtoothup wave effect supported. + * Sawtoothup wave effect supported. * * Periodic haptic effect that simulates saw tooth up waves. * @@ -204,7 +203,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_SAWTOOTHUP (1u<<4) /** - * \brief Sawtoothdown wave effect supported. + * Sawtoothdown wave effect supported. * * Periodic haptic effect that simulates saw tooth down waves. * @@ -213,7 +212,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5) /** - * \brief Ramp effect supported. + * Ramp effect supported. * * Ramp haptic effect. * @@ -222,7 +221,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_RAMP (1u<<6) /** - * \brief Spring effect supported - uses axes position. + * Spring effect supported - uses axes position. * * Condition haptic effect that simulates a spring. Effect is based on the * axes position. @@ -232,7 +231,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_SPRING (1u<<7) /** - * \brief Damper effect supported - uses axes velocity. + * Damper effect supported - uses axes velocity. * * Condition haptic effect that simulates dampening. Effect is based on the * axes velocity. @@ -242,7 +241,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_DAMPER (1u<<8) /** - * \brief Inertia effect supported - uses axes acceleration. + * Inertia effect supported - uses axes acceleration. * * Condition haptic effect that simulates inertia. Effect is based on the axes * acceleration. @@ -252,7 +251,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_INERTIA (1u<<9) /** - * \brief Friction effect supported - uses axes movement. + * Friction effect supported - uses axes movement. * * Condition haptic effect that simulates friction. Effect is based on the * axes movement. @@ -262,7 +261,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_FRICTION (1u<<10) /** - * \brief Custom effect is supported. + * Custom effect is supported. * * User defined custom haptic effect. */ @@ -273,7 +272,7 @@ typedef struct SDL_Haptic SDL_Haptic; /* These last few are features the device has, not effects */ /** - * \brief Device can set global gain. + * Device can set global gain. * * Device supports setting the global gain. * @@ -282,7 +281,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_GAIN (1u<<12) /** - * \brief Device can set autocenter. + * Device can set autocenter. * * Device supports setting autocenter. * @@ -291,7 +290,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_AUTOCENTER (1u<<13) /** - * \brief Device can be queried for effect status. + * Device can be queried for effect status. * * Device supports querying effect status. * @@ -300,7 +299,7 @@ typedef struct SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_STATUS (1u<<14) /** - * \brief Device can be paused. + * Device can be paused. * * Devices supports being paused. * @@ -316,31 +315,33 @@ typedef struct SDL_Haptic SDL_Haptic; /* @{ */ /** - * \brief Uses polar coordinates for the direction. + * Uses polar coordinates for the direction. * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_POLAR 0 /** - * \brief Uses cartesian coordinates for the direction. + * Uses cartesian coordinates for the direction. * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_CARTESIAN 1 /** - * \brief Uses spherical coordinates for the direction. + * Uses spherical coordinates for the direction. * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_SPHERICAL 2 /** - * \brief Use this value to play an effect on the steering wheel axis. This - * provides better compatibility across platforms and devices as SDL will guess - * the correct axis. - * \sa SDL_HapticDirection + * Use this value to play an effect on the steering wheel axis. + * + * This provides better compatibility across platforms and devices as SDL + * will guess the correct axis. + * + * \sa SDL_HapticDirection */ #define SDL_HAPTIC_STEERING_AXIS 3 @@ -353,7 +354,7 @@ typedef struct SDL_Haptic SDL_Haptic; */ /** - * \brief Used to play a device an infinite number of times. + * Used to play a device an infinite number of times. * * \sa SDL_HapticRunEffect */ @@ -361,7 +362,7 @@ typedef struct SDL_Haptic SDL_Haptic; /** - * \brief Structure that represents a haptic direction. + * Structure that represents a haptic direction. * * This is the direction where the force comes from, * instead of the direction in which the force is exerted. @@ -464,7 +465,7 @@ typedef struct SDL_HapticDirection /** - * \brief A structure containing a template for a Constant effect. + * A structure containing a template for a Constant effect. * * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect. * @@ -499,7 +500,7 @@ typedef struct SDL_HapticConstant } SDL_HapticConstant; /** - * \brief A structure containing a template for a Periodic effect. + * A structure containing a template for a Periodic effect. * * The struct handles the following effects: * - ::SDL_HAPTIC_SINE @@ -585,7 +586,7 @@ typedef struct SDL_HapticPeriodic } SDL_HapticPeriodic; /** - * \brief A structure containing a template for a Condition effect. + * A structure containing a template for a Condition effect. * * The struct handles the following effects: * - ::SDL_HAPTIC_SPRING: Effect based on axes position. @@ -633,7 +634,7 @@ typedef struct SDL_HapticCondition } SDL_HapticCondition; /** - * \brief A structure containing a template for a Ramp effect. + * A structure containing a template for a Ramp effect. * * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect. * @@ -671,7 +672,7 @@ typedef struct SDL_HapticRamp } SDL_HapticRamp; /** - * \brief A structure containing a template for a Left/Right effect. + * A structure containing a template for a Left/Right effect. * * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect. * @@ -696,7 +697,7 @@ typedef struct SDL_HapticLeftRight } SDL_HapticLeftRight; /** - * \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect. + * A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect. * * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect. * @@ -738,7 +739,7 @@ typedef struct SDL_HapticCustom } SDL_HapticCustom; /** - * \brief The generic template for any haptic effect. + * The generic template for any haptic effect. * * All values max at 32767 (0x7FFF). Signed values also can be negative. * Time values unless specified otherwise are in milliseconds. diff --git a/include/SDL3/SDL_hidapi.h b/include/SDL3/SDL_hidapi.h index 1d7b222456a37..3a1bbace0f53b 100644 --- a/include/SDL3/SDL_hidapi.h +++ b/include/SDL3/SDL_hidapi.h @@ -22,7 +22,7 @@ /** * \file SDL_hidapi.h * - * \brief Header file for SDL HIDAPI functions. + * Header file for SDL HIDAPI functions. * * This is an adaptation of the original HIDAPI interface by Alan Ott, * and includes source code licensed under the following BSD license: @@ -71,13 +71,13 @@ extern "C" { #endif /** - * \brief A handle representing an open HID device + * A handle representing an open HID device */ struct SDL_hid_device_; typedef struct SDL_hid_device_ SDL_hid_device; /**< opaque hidapi structure */ /** - * \brief HID underlying bus types. + * HID underlying bus types. */ typedef enum { /** Unknown bus type */ @@ -109,7 +109,7 @@ typedef enum { /** hidapi info structure */ /** - * \brief Information about a connected HID device + * Information about a connected HID device */ typedef struct SDL_hid_device_info { diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index fd746553ce2c0..a4933ac77bba0 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -22,7 +22,7 @@ /** * \file SDL_hints.h * - * \brief Official documentation for SDL configuration variables + * Official documentation for SDL configuration variables * * This file contains functions to set and get configuration hints, * as well as listing each of them alphabetically. @@ -48,17 +48,16 @@ extern "C" { #endif /** - * \brief A variable controlling whether the Android / iOS built-in - * accelerometer should be listed as a joystick device. + * Set if Android/iOS accelerometers should be listed as joystick devices. * - * This variable can be set to the following values: + * This variable can be set to the following values: * "0" - The accelerometer is not listed as a joystick * "1" - The accelerometer is available as a 3 axis joystick (the default). */ #define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK" /** - * \brief Specify the behavior of Alt+Tab while the keyboard is grabbed. + * Specify the behavior of Alt+Tab while the keyboard is grabbed. * * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed * and your window is full-screen. This prevents the user from getting stuck in @@ -72,7 +71,7 @@ extern "C" { #define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED" /** - * \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it. + * If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it. * This is a debugging aid for developers and not expected to be used by end users. The default is "1" * * This variable can be set to the following values: @@ -82,7 +81,7 @@ extern "C" { #define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST" /** - * \brief A variable to control whether the event loop will block itself when the app is paused. + * A variable to control whether the event loop will block itself when the app is paused. * * The variable can be set to the following values: * "0" - Non blocking. @@ -93,7 +92,7 @@ extern "C" { #define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" /** - * \brief A variable to control whether SDL will pause audio in background + * A variable to control whether SDL will pause audio in background * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking") * * The variable can be set to the following values: @@ -105,7 +104,7 @@ extern "C" { #define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO" /** - * \brief A variable to control whether we trap the Android back button to handle it manually. + * A variable to control whether we trap the Android back button to handle it manually. * This is necessary for the right mouse button to work on some Android devices, or * to be able to trap the back button for use in your code reliably. If set to true, * the back button will show up as an SDL_EVENT_KEY_DOWN / SDL_EVENT_KEY_UP pair with a keycode of @@ -122,7 +121,7 @@ extern "C" { #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" /** - * \brief A variable to control whether SDL activity is allowed to be re-created. + * A variable to control whether SDL activity is allowed to be re-created. * If so, java static datas and static datas from native libraries remain with their current values. * When not allowed, the activity terminates with exit(0) to be fully re-initialized afterward. * @@ -135,7 +134,7 @@ extern "C" { #define SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY "SDL_ANDROID_ALLOW_RECREATE_ACTIVITY" /** - * \brief A variable setting the app ID string. + * A variable setting the app ID string. * This string is used by desktop compositors to identify and group windows * together, as well as match applications with associated desktop settings * and icons. @@ -182,7 +181,7 @@ extern "C" { #define SDL_HINT_APP_ID "SDL_APP_ID" /** - * \brief Specify an application name. + * Specify an application name. * * This hint lets you specify the application name sent to the OS when * required. For example, this will often appear in volume control applets for @@ -202,7 +201,7 @@ extern "C" { #define SDL_HINT_APP_NAME "SDL_APP_NAME" /** - * \brief A variable controlling whether controllers used with the Apple TV + * A variable controlling whether controllers used with the Apple TV * generate UI events. * * When UI events are generated by controller input, the app will be @@ -220,7 +219,7 @@ extern "C" { #define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS" /** - * \brief A variable controlling whether the Apple TV remote's joystick axes + * A variable controlling whether the Apple TV remote's joystick axes * will automatically match the rotation of the remote. * * This variable can be set to the following values: @@ -230,7 +229,7 @@ extern "C" { #define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" /** - * \brief A variable controlling the audio category on iOS and macOS + * A variable controlling the audio category on iOS and macOS * * This variable can be set to the following values: * @@ -243,7 +242,7 @@ extern "C" { #define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" /** - * \brief Specify an application name for an audio device. + * Specify an application name for an audio device. * * Some audio backends (such as PulseAudio) allow you to describe your audio * stream. Among other things, this description might show up in a system @@ -264,7 +263,7 @@ extern "C" { #define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME" /** - * \brief Specify an application name for an audio device. + * Specify an application name for an audio device. * * Some audio backends (such as PulseAudio) allow you to describe your audio * stream. Among other things, this description might show up in a system @@ -285,7 +284,7 @@ extern "C" { #define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME" /** - * \brief Specify an application role for an audio device. + * Specify an application role for an audio device. * * Some audio backends (such as Pipewire) allow you to describe the role of * your audio stream. Among other things, this description might show up in @@ -305,7 +304,7 @@ extern "C" { #define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE" /** - * \brief A variable controlling whether SDL updates joystick state when getting input events + * A variable controlling whether SDL updates joystick state when getting input events * * This variable can be set to the following values: * @@ -317,7 +316,7 @@ extern "C" { #define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS" /** - * \brief A variable controlling whether SDL updates sensor state when getting input events + * A variable controlling whether SDL updates sensor state when getting input events * * This variable can be set to the following values: * @@ -329,7 +328,7 @@ extern "C" { #define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS" /** - * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs. + * Prevent SDL from using version 4 of the bitmap header when saving BMPs. * * The bitmap header version 4 is required for proper alpha channel support and * SDL will use it when required. Should this not be desired, this hint can @@ -348,7 +347,7 @@ extern "C" { #define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" /** - * \brief Override for SDL_GetDisplayUsableBounds() + * Override for SDL_GetDisplayUsableBounds() * * If set, this hint will override the expected results for * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want @@ -362,7 +361,7 @@ extern "C" { #define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS" /** - * \brief Disable giving back control to the browser automatically + * Disable giving back control to the browser automatically * when running with asyncify * * With -s ASYNCIFY, SDL calls emscripten_sleep during operations @@ -377,7 +376,7 @@ extern "C" { #define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY" /** - * \brief Specify the CSS selector used for the "default" window/canvas + * Specify the CSS selector used for the "default" window/canvas * * This hint only applies to the emscripten platform * @@ -386,7 +385,7 @@ extern "C" { #define SDL_HINT_EMSCRIPTEN_CANVAS_SELECTOR "SDL_EMSCRIPTEN_CANVAS_SELECTOR" /** - * \brief override the binding element for keyboard inputs for Emscripten builds + * override the binding element for keyboard inputs for Emscripten builds * * This hint only applies to the emscripten platform * @@ -400,7 +399,7 @@ extern "C" { #define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" /** - * \brief A variable that controls whether the on-screen keyboard should be shown when text input is active + * A variable that controls whether the on-screen keyboard should be shown when text input is active * * The variable can be set to the following values: * "0" - Do not show the on-screen keyboard @@ -411,7 +410,7 @@ extern "C" { #define SDL_HINT_ENABLE_SCREEN_KEYBOARD "SDL_ENABLE_SCREEN_KEYBOARD" /** - * \brief A variable controlling verbosity of the logging of SDL events pushed onto the internal queue. + * A variable controlling verbosity of the logging of SDL events pushed onto the internal queue. * * This variable can be set to the following values, from least to most verbose: * @@ -433,7 +432,7 @@ extern "C" { #define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" /** - * \brief A variable controlling whether raising the window should be done more forcefully + * A variable controlling whether raising the window should be done more forcefully * * This variable can be set to the following values: * "0" - No forcing (the default) @@ -446,7 +445,7 @@ extern "C" { #define SDL_HINT_FORCE_RAISEWINDOW "SDL_HINT_FORCE_RAISEWINDOW" /** -* \brief A variable controlling whether the window is activated when the SDL_RaiseWindow function is called +* A variable controlling whether the window is activated when the SDL_RaiseWindow function is called * * This variable can be set to the following values: * "0" - The window is not activated when the SDL_RaiseWindow function is called @@ -458,7 +457,7 @@ extern "C" { #define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED "SDL_WINDOW_ACTIVATE_WHEN_RAISED" /** - * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface. + * A variable controlling how 3D acceleration is used to accelerate the SDL screen surface. * * SDL can try to accelerate the SDL screen surface by using streaming * textures with a 3D rendering engine. This variable controls whether and @@ -475,7 +474,7 @@ extern "C" { #define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION" /** - * \brief A variable that lets you manually hint extra gamecontroller db entries. + * A variable that lets you manually hint extra gamecontroller db entries. * * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamepad.h * @@ -485,7 +484,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" /** - * \brief A variable that lets you provide a file with extra gamecontroller db entries. + * A variable that lets you provide a file with extra gamecontroller db entries. * * The file should contain lines of gamecontroller config data, see SDL_gamepad.h * @@ -495,7 +494,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" /** - * \brief A variable that overrides the automatic controller type detection + * A variable that overrides the automatic controller type detection * * The variable should be comma separated entries, in the form: VID/PID=type * @@ -514,7 +513,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE" /** - * \brief A variable containing a list of devices to skip when scanning for game controllers. + * A variable containing a list of devices to skip when scanning for game controllers. * * The format of the string is a comma separated list of USB VID/PID pairs * in hexadecimal form, e.g. @@ -527,7 +526,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES" /** - * \brief If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable. + * If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable. * * The format of the string is a comma separated list of USB VID/PID pairs * in hexadecimal form, e.g. @@ -540,7 +539,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT" /** - * \brief If set, game controller face buttons report their values according to their labels instead of their positional layout. + * If set, game controller face buttons report their values according to their labels instead of their positional layout. * * For example, on Nintendo Switch controllers, normally you'd get: * @@ -563,7 +562,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS" /** - * \brief Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. + * Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. * * The variable can be set to the following values: * "0" - Sensor fusion is disabled @@ -582,7 +581,7 @@ extern "C" { #define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION" /** - * \brief A variable controlling whether grabbing input grabs the keyboard + * A variable controlling whether grabbing input grabs the keyboard * * This variable can be set to the following values: * "0" - Grab will affect only the mouse @@ -593,7 +592,7 @@ extern "C" { #define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD" /** - * \brief A variable to control whether SDL_hid_enumerate() enumerates all HID devices or only controllers. + * A variable to control whether SDL_hid_enumerate() enumerates all HID devices or only controllers. * * This variable can be set to the following values: * "0" - SDL_hid_enumerate() will enumerate all HID devices @@ -604,7 +603,7 @@ extern "C" { #define SDL_HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS "SDL_HIDAPI_ENUMERATE_ONLY_CONTROLLERS" /** - * \brief A variable containing a list of devices to ignore in SDL_hid_enumerate() + * A variable containing a list of devices to ignore in SDL_hid_enumerate() * * For example, to ignore the Shanwan DS3 controller and any Valve controller, you might * have the string "0x2563/0x0523,0x28de/0x0000" @@ -612,7 +611,7 @@ extern "C" { #define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES" /** - * \brief A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_EVENT_TEXT_EDITING events. + * A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_EVENT_TEXT_EDITING events. * * The variable can be set to the following values: * "0" - SDL_EVENT_TEXT_EDITING events are sent, and it is the application's @@ -624,7 +623,7 @@ extern "C" { #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" /** - * \brief A variable to control whether certain IMEs should show native UI components (such as the Candidate List) instead of suppressing them. + * A variable to control whether certain IMEs should show native UI components (such as the Candidate List) instead of suppressing them. * * The variable can be set to the following values: * "0" - Native UI components are not display. (default) @@ -633,7 +632,7 @@ extern "C" { #define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI" /** - * \brief A variable controlling whether the home indicator bar on iPhone X + * A variable controlling whether the home indicator bar on iPhone X * should be hidden. * * This variable can be set to the following values: @@ -644,7 +643,7 @@ extern "C" { #define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR" /** - * \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background. + * A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background. * * The variable can be set to the following values: * "0" - Disable joystick & gamecontroller input events when the @@ -657,7 +656,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" /** - * \brief A variable controlling whether the HIDAPI joystick drivers should be used. + * A variable controlling whether the HIDAPI joystick drivers should be used. * * This variable can be set to the following values: * "0" - HIDAPI drivers are not used @@ -668,7 +667,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI" /** - * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -679,7 +678,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE" /** - * \brief A variable controlling whether "low_frequency_rumble" and "high_frequency_rumble" is used to implement + * A variable controlling whether "low_frequency_rumble" and "high_frequency_rumble" is used to implement * the GameCube controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2) * this is useful for applications that need full compatibility for things like ADSR envelopes. * Stop is implemented by setting "low_frequency_rumble" to "0" and "high_frequency_rumble" ">0" @@ -694,7 +693,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE" /** - * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch Joy-Cons should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Switch Joy-Cons should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -705,7 +704,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS" /** - * \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver + * A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver * * This variable can be set to the following values: * "0" - Left and right Joy-Con controllers will not be combined and each will be a mini-gamepad @@ -714,7 +713,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS" /** - * \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver + * A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver * * This variable can be set to the following values: * "0" - Left and right Joy-Con controllers will not be in vertical mode (the default) @@ -725,7 +724,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS" /** - * \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used. + * A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -736,7 +735,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA" /** - * \brief A variable controlling whether the HIDAPI driver for Nintendo Online classic controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Online classic controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -747,7 +746,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC "SDL_JOYSTICK_HIDAPI_NINTENDO_CLASSIC" /** - * \brief A variable controlling whether the HIDAPI driver for NVIDIA SHIELD controllers should be used. + * A variable controlling whether the HIDAPI driver for NVIDIA SHIELD controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -758,7 +757,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_SHIELD "SDL_JOYSTICK_HIDAPI_SHIELD" /** - * \brief A variable controlling whether the HIDAPI driver for PS3 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS3 controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -772,7 +771,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS3 "SDL_JOYSTICK_HIDAPI_PS3" /** - * \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS4 controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -783,7 +782,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4" /** - * \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver. + * A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver. * * This variable can be set to the following values: * "0" - extended reports are not enabled (the default) @@ -803,7 +802,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE" /** - * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS5 controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -814,7 +813,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5" /** - * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller. + * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller. * * This variable can be set to the following values: * "0" - player LEDs are not enabled @@ -823,7 +822,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED" /** - * \brief A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver. + * A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver. * * This variable can be set to the following values: * "0" - extended reports are not enabled (the default) @@ -842,7 +841,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE" /** - * \brief A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used. + * A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -853,7 +852,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA" /** - * \brief A variable controlling whether the HIDAPI driver for Bluetooth Steam Controllers should be used. + * A variable controlling whether the HIDAPI driver for Bluetooth Steam Controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -865,7 +864,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" /** - * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -876,7 +875,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH" /** - * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Pro controller is opened + * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Pro controller is opened * * This variable can be set to the following values: * "0" - home button LED is turned off @@ -887,7 +886,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" /** - * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened + * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened * * This variable can be set to the following values: * "0" - home button LED is turned off @@ -898,7 +897,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED "SDL_JOYSTICK_HIDAPI_JOYCON_HOME_LED" /** - * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Nintendo Switch controller. + * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Nintendo Switch controller. * * This variable can be set to the following values: * "0" - player LEDs are not enabled @@ -907,7 +906,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" /** - * \brief A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -918,7 +917,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_WII "SDL_JOYSTICK_HIDAPI_WII" /** - * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Wii controller. + * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Wii controller. * * This variable can be set to the following values: * "0" - player LEDs are not enabled @@ -927,7 +926,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED" /** - * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -938,7 +937,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX" /** - * \brief A variable controlling whether the HIDAPI driver for XBox 360 controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox 360 controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -949,7 +948,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360" /** - * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with an Xbox 360 controller. + * A variable controlling whether the player LEDs should be lit to indicate which player is associated with an Xbox 360 controller. * * This variable can be set to the following values: * "0" - player LEDs are not enabled @@ -958,7 +957,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED "SDL_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED" /** - * \brief A variable controlling whether the HIDAPI driver for XBox 360 wireless controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox 360 wireless controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -969,7 +968,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS" /** - * \brief A variable controlling whether the HIDAPI driver for XBox One controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox One controllers should be used. * * This variable can be set to the following values: * "0" - HIDAPI driver is not used @@ -980,7 +979,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE "SDL_JOYSTICK_HIDAPI_XBOX_ONE" /** - * \brief A variable controlling whether the Home button LED should be turned on when an Xbox One controller is opened + * A variable controlling whether the Home button LED should be turned on when an Xbox One controller is opened * * This variable can be set to the following values: * "0" - home button LED is turned off @@ -991,7 +990,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" /** - * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. + * A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. * * This variable can be set to the following values: * "0" - RAWINPUT drivers are not used @@ -1000,7 +999,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT" /** - * \brief A variable controlling whether the RAWINPUT driver should pull correlated data from XInput. + * A variable controlling whether the RAWINPUT driver should pull correlated data from XInput. * * This variable can be set to the following values: * "0" - RAWINPUT driver will only use data from raw input APIs @@ -1013,7 +1012,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT" /** - * \brief A variable controlling whether the ROG Chakram mice should show up as joysticks + * A variable controlling whether the ROG Chakram mice should show up as joysticks * * This variable can be set to the following values: * "0" - ROG Chakram mice do not show up as joysticks (the default) @@ -1022,7 +1021,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_ROG_CHAKRAM "SDL_JOYSTICK_ROG_CHAKRAM" /** - * \brief A variable controlling whether a separate thread should be used + * A variable controlling whether a separate thread should be used * for handling joystick detection and raw input messages on Windows * * This variable can be set to the following values: @@ -1033,7 +1032,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" /** - * \brief A variable controlling whether Windows.Gaming.Input should be used for controller handling. + * A variable controlling whether Windows.Gaming.Input should be used for controller handling. * * This variable can be set to the following values: * "0" - WGI is not used @@ -1042,7 +1041,7 @@ extern "C" { #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" /** - * \brief Determines whether SDL enforces that DRM master is required in order + * Determines whether SDL enforces that DRM master is required in order * to initialize the KMSDRM video backend. * * The DRM subsystem has a concept of a "DRM master" which is a DRM client that @@ -1065,14 +1064,14 @@ extern "C" { #define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" /** - * \brief A comma separated list of devices to open as joysticks + * A comma separated list of devices to open as joysticks * * This variable is currently only used by the Linux joystick driver. */ #define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE" /** - * \brief A variable controlling whether joysticks on Linux will always treat 'hat' axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking whether they may be analog. + * A variable controlling whether joysticks on Linux will always treat 'hat' axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking whether they may be analog. * * This variable can be set to the following values: * "0" - Only map hat axis inputs to digital hat outputs if the input axes appear to actually be digital (the default) @@ -1081,7 +1080,7 @@ extern "C" { #define SDL_HINT_LINUX_DIGITAL_HATS "SDL_LINUX_DIGITAL_HATS" /** - * \brief A variable controlling whether digital hats on Linux will apply deadzones to their underlying input axes or use unfiltered values. + * A variable controlling whether digital hats on Linux will apply deadzones to their underlying input axes or use unfiltered values. * * This variable can be set to the following values: * "0" - Return digital hat values based on unfiltered input axis values @@ -1090,7 +1089,7 @@ extern "C" { #define SDL_HINT_LINUX_HAT_DEADZONES "SDL_LINUX_HAT_DEADZONES" /** - * \brief A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux + * A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux * * This variable can be set to the following values: * "0" - Use /dev/input/event* @@ -1101,7 +1100,7 @@ extern "C" { #define SDL_HINT_LINUX_JOYSTICK_CLASSIC "SDL_LINUX_JOYSTICK_CLASSIC" /** - * \brief A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. + * A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. * * This variable can be set to the following values: * "0" - Return unfiltered joystick axis values (the default) @@ -1110,7 +1109,7 @@ extern "C" { #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" /** -* \brief When set don't force the SDL app to become a foreground process +* When set don't force the SDL app to become a foreground process * * This hint only applies to macOS. * @@ -1118,7 +1117,7 @@ extern "C" { #define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP" /** - * \brief A variable that determines whether ctrl+click should generate a right-click event on Mac + * A variable that determines whether ctrl+click should generate a right-click event on Mac * * If present, holding ctrl while left clicking will generate a right click * event when on Mac. @@ -1126,7 +1125,7 @@ extern "C" { #define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK" /** - * \brief A variable controlling whether dispatching OpenGL context updates should block the dispatching thread until the main thread finishes processing + * A variable controlling whether dispatching OpenGL context updates should block the dispatching thread until the main thread finishes processing * * This variable can be set to the following values: * "0" - Dispatching OpenGL context updates will block the dispatching thread until the main thread finishes processing (default). @@ -1144,17 +1143,17 @@ extern "C" { #define SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH "SDL_MAC_OPENGL_ASYNC_DISPATCH" /** - * \brief A variable setting the double click radius, in pixels. + * A variable setting the double click radius, in pixels. */ #define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS" /** - * \brief A variable setting the double click time, in milliseconds. + * A variable setting the double click time, in milliseconds. */ #define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" /** - * \brief Allow mouse click events when clicking to focus an SDL window + * Allow mouse click events when clicking to focus an SDL window * * This variable can be set to the following values: * "0" - Ignore mouse clicks that activate a window @@ -1165,12 +1164,12 @@ extern "C" { #define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH" /** - * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode + * A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode */ #define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE" /** - * \brief A variable controlling whether relative mouse mode constrains the mouse to the center of the window + * A variable controlling whether relative mouse mode constrains the mouse to the center of the window * * This variable can be set to the following values: * "0" - Relative mouse mode constrains the mouse to the window @@ -1186,7 +1185,7 @@ extern "C" { #define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER" /** - * \brief A variable controlling whether relative mouse mode is implemented using mouse warping + * A variable controlling whether relative mouse mode is implemented using mouse warping * * This variable can be set to the following values: * "0" - Relative mouse mode uses raw input @@ -1197,12 +1196,12 @@ extern "C" { #define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP" /** - * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode + * A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode */ #define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" /** - * \brief A variable controlling whether the system mouse acceleration curve is used for relative mouse motion. + * A variable controlling whether the system mouse acceleration curve is used for relative mouse motion. * * This variable can be set to the following values: * "0" - Relative mouse motion will be unscaled (the default) @@ -1213,7 +1212,7 @@ extern "C" { #define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE" /** - * \brief A variable controlling whether a motion event should be generated for mouse warping in relative mode. + * A variable controlling whether a motion event should be generated for mouse warping in relative mode. * * This variable can be set to the following values: * "0" - Warping the mouse will not generate a motion event in relative mode @@ -1224,7 +1223,7 @@ extern "C" { #define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION" /** - * \brief A variable controlling whether mouse events should generate synthetic touch events + * A variable controlling whether mouse events should generate synthetic touch events * * This variable can be set to the following values: * "0" - Mouse events will not generate touch events (default for desktop platforms) @@ -1233,7 +1232,7 @@ extern "C" { #define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" /** - * \brief A variable controlling whether the mouse is captured while mouse buttons are pressed + * A variable controlling whether the mouse is captured while mouse buttons are pressed * * This variable can be set to the following values: * "0" - The mouse is not captured while mouse buttons are pressed @@ -1246,7 +1245,7 @@ extern "C" { #define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE" /** - * \brief Tell SDL not to catch the SIGINT or SIGTERM signals. + * Tell SDL not to catch the SIGINT or SIGTERM signals. * * This hint only applies to Unix-like platforms, and should set before * any calls to SDL_Init() @@ -1259,7 +1258,7 @@ extern "C" { #define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" /** - * \brief A variable controlling what driver to use for OpenGL ES contexts. + * A variable controlling what driver to use for OpenGL ES contexts. * * On some platforms, currently Windows and X11, OpenGL drivers may support * creating contexts with an OpenGL ES profile. By default SDL uses these @@ -1290,7 +1289,7 @@ extern "C" { #define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" /** - * \brief A variable controlling which orientations are allowed on iOS/Android. + * A variable controlling which orientations are allowed on iOS/Android. * * In some circumstances it is necessary to be able to explicitly control * which UI orientations are allowed. @@ -1301,7 +1300,7 @@ extern "C" { #define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" /** - * \brief A variable controlling the use of a sentinel event when polling the event queue + * A variable controlling the use of a sentinel event when polling the event queue * * This variable can be set to the following values: * "0" - Disable poll sentinels @@ -1317,7 +1316,7 @@ extern "C" { #define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL" /** - * \brief Override for SDL_GetPreferredLocales() + * Override for SDL_GetPreferredLocales() * * If set, this will be favored over anything the OS might report for the * user's preferred locales. Changing this hint at runtime will not generate @@ -1331,7 +1330,7 @@ extern "C" { #define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" /** - * \brief A variable describing the content orientation on QtWayland-based platforms. + * A variable describing the content orientation on QtWayland-based platforms. * * On QtWayland platforms, windows are rotated client-side to allow for custom * transitions. In order to correctly position overlays (e.g. volume bar) and @@ -1350,7 +1349,7 @@ extern "C" { #define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION" /** - * \brief Flags to set on QtWayland windows to integrate with the native window manager. + * Flags to set on QtWayland windows to integrate with the native window manager. * * On QtWayland platforms, this hint controls the flags to set on the windows. * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures. @@ -1361,7 +1360,7 @@ extern "C" { #define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS" /** - * \brief A variable controlling whether the 2D render API is compatible or efficient. + * A variable controlling whether the 2D render API is compatible or efficient. * * This variable can be set to the following values: * @@ -1385,7 +1384,7 @@ extern "C" { #define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" /** - * \brief A variable controlling how the 2D render API renders lines + * A variable controlling how the 2D render API renders lines * * This variable can be set to the following values: * "0" - Use the default line drawing method (Bresenham's line algorithm as of SDL 2.0.20) @@ -1398,7 +1397,7 @@ extern "C" { #define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" /** - * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer. + * A variable controlling whether to enable Direct3D 11+'s Debug Layer. * * This variable does not have any effect on the Direct3D 9 based renderer. * @@ -1411,7 +1410,7 @@ extern "C" { #define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" /** - * \brief A variable controlling whether the Direct3D device is initialized for thread-safe operations. + * A variable controlling whether the Direct3D device is initialized for thread-safe operations. * * This variable can be set to the following values: * "0" - Thread-safety is not enabled (faster) @@ -1422,7 +1421,7 @@ extern "C" { #define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE" /** - * \brief A variable specifying which render driver to use. + * A variable specifying which render driver to use. * * If the application doesn't pick a specific renderer to use, this variable * specifies the name of the preferred renderer. If the preferred renderer @@ -1444,7 +1443,7 @@ extern "C" { #define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER" /** - * \brief A variable controlling whether the OpenGL render driver uses shaders if they are available. + * A variable controlling whether the OpenGL render driver uses shaders if they are available. * * This variable can be set to the following values: * "0" - Disable shaders @@ -1455,7 +1454,7 @@ extern "C" { #define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS" /** - * \brief A variable controlling the scaling quality + * A variable controlling the scaling quality * * This variable can be set to the following values: * "0" or "nearest" - Nearest pixel sampling @@ -1467,7 +1466,7 @@ extern "C" { #define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY" /** - * \brief A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing. + * A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing. * * This variable can be set to the following values: * "0" - Disable vsync @@ -1478,7 +1477,7 @@ extern "C" { #define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" /** - * \brief A variable controlling whether the Metal render driver select low power device over default one + * A variable controlling whether the Metal render driver select low power device over default one * * This variable can be set to the following values: * "0" - Use the prefered OS device @@ -1489,7 +1488,7 @@ extern "C" { #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" /** - * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS + * A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS * * This variable can be set to the following values: * "0" - It will be using VSYNC as defined in the main flag. Default @@ -1500,7 +1499,7 @@ extern "C" { #define SDL_HINT_PS2_DYNAMIC_VSYNC "SDL_PS2_DYNAMIC_VSYNC" /** - * \brief A variable to control whether the return key on the soft keyboard + * A variable to control whether the return key on the soft keyboard * should hide the soft keyboard on Android and iOS. * * The variable can be set to the following values: @@ -1512,7 +1511,7 @@ extern "C" { #define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME" /** - * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI + * Tell SDL which Dispmanx layer to use on a Raspberry PI * * Also known as Z-order. The variable can take a negative or positive value. * The default is 10000. @@ -1520,7 +1519,7 @@ extern "C" { #define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER" /** - * \brief Specify an "activity name" for screensaver inhibition. + * Specify an "activity name" for screensaver inhibition. * * Some platforms, notably Linux desktops, list the applications which are * inhibiting the screensaver or other power-saving features. @@ -1540,7 +1539,7 @@ extern "C" { #define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME" /** - * \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime. + * Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime. * * On some platforms, like Linux, a realtime priority thread may be subject to restrictions * that require special handling by the application. This hint exists to let SDL know that @@ -1559,7 +1558,7 @@ extern "C" { #define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL" /** -* \brief A string specifying additional information to use with SDL_SetThreadPriority. +* A string specifying additional information to use with SDL_SetThreadPriority. * * By default SDL_SetThreadPriority will make appropriate system changes in order to * apply a thread priority. For example on systems using pthreads the scheduler policy @@ -1576,7 +1575,7 @@ extern "C" { #define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY" /** -* \brief A string specifying SDL's threads stack size in bytes or "0" for the backend's default size +* A string specifying SDL's threads stack size in bytes or "0" for the backend's default size * * Use this hint in case you need to set SDL's threads stack size to other than the default. * This is specially useful if you build SDL against a non glibc libc library (such as musl) which @@ -1590,7 +1589,7 @@ extern "C" { #define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE" /** - * \brief A variable that controls the timer resolution, in milliseconds. + * A variable that controls the timer resolution, in milliseconds. * * The higher resolution the timer, the more frequently the CPU services * timer interrupts, and the more precise delays are, but this takes up @@ -1606,7 +1605,7 @@ extern "C" { #define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" /** - * \brief A variable controlling whether touch events should generate synthetic mouse events + * A variable controlling whether touch events should generate synthetic mouse events * * This variable can be set to the following values: * "0" - Touch events will not generate mouse events @@ -1617,7 +1616,7 @@ extern "C" { #define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" /** - * \brief A variable controlling which touchpad should generate synthetic mouse events + * A variable controlling which touchpad should generate synthetic mouse events * * This variable can be set to the following values: * "0" - Only front touchpad should generate mouse events. Default @@ -1629,7 +1628,7 @@ extern "C" { #define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE" /** - * \brief A variable controlling whether the Android / tvOS remotes + * A variable controlling whether the Android / tvOS remotes * should be listed as joystick devices, instead of sending keyboard events. * * This variable can be set to the following values: @@ -1639,7 +1638,7 @@ extern "C" { #define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" /** - * \brief A variable controlling whether the screensaver is enabled. + * A variable controlling whether the screensaver is enabled. * * This variable can be set to the following values: * "0" - Disable screensaver @@ -1650,7 +1649,7 @@ extern "C" { #define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" /** - * \brief Tell the video driver that we only want a double buffer. + * Tell the video driver that we only want a double buffer. * * By default, most lowlevel 2D APIs will use a triple buffer scheme that * wastes no CPU time on waiting for vsync after issuing a flip, but @@ -1669,7 +1668,7 @@ extern "C" { #define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER" /** - * \brief If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay. + * If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay. * * This variable can be set to one of the following values: * "0" - Do not fall back to eglGetDisplay @@ -1681,7 +1680,7 @@ extern "C" { #define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_GETDISPLAY_FALLBACK" /** - * \brief A variable controlling whether the graphics context is externally managed. + * A variable controlling whether the graphics context is externally managed. * * This variable can be set to the following values: * "0" - SDL will manage graphics contexts that are attached to windows. @@ -1696,7 +1695,7 @@ extern "C" { #define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT" /** - * \brief A variable that dictates policy for fullscreen Spaces on macOS. + * A variable that dictates policy for fullscreen Spaces on macOS. * * This hint only applies to macOS. * @@ -1713,7 +1712,7 @@ extern "C" { #define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" /** - * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false. + * Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false. * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're * seeing if "true" causes more problems than it solves in modern times. * @@ -1721,7 +1720,7 @@ extern "C" { #define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" /** - * \brief A variable controlling whether the libdecor Wayland backend is allowed to be used. + * A variable controlling whether the libdecor Wayland backend is allowed to be used. * * This variable can be set to the following values: * "0" - libdecor use is disabled. @@ -1732,7 +1731,7 @@ extern "C" { #define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" /** - * \brief A variable controlling whether the libdecor Wayland backend is preferred over native decrations. + * A variable controlling whether the libdecor Wayland backend is preferred over native decrations. * * When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is * available. (Note that, by default, libdecor will use xdg-decoration itself if available). @@ -1746,7 +1745,7 @@ extern "C" { #define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR" /** - * \brief A variable controlling whether video mode emulation is enabled under Wayland. + * A variable controlling whether video mode emulation is enabled under Wayland. * * When this hint is set, a standard set of emulated CVT video modes will be exposed for use by the application. * If it is disabled, the only modes exposed will be the logical desktop size and, in the case of a scaled @@ -1761,7 +1760,7 @@ extern "C" { #define SDL_HINT_VIDEO_WAYLAND_MODE_EMULATION "SDL_VIDEO_WAYLAND_MODE_EMULATION" /** - * \brief A variable controlling how modes with a non-native aspect ratio are displayed under Wayland. + * A variable controlling how modes with a non-native aspect ratio are displayed under Wayland. * * When this hint is set, the requested scaling will be used when displaying fullscreen video modes * that don't match the display's native aspect ratio. This is contingent on compositor viewport support. @@ -1776,7 +1775,7 @@ extern "C" { #define SDL_HINT_VIDEO_WAYLAND_MODE_SCALING "SDL_VIDEO_WAYLAND_MODE_SCALING" /** - * \brief Enable or disable mouse pointer warp emulation, needed by some older games. + * Enable or disable mouse pointer warp emulation, needed by some older games. * * When this hint is set, any SDL will emulate mouse warps using relative mouse mode. * This is required for some older games (such as Source engine games), which warp the @@ -1793,7 +1792,7 @@ extern "C" { #define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" /** -* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p"). +* A variable that is the address of another SDL_Window* (as a hex string formatted with "%p"). * * If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has * SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly @@ -1812,7 +1811,7 @@ extern "C" { #define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT" /** - * \brief When calling SDL_CreateWindowFrom(), make the window compatible with OpenGL. + * When calling SDL_CreateWindowFrom(), make the window compatible with OpenGL. * * This variable can be set to the following values: * "0" - Don't add any graphics flags to the SDL_WindowFlags @@ -1823,7 +1822,7 @@ extern "C" { #define SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL "SDL_VIDEO_FOREIGN_WINDOW_OPENGL" /** - * \brief When calling SDL_CreateWindowFrom(), make the window compatible with Vulkan. + * When calling SDL_CreateWindowFrom(), make the window compatible with Vulkan. * * This variable can be set to the following values: * "0" - Don't add any graphics flags to the SDL_WindowFlags @@ -1834,7 +1833,7 @@ extern "C" { #define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN "SDL_VIDEO_FOREIGN_WINDOW_VULKAN" /** -* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries +* A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries * * SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It * can use two different sets of binaries, those compiled by the user from source @@ -1850,8 +1849,7 @@ extern "C" { #define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" /** - * \brief A variable controlling whether the OpenGL context should be created - * with EGL by default + * Set whether the OpenGL context should be created with EGL by default * * This variable can be set to the following values: * "0" - Use platform-specific GL context creation API (GLX, WGL, CGL, etc) @@ -1862,7 +1860,7 @@ extern "C" { #define SDL_HINT_VIDEO_FORCE_EGL "SDL_VIDEO_FORCE_EGL" /** - * \brief A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used. + * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used. * * This variable can be set to the following values: * "0" - Disable _NET_WM_BYPASS_COMPOSITOR @@ -1874,7 +1872,7 @@ extern "C" { #define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR" /** - * \brief A variable controlling whether the X11 _NET_WM_PING protocol should be supported. + * A variable controlling whether the X11 _NET_WM_PING protocol should be supported. * * This variable can be set to the following values: * "0" - Disable _NET_WM_PING @@ -1888,20 +1886,20 @@ extern "C" { #define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" /** - * \brief A variable forcing the visual ID chosen for new X11 windows + * A variable forcing the visual ID chosen for new X11 windows * */ #define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID" /** - * \brief A variable forcing the scaling factor for X11 windows + * A variable forcing the scaling factor for X11 windows * * This variable can be set to a floating point value in the range 1.0-10.0f */ #define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR" /** - * \brief A variable controlling whether the X11 XRandR extension should be used. + * A variable controlling whether the X11 XRandR extension should be used. * * This variable can be set to the following values: * "0" - Disable XRandR @@ -1912,7 +1910,7 @@ extern "C" { #define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" /** - * \brief Controls how the fact chunk affects the loading of a WAVE file. + * Controls how the fact chunk affects the loading of a WAVE file. * * The fact chunk stores information about the number of samples of a WAVE * file. The Standards Update from Microsoft notes that this value can be used @@ -1939,7 +1937,7 @@ extern "C" { #define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" /** - * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file. + * Controls how the size of the RIFF chunk affects the loading of a WAVE file. * * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE * file) is not always reliable. In case the size is wrong, it's possible to @@ -1960,7 +1958,7 @@ extern "C" { #define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" /** - * \brief Controls how a truncated WAVE file is handled. + * Controls how a truncated WAVE file is handled. * * A WAVE file is considered truncated if any of the chunks are incomplete or * the data chunk size is not a multiple of the block size. By default, SDL @@ -1976,7 +1974,7 @@ extern "C" { #define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" /** - * \brief Tell SDL not to name threads on Windows with the 0x406D1388 Exception. + * Tell SDL not to name threads on Windows with the 0x406D1388 Exception. * The 0x406D1388 Exception is a trick used to inform Visual Studio of a * thread's name, but it tends to cause problems with other debuggers, * and the .NET runtime. Note that SDL 2.0.6 and later will still use @@ -1992,7 +1990,7 @@ extern "C" { #define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING" /** - * \brief Controls whether menus can be opened with their keyboard shortcut (Alt+mnemonic). + * Controls whether menus can be opened with their keyboard shortcut (Alt+mnemonic). * * If the mnemonics are enabled, then menus can be opened by pressing the Alt * key and the corresponding mnemonic (for example, Alt+F opens the File menu). @@ -2014,7 +2012,7 @@ extern "C" { #define SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS "SDL_WINDOWS_ENABLE_MENU_MNEMONICS" /** - * \brief A variable controlling whether the windows message loop is processed by SDL + * A variable controlling whether the windows message loop is processed by SDL * * This variable can be set to the following values: * "0" - The window message loop is not run @@ -2025,7 +2023,7 @@ extern "C" { #define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP" /** - * \brief Force SDL to use Critical Sections for mutexes on Windows. + * Force SDL to use Critical Sections for mutexes on Windows. * On Windows 7 and newer, Slim Reader/Writer Locks are available. * They offer better performance, allocate no kernel resources and * use less memory. SDL will fall back to Critical Sections on older @@ -2039,7 +2037,7 @@ extern "C" { #define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS" /** - * \brief Force SDL to use Kernel Semaphores on Windows. + * Force SDL to use Kernel Semaphores on Windows. * Kernel Semaphores are inter-process and require a context * switch on every interaction. On Windows 8 and newer, the * WaitOnAddress API is available. Using that and atomics to @@ -2055,13 +2053,13 @@ extern "C" { #define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL" /** - * \brief A variable to specify custom icon resource id from RC file on Windows platform + * A variable to specify custom icon resource id from RC file on Windows platform */ #define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" #define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL" /** - * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows. + * Tell SDL not to generate window-close events for Alt+F4 on Windows. * * The variable can be set to the following values: * "0" - SDL will generate a window-close event when it sees Alt+F4. @@ -2070,7 +2068,7 @@ extern "C" { #define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4" /** - * \brief Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9. + * Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9. * Direct3D 9Ex contains changes to state management that can eliminate device * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require * some changes to your application to cope with the new behavior, so this @@ -2090,7 +2088,7 @@ extern "C" { #define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX" /** - * \brief A variable controlling whether the window frame and title bar are interactive when the cursor is hidden + * A variable controlling whether the window frame and title bar are interactive when the cursor is hidden * * This variable can be set to the following values: * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc) @@ -2101,7 +2099,7 @@ extern "C" { #define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN" /** -* \brief A variable controlling whether the window is activated when the SDL_ShowWindow function is called +* A variable controlling whether the window is activated when the SDL_ShowWindow function is called * * This variable can be set to the following values: * "0" - The window is not activated when the SDL_ShowWindow function is called @@ -2111,7 +2109,7 @@ extern "C" { */ #define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN "SDL_WINDOW_ACTIVATE_WHEN_SHOWN" -/** \brief Allows back-button-press events on Windows Phone to be marked as handled +/** Allows back-button-press events on Windows Phone to be marked as handled * * Windows Phone devices typically feature a Back button. When pressed, * the OS will emit back-button-press events, which apps are expected to @@ -2163,7 +2161,7 @@ extern "C" { */ #define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON" -/** \brief Label text for a WinRT app's privacy policy link +/** Label text for a WinRT app's privacy policy link * * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT, * Microsoft mandates that this policy be available via the Windows Settings charm. @@ -2185,7 +2183,7 @@ extern "C" { #define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL" /** - * \brief A URL to a WinRT app's privacy policy + * A URL to a WinRT app's privacy policy * * All network-enabled WinRT apps must make a privacy policy available to its * users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be @@ -2211,7 +2209,7 @@ extern "C" { #define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL" /** - * \brief Mark X11 windows as override-redirect. + * Mark X11 windows as override-redirect. * * If set, this _might_ increase framerate at the expense of the desktop * not working as expected. Override-redirect windows aren't noticed by the @@ -2223,7 +2221,7 @@ extern "C" { #define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" /** - * \brief A variable that lets you disable the detection and use of Xinput gamepad devices + * A variable that lets you disable the detection and use of Xinput gamepad devices * * The variable can be set to the following values: * "0" - Disable XInput detection (only uses direct input) @@ -2232,7 +2230,7 @@ extern "C" { #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" /** - * \brief A variable that lets you disable the detection and use of DirectInput gamepad devices + * A variable that lets you disable the detection and use of DirectInput gamepad devices * * The variable can be set to the following values: * "0" - Disable DirectInput detection (only uses XInput) @@ -2241,7 +2239,7 @@ extern "C" { #define SDL_HINT_DIRECTINPUT_ENABLED "SDL_DIRECTINPUT_ENABLED" /** - * \brief A variable that causes SDL to use the old axis and button mapping for XInput devices. + * A variable that causes SDL to use the old axis and button mapping for XInput devices. * * This hint is for backwards compatibility only and will be removed in SDL 2.1 * @@ -2250,7 +2248,7 @@ extern "C" { #define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING" /** - * \brief A variable that causes SDL to not ignore audio "monitors" + * A variable that causes SDL to not ignore audio "monitors" * * This is currently only used for PulseAudio and ignored elsewhere. * @@ -2269,7 +2267,7 @@ extern "C" { #define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS" /** - * \brief A variable that forces X11 windows to create as a custom type. + * A variable that forces X11 windows to create as a custom type. * * This is currently only used for X11 and ignored elsewhere. * @@ -2289,7 +2287,7 @@ extern "C" { #define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE" /** - * \brief A variable that decides whether to send SDL_EVENT_QUIT when closing the final window. + * A variable that decides whether to send SDL_EVENT_QUIT when closing the final window. * * By default, SDL sends an SDL_EVENT_QUIT event when there is only one window * and it receives an SDL_EVENT_WINDOW_CLOSE_REQUESTED event, under the assumption most @@ -2314,7 +2312,7 @@ extern "C" { /** - * \brief A variable that decides what video backend to use. + * A variable that decides what video backend to use. * * By default, SDL will try all available video backends in a reasonable * order until it finds one that can work, but this hint allows the app @@ -2337,7 +2335,7 @@ extern "C" { #define SDL_HINT_VIDEO_DRIVER "SDL_VIDEO_DRIVER" /** - * \brief A variable that decides what audio backend to use. + * A variable that decides what audio backend to use. * * By default, SDL will try all available audio backends in a reasonable * order until it finds one that can work, but this hint allows the app @@ -2360,7 +2358,7 @@ extern "C" { #define SDL_HINT_AUDIO_DRIVER "SDL_AUDIO_DRIVER" /** - * \brief A variable that decides what KMSDRM device to use. + * A variable that decides what KMSDRM device to use. * * Internally, SDL might open something like "/dev/dri/cardNN" to * access KMSDRM functionality, where "NN" is a device index number. @@ -2375,7 +2373,7 @@ extern "C" { /** - * \brief A variable that treats trackpads as touch devices. + * A variable that treats trackpads as touch devices. * * On macOS (and possibly other platforms in the future), SDL will report * touches on a trackpad as mouse input, which is generally what users @@ -2397,7 +2395,7 @@ extern "C" { /** - * \brief Sets the title of the TextInput window on GDK platforms. + * Sets the title of the TextInput window on GDK platforms. * * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the * standard SDL text input and virtual keyboard capabilities @@ -2416,7 +2414,7 @@ extern "C" { #define SDL_HINT_GDK_TEXTINPUT_TITLE "SDL_GDK_TEXTINPUT_TITLE" /** - * \brief Sets the description of the TextInput window on GDK platforms. + * Sets the description of the TextInput window on GDK platforms. * * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the * standard SDL text input and virtual keyboard capabilities @@ -2435,7 +2433,7 @@ extern "C" { #define SDL_HINT_GDK_TEXTINPUT_DESCRIPTION "SDL_GDK_TEXTINPUT_DESCRIPTION" /** - * \brief Sets the default text of the TextInput window on GDK platforms. + * Sets the default text of the TextInput window on GDK platforms. * * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the * standard SDL text input and virtual keyboard capabilities @@ -2454,7 +2452,7 @@ extern "C" { #define SDL_HINT_GDK_TEXTINPUT_DEFAULT "SDL_GDK_TEXTINPUT_DEFAULT" /** - * \brief Sets the input scope of the TextInput window on GDK platforms. + * Sets the input scope of the TextInput window on GDK platforms. * * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the * standard SDL text input and virtual keyboard capabilities @@ -2477,7 +2475,7 @@ extern "C" { #define SDL_HINT_GDK_TEXTINPUT_SCOPE "SDL_GDK_TEXTINPUT_SCOPE" /** - * \brief Sets the maximum input length of the TextInput window on GDK platforms. + * Sets the maximum input length of the TextInput window on GDK platforms. * * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the * standard SDL text input and virtual keyboard capabilities @@ -2537,7 +2535,7 @@ extern "C" { /** - * \brief An enumeration of hint priorities + * An enumeration of hint priorities */ typedef enum { diff --git a/include/SDL3/SDL_init.h b/include/SDL3/SDL_init.h index 361c653469fa2..ce41eb99b0d9e 100644 --- a/include/SDL3/SDL_init.h +++ b/include/SDL3/SDL_init.h @@ -22,7 +22,7 @@ /** * \file SDL_init.h * - * \brief Init and quit header for the SDL library + * Init and quit header for the SDL library */ #ifndef SDL_init_h_ @@ -39,7 +39,7 @@ extern "C" { /* As of version 0.5, SDL is loaded dynamically into the application */ /** - * \brief Initialization flags for SDL_Init and/or SDL_InitSubSystem + * Initialization flags for SDL_Init and/or SDL_InitSubSystem * * These are the flags which may be passed to SDL_Init(). You should * specify the subsystems which you will be using in your application. diff --git a/include/SDL3/SDL_intrin.h b/include/SDL3/SDL_intrin.h index addda91eecd54..5d276d6ee419e 100644 --- a/include/SDL3/SDL_intrin.h +++ b/include/SDL3/SDL_intrin.h @@ -22,7 +22,7 @@ /** * \file SDL_intrin.h * - * \brief Header file for CPU intrinsics for SDL + * Header file for CPU intrinsics for SDL */ #ifndef SDL_intrin_h_ diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index 7b73537f6414d..efb7d629ed52f 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -22,7 +22,7 @@ /** * \file SDL_joystick.h * - * \brief Include file for SDL joystick event handling + * Include file for SDL joystick event handling * * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in. @@ -359,7 +359,7 @@ typedef struct SDL_VirtualJoystickDesc } SDL_VirtualJoystickDesc; /** - * \brief The current version of the SDL_VirtualJoystickDesc structure + * The current version of the SDL_VirtualJoystickDesc structure */ #define SDL_VIRTUAL_JOYSTICK_DESC_VERSION 1 diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index 5b2df215a7234..d51af2921a2e7 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -22,7 +22,7 @@ /** * \file SDL_keyboard.h * - * \brief Include file for SDL keyboard event handling + * Include file for SDL keyboard event handling */ #ifndef SDL_keyboard_h_ @@ -40,7 +40,7 @@ extern "C" { #endif /** - * \brief The SDL keysym structure, used in key events. + * The SDL keysym structure, used in key events. * * \note If you are looking for translated character input, see the ::SDL_EVENT_TEXT_INPUT event. */ diff --git a/include/SDL3/SDL_keycode.h b/include/SDL3/SDL_keycode.h index 9f4953c01b7df..31899c3f952cf 100644 --- a/include/SDL3/SDL_keycode.h +++ b/include/SDL3/SDL_keycode.h @@ -22,7 +22,7 @@ /** * \file SDL_keycode.h * - * \brief Defines constants which identify keyboard keys and modifiers. + * Defines constants which identify keyboard keys and modifiers. */ #ifndef SDL_keycode_h_ @@ -32,7 +32,7 @@ #include /** - * \brief The SDL virtual key representation. + * The SDL virtual key representation. * * Values of this type are used to represent keyboard keys using the current * layout of the keyboard. These values include Unicode values representing @@ -327,7 +327,7 @@ typedef enum } SDL_KeyCode; /** - * \brief Enumeration of valid key mods (possibly OR'd together). + * Enumeration of valid key mods (possibly OR'd together). */ typedef enum { diff --git a/include/SDL3/SDL_loadso.h b/include/SDL3/SDL_loadso.h index f7ed6d2c3dda6..41439fd2d23d8 100644 --- a/include/SDL3/SDL_loadso.h +++ b/include/SDL3/SDL_loadso.h @@ -22,7 +22,7 @@ /** * \file SDL_loadso.h * - * \brief System dependent library loading routines + * System dependent library loading routines * * Some things to keep in mind: * \li These functions only work on C function names. Other languages may diff --git a/include/SDL3/SDL_locale.h b/include/SDL3/SDL_locale.h index ebf965ec282a2..4e3932ce7f7b4 100644 --- a/include/SDL3/SDL_locale.h +++ b/include/SDL3/SDL_locale.h @@ -22,7 +22,7 @@ /** * \file SDL_locale.h * - * \brief Include file for SDL locale services + * Include file for SDL locale services */ #ifndef SDL_locale_h diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h index d4eb9545fe41c..370c4de2795e0 100644 --- a/include/SDL3/SDL_log.h +++ b/include/SDL3/SDL_log.h @@ -22,7 +22,7 @@ /** * \file SDL_log.h * - * \brief Simple log messages with categories and priorities. + * Simple log messages with categories and priorities. * * By default logs are quiet, but if you're debugging SDL you might want: * @@ -47,14 +47,14 @@ extern "C" { /** - * \brief The maximum size of a log message prior to SDL 2.0.24 + * The maximum size of a log message prior to SDL 2.0.24 * * As of 2.0.24 there is no limit to the length of SDL log messages. */ #define SDL_MAX_LOG_MESSAGE 4096 /** - * \brief The predefined log categories + * The predefined log categories * * By default the application category is enabled at the INFO level, * the assert category is enabled at the WARN level, test is enabled @@ -97,7 +97,7 @@ typedef enum } SDL_LogCategory; /** - * \brief The predefined log priorities + * The predefined log priorities */ typedef enum { diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 424d3deeb8148..05ae074b964ee 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -35,7 +35,7 @@ /** * \file SDL_main.h * - * \brief Redefine main() on some platforms so that it is called by SDL. + * Redefine main() on some platforms so that it is called by SDL. */ #ifndef SDL_MAIN_HANDLED diff --git a/include/SDL3/SDL_metal.h b/include/SDL3/SDL_metal.h index 42ef3c86cb1f7..6568871235fa2 100644 --- a/include/SDL3/SDL_metal.h +++ b/include/SDL3/SDL_metal.h @@ -22,7 +22,7 @@ /** * \file SDL_metal.h * - * \brief Header file for functions to creating Metal layers and views on SDL windows. + * Header file for functions to creating Metal layers and views on SDL windows. */ #ifndef SDL_metal_h_ @@ -37,7 +37,7 @@ extern "C" { #endif /** - * \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS). + * A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS). * * \note This can be cast directly to an NSView or UIView. */ diff --git a/include/SDL3/SDL_misc.h b/include/SDL3/SDL_misc.h index 42426b5291d88..ae1b32de83c67 100644 --- a/include/SDL3/SDL_misc.h +++ b/include/SDL3/SDL_misc.h @@ -22,7 +22,7 @@ /** * \file SDL_misc.h * - * \brief Include file for SDL API functions that don't fit elsewhere. + * Include file for SDL API functions that don't fit elsewhere. */ #ifndef SDL_misc_h_ diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index f20d832eee209..51751df029313 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -22,7 +22,7 @@ /** * \file SDL_mouse.h * - * \brief Include file for SDL mouse event handling. + * Include file for SDL mouse event handling. */ #ifndef SDL_mouse_h_ @@ -43,7 +43,7 @@ typedef Uint32 SDL_MouseID; typedef struct SDL_Cursor SDL_Cursor; /**< Implementation dependent */ /** - * \brief Cursor types for SDL_CreateSystemCursor(). + * Cursor types for SDL_CreateSystemCursor(). */ typedef enum { @@ -63,7 +63,7 @@ typedef enum } SDL_SystemCursor; /** - * \brief Scroll direction types for the Scroll event + * Scroll direction types for the Scroll event */ typedef enum { diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index 6f13eb05d65a5..f0a0e7d96ed58 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -25,7 +25,7 @@ /** * \file SDL_mutex.h * - * \brief Functions to provide thread synchronization primitives. + * Functions to provide thread synchronization primitives. */ #include diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 9eb6994564691..bf5fd2a0a0325 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -22,7 +22,7 @@ /** * \file SDL_oldnames.h * - * \brief Definitions to ease transition from SDL2 code + * Definitions to ease transition from SDL2 code */ #ifndef SDL_oldnames_h_ diff --git a/include/SDL3/SDL_opengl.h b/include/SDL3/SDL_opengl.h index f771f3eaf139d..6eb7c90b9763c 100644 --- a/include/SDL3/SDL_opengl.h +++ b/include/SDL3/SDL_opengl.h @@ -22,7 +22,7 @@ /** * \file SDL_opengl.h * - * \brief This is a simple file to encapsulate the OpenGL API headers. + * This is a simple file to encapsulate the OpenGL API headers. */ /** diff --git a/include/SDL3/SDL_opengles.h b/include/SDL3/SDL_opengles.h index 11f57868fed49..5f50b5385305a 100644 --- a/include/SDL3/SDL_opengles.h +++ b/include/SDL3/SDL_opengles.h @@ -22,7 +22,7 @@ /** * \file SDL_opengles.h * - * \brief This is a simple file to encapsulate the OpenGL ES 1.X API headers. + * This is a simple file to encapsulate the OpenGL ES 1.X API headers. */ #include diff --git a/include/SDL3/SDL_opengles2.h b/include/SDL3/SDL_opengles2.h index eee6162fd0ceb..abbe47b76e2fc 100644 --- a/include/SDL3/SDL_opengles2.h +++ b/include/SDL3/SDL_opengles2.h @@ -22,7 +22,7 @@ /** * \file SDL_opengles2.h * - * \brief This is a simple file to encapsulate the OpenGL ES 2.0 API headers. + * This is a simple file to encapsulate the OpenGL ES 2.0 API headers. */ #include diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 8f7086d9af519..cde70c116face 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -22,7 +22,7 @@ /** * \file SDL_pixels.h * - * \brief Header for the enumerated pixel format definitions. + * Header for the enumerated pixel format definitions. * * SDL's pixel formats have the following naming convention: * diff --git a/include/SDL3/SDL_platform.h b/include/SDL3/SDL_platform.h index c97761562092e..b2171fbbfb1aa 100644 --- a/include/SDL3/SDL_platform.h +++ b/include/SDL3/SDL_platform.h @@ -22,7 +22,7 @@ /** * \file SDL_platform.h * - * \brief Header file for platform functions. + * Header file for platform functions. */ #ifndef SDL_platform_h_ diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h index 565a09437980e..da657bc504aa2 100644 --- a/include/SDL3/SDL_platform_defines.h +++ b/include/SDL3/SDL_platform_defines.h @@ -22,7 +22,7 @@ /** * \file SDL_platform_defines.h * - * \brief Try to get a standard set of platform defines. + * Try to get a standard set of platform defines. */ #ifndef SDL_platform_defines_h_ diff --git a/include/SDL3/SDL_power.h b/include/SDL3/SDL_power.h index db83ccf197bdf..5bb381b90a954 100644 --- a/include/SDL3/SDL_power.h +++ b/include/SDL3/SDL_power.h @@ -25,7 +25,7 @@ /** * \file SDL_power.h * - * \brief Header for the SDL power management routines. + * Header for the SDL power management routines. */ #include diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 9d01c9381ab9c..56356d6b8f5df 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -22,7 +22,7 @@ /** * \file SDL_properties.h * - * \brief Header file for SDL properties. + * Header file for SDL properties. */ #ifndef SDL_properties_h_ diff --git a/include/SDL3/SDL_quit.h b/include/SDL3/SDL_quit.h index 4087e601c0d6b..18ef4142ed241 100644 --- a/include/SDL3/SDL_quit.h +++ b/include/SDL3/SDL_quit.h @@ -22,7 +22,7 @@ /** * \file SDL_quit.h * - * \brief Include file for SDL quit event handling. + * Include file for SDL quit event handling. */ #ifndef SDL_quit_h_ diff --git a/include/SDL3/SDL_rect.h b/include/SDL3/SDL_rect.h index c50f168fe3e1f..1b5ce0410fc93 100644 --- a/include/SDL3/SDL_rect.h +++ b/include/SDL3/SDL_rect.h @@ -22,7 +22,7 @@ /** * \file SDL_rect.h * - * \brief Header file for SDL_rect definition and management functions. + * Header file for SDL_rect definition and management functions. */ #ifndef SDL_rect_h_ diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 57f85fd3d6125..120c3968fd600 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -22,7 +22,7 @@ /** * \file SDL_render.h * - * \brief Header file for SDL 2D rendering functions. + * Header file for SDL 2D rendering functions. * * This API supports the following features: * * single pixel points diff --git a/include/SDL3/SDL_revision.h b/include/SDL3/SDL_revision.h index 67a2a2b70d090..7af451e11090a 100644 --- a/include/SDL3/SDL_revision.h +++ b/include/SDL3/SDL_revision.h @@ -22,7 +22,7 @@ /** * \file SDL_revision.h * - * \brief Header file containing the SDL revision + * Header file containing the SDL revision */ #ifndef SDL_revision_h_ diff --git a/include/SDL3/SDL_scancode.h b/include/SDL3/SDL_scancode.h index 30b0a751cf378..384aa5a48c748 100644 --- a/include/SDL3/SDL_scancode.h +++ b/include/SDL3/SDL_scancode.h @@ -22,7 +22,7 @@ /** * \file SDL_scancode.h * - * \brief Defines keyboard scancodes. + * Defines keyboard scancodes. */ #ifndef SDL_scancode_h_ @@ -31,7 +31,7 @@ #include /** - * \brief The SDL keyboard scancode representation. + * The SDL keyboard scancode representation. * * Values of this type are used to represent keyboard keys, among other places * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h index 3c99f6825435b..9df4e71da2e76 100644 --- a/include/SDL3/SDL_sensor.h +++ b/include/SDL3/SDL_sensor.h @@ -22,7 +22,7 @@ /** * \file SDL_sensor.h * - * \brief Include file for SDL sensor event handling + * Include file for SDL sensor event handling */ #ifndef SDL_sensor_h_ @@ -41,7 +41,7 @@ extern "C" { #endif /** - * \brief SDL_sensor.h + * SDL_sensor.h * * In order to use these functions, SDL_Init() must have been called * with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system diff --git a/include/SDL3/SDL_shape.h b/include/SDL3/SDL_shape.h index 4b7fb661f4372..92d7db7a5cbb4 100644 --- a/include/SDL3/SDL_shape.h +++ b/include/SDL3/SDL_shape.h @@ -36,7 +36,7 @@ extern "C" { /** \file SDL_shape.h * - * \brief Header file for the shaped window API. + * Header file for the shaped window API. */ #define SDL_NONSHAPEABLE_WINDOW -1 @@ -76,32 +76,32 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateShapedWindow(const char *title, in */ extern DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window); -/** \brief An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */ +/** An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */ typedef enum { - /** \brief The default mode, a binarized alpha cutoff of 1. */ + /** The default mode, a binarized alpha cutoff of 1. */ ShapeModeDefault, - /** \brief A binarized alpha cutoff with a given integer value. */ + /** A binarized alpha cutoff with a given integer value. */ ShapeModeBinarizeAlpha, - /** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ + /** A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ ShapeModeReverseBinarizeAlpha, - /** \brief A color key is applied. */ + /** A color key is applied. */ ShapeModeColorKey } WindowShapeMode; #define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha) -/** \brief A union containing parameters for shaped windows. */ +/** A union containing parameters for shaped windows. */ typedef union { - /** \brief A cutoff alpha value for binarization of the window shape's alpha channel. */ + /** A cutoff alpha value for binarization of the window shape's alpha channel. */ Uint8 binarizationCutoff; SDL_Color colorKey; } SDL_WindowShapeParams; -/** \brief A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */ +/** A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */ typedef struct SDL_WindowShapeMode { - /** \brief The mode of these window-shape parameters. */ + /** The mode of these window-shape parameters. */ WindowShapeMode mode; - /** \brief Window-shape parameters. */ + /** Window-shape parameters. */ SDL_WindowShapeParams parameters; } SDL_WindowShapeMode; diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index a660f03befd9d..5d1483cefed6b 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -22,7 +22,7 @@ /** * \file SDL_stdinc.h * - * \brief This is a general header that includes C language support. + * This is a general header that includes C language support. */ #ifndef SDL_stdinc_h_ @@ -123,57 +123,57 @@ char *alloca(); /* @{ */ /** - * \brief A boolean type. + * A boolean type. */ #define SDL_FALSE 0 #define SDL_TRUE 1 typedef unsigned int SDL_bool; /** - * \brief A signed 8-bit integer type. + * A signed 8-bit integer type. */ #define SDL_MAX_SINT8 ((Sint8)0x7F) /* 127 */ #define SDL_MIN_SINT8 ((Sint8)(~0x7F)) /* -128 */ typedef int8_t Sint8; /** - * \brief An unsigned 8-bit integer type. + * An unsigned 8-bit integer type. */ #define SDL_MAX_UINT8 ((Uint8)0xFF) /* 255 */ #define SDL_MIN_UINT8 ((Uint8)0x00) /* 0 */ typedef uint8_t Uint8; /** - * \brief A signed 16-bit integer type. + * A signed 16-bit integer type. */ #define SDL_MAX_SINT16 ((Sint16)0x7FFF) /* 32767 */ #define SDL_MIN_SINT16 ((Sint16)(~0x7FFF)) /* -32768 */ typedef int16_t Sint16; /** - * \brief An unsigned 16-bit integer type. + * An unsigned 16-bit integer type. */ #define SDL_MAX_UINT16 ((Uint16)0xFFFF) /* 65535 */ #define SDL_MIN_UINT16 ((Uint16)0x0000) /* 0 */ typedef uint16_t Uint16; /** - * \brief A signed 32-bit integer type. + * A signed 32-bit integer type. */ #define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) /* 2147483647 */ #define SDL_MIN_SINT32 ((Sint32)(~0x7FFFFFFF)) /* -2147483648 */ typedef int32_t Sint32; /** - * \brief An unsigned 32-bit integer type. + * An unsigned 32-bit integer type. */ #define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu) /* 4294967295 */ #define SDL_MIN_UINT32 ((Uint32)0x00000000) /* 0 */ typedef uint32_t Uint32; /** - * \brief A signed 64-bit integer type. + * A signed 64-bit integer type. */ #define SDL_MAX_SINT64 ((Sint64)0x7FFFFFFFFFFFFFFFll) /* 9223372036854775807 */ #define SDL_MIN_SINT64 ((Sint64)(~0x7FFFFFFFFFFFFFFFll)) /* -9223372036854775808 */ typedef int64_t Sint64; /** - * \brief An unsigned 64-bit integer type. + * An unsigned 64-bit integer type. */ #define SDL_MAX_UINT64 ((Uint64)0xFFFFFFFFFFFFFFFFull) /* 18446744073709551615 */ #define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */ diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 0cbf1eb9755ba..aefb4233844f3 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -22,7 +22,7 @@ /** * \file SDL_surface.h * - * \brief Header file for ::SDL_Surface definition and management functions. + * Header file for ::SDL_Surface definition and management functions. */ #ifndef SDL_surface_h_ @@ -65,7 +65,7 @@ extern "C" { typedef struct SDL_BlitMap SDL_BlitMap; /* this is an opaque type. */ /** - * \brief A collection of pixels used in software blitting. + * A collection of pixels used in software blitting. * * Pixels are arranged in memory in rows, with the top row first. * Each row occupies an amount of memory given by the pitch (sometimes @@ -112,13 +112,13 @@ typedef struct SDL_Surface } SDL_Surface; /** - * \brief The type of function used for surface blitting functions. + * The type of function used for surface blitting functions. */ typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrect, struct SDL_Surface *dst, const SDL_Rect *dstrect); /** - * \brief The formula used for converting between YUV and RGB + * The formula used for converting between YUV and RGB */ typedef enum { diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index a35f688b4a035..f2c822112a788 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -22,7 +22,7 @@ /** * \file SDL_system.h * - * \brief Include file for platform specific SDL API functions + * Include file for platform specific SDL API functions */ #ifndef SDL_system_h_ @@ -475,44 +475,44 @@ extern DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); #ifdef __WINRT__ /** - * \brief WinRT / Windows Phone path types + * WinRT / Windows Phone path types */ typedef enum { - /** \brief The installed app's root directory. + /** The installed app's root directory. Files here are likely to be read-only. */ SDL_WINRT_PATH_INSTALLED_LOCATION, - /** \brief The app's local data store. Files may be written here */ + /** The app's local data store. Files may be written here */ SDL_WINRT_PATH_LOCAL_FOLDER, - /** \brief The app's roaming data store. Unsupported on Windows Phone. + /** The app's roaming data store. Unsupported on Windows Phone. Files written here may be copied to other machines via a network connection. */ SDL_WINRT_PATH_ROAMING_FOLDER, - /** \brief The app's temporary data store. Unsupported on Windows Phone. + /** The app's temporary data store. Unsupported on Windows Phone. Files written here may be deleted at any time. */ SDL_WINRT_PATH_TEMP_FOLDER } SDL_WinRT_Path; /** - * \brief WinRT Device Family + * WinRT Device Family */ typedef enum { - /** \brief Unknown family */ + /** Unknown family */ SDL_WINRT_DEVICEFAMILY_UNKNOWN, - /** \brief Desktop family*/ + /** Desktop family*/ SDL_WINRT_DEVICEFAMILY_DESKTOP, - /** \brief Mobile family (for example smartphone) */ + /** Mobile family (for example smartphone) */ SDL_WINRT_DEVICEFAMILY_MOBILE, - /** \brief XBox family */ + /** XBox family */ SDL_WINRT_DEVICEFAMILY_XBOX, } SDL_WinRT_DeviceFamily; diff --git a/include/SDL3/SDL_syswm.h b/include/SDL3/SDL_syswm.h index 9cb03d9e46caf..cefe98077c9a8 100644 --- a/include/SDL3/SDL_syswm.h +++ b/include/SDL3/SDL_syswm.h @@ -22,7 +22,7 @@ /** * \file SDL_syswm.h * - * \brief Include file for SDL custom system window manager hooks. + * Include file for SDL custom system window manager hooks. */ #ifndef SDL_syswm_h_ @@ -34,7 +34,7 @@ #include /** - * \brief SDL_syswm.h + * SDL_syswm.h * * Your application has access to a special type of event ::SDL_EVENT_SYSWM, * which contains window-manager specific information and arrives whenever diff --git a/include/SDL3/SDL_test.h b/include/SDL3/SDL_test.h index d66d26b0b3987..3e51601dd7f75 100644 --- a/include/SDL3/SDL_test.h +++ b/include/SDL3/SDL_test.h @@ -22,7 +22,7 @@ /** * \file SDL_test.h * - * \brief Include file for SDL test framework. + * Include file for SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ diff --git a/include/SDL3/SDL_test_assert.h b/include/SDL3/SDL_test_assert.h index b140c9d91ff87..329367ea2eba9 100644 --- a/include/SDL3/SDL_test_assert.h +++ b/include/SDL3/SDL_test_assert.h @@ -22,7 +22,7 @@ /** * \file SDL_test_assert.h * - * \brief Assertion functions of SDL test framework. + * Assertion functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -43,17 +43,17 @@ extern "C" { #endif /** - * \brief Fails the assert. + * Fails the assert. */ #define ASSERT_FAIL 0 /** - * \brief Passes the assert. + * Passes the assert. */ #define ASSERT_PASS 1 /** - * \brief Assert that logs and break execution flow on failures. + * Assert that logs and break execution flow on failures. * * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertDescription Message to log with the assert describing it. @@ -61,7 +61,7 @@ extern "C" { void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters. + * Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters. * * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertDescription Message to log with the assert describing it. @@ -71,25 +71,25 @@ void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *as int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Explicitly pass without checking an assertion condition. Updates assertion counter. + * Explicitly pass without checking an assertion condition. Updates assertion counter. * * \param assertDescription Message to log with the assert describing it. */ void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1); /** - * \brief Resets the assert summary counters to zero. + * Resets the assert summary counters to zero. */ void SDLTest_ResetAssertSummary(void); /** - * \brief Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR. + * Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR. */ void SDLTest_LogAssertSummary(void); /** - * \brief Converts the current assert summary state to a test result. + * Converts the current assert summary state to a test result. * * \returns TEST_RESULT_PASSED, TEST_RESULT_FAILED, or TEST_RESULT_NO_ASSERT */ diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index f194a42b5c392..c54a20084662b 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -22,7 +22,7 @@ /** * \file SDL_test_common.h * - * \brief Common functions of SDL test framework. + * Common functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -139,7 +139,7 @@ extern "C" { /* Function prototypes */ /** - * \brief Parse command line parameters and create common state. + * Parse command line parameters and create common state. * * \param argv Array of command line parameters * \param flags Flags indicating which subsystem to initialize (i.e. SDL_INIT_VIDEO | SDL_INIT_AUDIO) @@ -149,14 +149,14 @@ extern "C" { SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); /** - * \brief Free the common state object. + * Free the common state object. * * \param state The common state object to destroy */ void SDLTest_CommonDestroyState(SDLTest_CommonState *state); /** - * \brief Process one common argument. + * Process one common argument. * * \param state The common state describing the test window to create. * \param index The index of the argument to process in argv[]. @@ -167,7 +167,7 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index); /** - * \brief Logs command line usage info. + * Logs command line usage info. * * This logs the appropriate command line options for the subsystems in use * plus other common options, and then any application-specific options. @@ -181,7 +181,7 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index); void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options); /** - * \brief Open test window. + * Open test window. * * \param state The common state describing the test window to create. * @@ -190,7 +190,7 @@ void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state); /** - * \brief Easy argument handling when test app doesn't need any custom args. + * Easy argument handling when test app doesn't need any custom args. * * \param state The common state describing the test window to create. * \param argc argc, as supplied to SDL_main @@ -223,7 +223,7 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event); /** - * \brief Close test window. + * Close test window. * * \param state The common state used to create test window. * @@ -231,7 +231,7 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event void SDLTest_CommonQuit(SDLTest_CommonState *state); /** - * \brief Draws various window information (position, size, etc.) to the renderer. + * Draws various window information (position, size, etc.) to the renderer. * * \param renderer The renderer to draw to. * \param window The window whose information should be displayed. diff --git a/include/SDL3/SDL_test_compare.h b/include/SDL3/SDL_test_compare.h index f3ac606c3f9f7..985fd8ec8b06c 100644 --- a/include/SDL3/SDL_test_compare.h +++ b/include/SDL3/SDL_test_compare.h @@ -22,7 +22,7 @@ /** * \file SDL_test_compare.h * - * \brief Comparison function of SDL test framework. + * Comparison function of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -45,7 +45,7 @@ extern "C" { #endif /** - * \brief Retrieves a single pixel from a surface. + * Retrieves a single pixel from a surface. * * This function prioritizes correctness over speed: it is suitable for * unit tests, but is not intended for use in a game engine. @@ -66,7 +66,7 @@ extern "C" { int SDLTest_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /** - * \brief Compares a surface and with reference image data for equality + * Compares a surface and with reference image data for equality * * \param surface Surface used in comparison * \param referenceSurface Test Surface used in comparison diff --git a/include/SDL3/SDL_test_crc32.h b/include/SDL3/SDL_test_crc32.h index 8d7f2651fa955..fc91673d0b67d 100644 --- a/include/SDL3/SDL_test_crc32.h +++ b/include/SDL3/SDL_test_crc32.h @@ -22,7 +22,7 @@ /** * \file SDL_test_crc32.h * - * \brief CRC32 functions of SDL test framework. + * CRC32 functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -70,7 +70,7 @@ extern "C" { /* ---------- Function Prototypes ------------- */ /** - * \brief Initialize the CRC context + * Initialize the CRC context * * Note: The function initializes the crc table required for all crc calculations. * @@ -83,7 +83,7 @@ extern "C" { /** - * \brief calculate a crc32 from a data block + * calculate a crc32 from a data block * * \param crcContext pointer to context variable * \param inBuf input buffer to checksum @@ -102,7 +102,7 @@ int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, C /** - * \brief clean up CRC context + * clean up CRC context * * \param crcContext pointer to context variable * diff --git a/include/SDL3/SDL_test_font.h b/include/SDL3/SDL_test_font.h index fd6194aaa818c..e7fd3f7248828 100644 --- a/include/SDL3/SDL_test_font.h +++ b/include/SDL3/SDL_test_font.h @@ -22,7 +22,7 @@ /** * \file SDL_test_font.h * - * \brief Font related functions of SDL test framework. + * Font related functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -43,7 +43,7 @@ extern int FONT_CHARACTER_SIZE; #define FONT_LINE_HEIGHT (FONT_CHARACTER_SIZE + 2) /** - * \brief Draw a string in the currently set font. + * Draw a string in the currently set font. * * \param renderer The renderer to draw on. * \param x The X coordinate of the upper left corner of the character. @@ -55,7 +55,7 @@ extern int FONT_CHARACTER_SIZE; int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c); /** - * \brief Draw a UTF-8 string in the currently set font. + * Draw a UTF-8 string in the currently set font. * * The font currently only supports characters in the Basic Latin and Latin-1 Supplement sets. * @@ -69,7 +69,7 @@ int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c); int SDLTest_DrawString(SDL_Renderer *renderer, float x, float y, const char *s); /** - * \brief Data used for multi-line text output + * Data used for multi-line text output */ typedef struct SDLTest_TextWindow { @@ -80,7 +80,7 @@ typedef struct SDLTest_TextWindow } SDLTest_TextWindow; /** - * \brief Create a multi-line text output window + * Create a multi-line text output window * * \param x The X coordinate of the upper left corner of the window. * \param y The Y coordinate of the upper left corner of the window. @@ -94,7 +94,7 @@ typedef struct SDLTest_TextWindow SDLTest_TextWindow *SDLTest_TextWindowCreate(float x, float y, float w, float h); /** - * \brief Display a multi-line text output window + * Display a multi-line text output window * * This function should be called every frame to display the text * @@ -106,7 +106,7 @@ SDLTest_TextWindow *SDLTest_TextWindowCreate(float x, float y, float w, float h) void SDLTest_TextWindowDisplay(SDLTest_TextWindow *textwin, SDL_Renderer *renderer); /** - * \brief Add text to a multi-line text output window + * Add text to a multi-line text output window * * Adds UTF-8 text to the end of the current text. The newline character starts a * new line of text. The backspace character deletes the last character or, if the @@ -121,7 +121,7 @@ void SDLTest_TextWindowDisplay(SDLTest_TextWindow *textwin, SDL_Renderer *render void SDLTest_TextWindowAddText(SDLTest_TextWindow *textwin, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Add text to a multi-line text output window + * Add text to a multi-line text output window * * Adds UTF-8 text to the end of the current text. The newline character starts a * new line of text. The backspace character deletes the last character or, if the @@ -136,7 +136,7 @@ void SDLTest_TextWindowAddText(SDLTest_TextWindow *textwin, SDL_PRINTF_FORMAT_ST void SDLTest_TextWindowAddTextWithLength(SDLTest_TextWindow *textwin, const char *text, size_t len); /** - * \brief Clear the text in a multi-line text output window + * Clear the text in a multi-line text output window * * \param textwin The text output window * @@ -145,7 +145,7 @@ void SDLTest_TextWindowAddTextWithLength(SDLTest_TextWindow *textwin, const char void SDLTest_TextWindowClear(SDLTest_TextWindow *textwin); /** - * \brief Free the storage associated with a multi-line text output window + * Free the storage associated with a multi-line text output window * * \param textwin The text output window * @@ -154,7 +154,7 @@ void SDLTest_TextWindowClear(SDLTest_TextWindow *textwin); void SDLTest_TextWindowDestroy(SDLTest_TextWindow *textwin); /** - * \brief Cleanup textures used by font drawing functions. + * Cleanup textures used by font drawing functions. */ void SDLTest_CleanupTextDrawing(void); diff --git a/include/SDL3/SDL_test_fuzzer.h b/include/SDL3/SDL_test_fuzzer.h index 2cfdbf53fdd3c..c8ddc8b9852a1 100644 --- a/include/SDL3/SDL_test_fuzzer.h +++ b/include/SDL3/SDL_test_fuzzer.h @@ -22,7 +22,7 @@ /** * \file SDL_test_fuzzer.h * - * \brief Fuzzer functions of SDL test framework. + * Fuzzer functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ diff --git a/include/SDL3/SDL_test_harness.h b/include/SDL3/SDL_test_harness.h index c8a7d120b7b2d..45944faafe416 100644 --- a/include/SDL3/SDL_test_harness.h +++ b/include/SDL3/SDL_test_harness.h @@ -22,7 +22,7 @@ /** * \file SDL_test_harness.h * - * \brief Test suite related functions of SDL test framework. + * Test suite related functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -99,7 +99,7 @@ typedef struct SDLTest_TestSuiteReference { /** - * \brief Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z). + * Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z). * * Note: The returned string needs to be deallocated by the caller. * @@ -110,7 +110,7 @@ typedef struct SDLTest_TestSuiteReference { char *SDLTest_GenerateRunSeed(const int length); /** - * \brief Execute a test suite using the given run seed and execution key. + * Execute a test suite using the given run seed and execution key. * * \param testSuites Suites containing the test case. * \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one. diff --git a/include/SDL3/SDL_test_log.h b/include/SDL3/SDL_test_log.h index fa4be923a3684..62db0a865a669 100644 --- a/include/SDL3/SDL_test_log.h +++ b/include/SDL3/SDL_test_log.h @@ -22,7 +22,7 @@ /** * \file SDL_test_log.h * - * \brief Logging related functions of SDL test framework. + * Logging related functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -43,14 +43,14 @@ extern "C" { #endif /** - * \brief Prints given message with a timestamp in the TEST category and INFO priority. + * Prints given message with a timestamp in the TEST category and INFO priority. * * \param fmt Message to be logged */ void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); /** - * \brief Prints given message with a timestamp in the TEST category and the ERROR priority. + * Prints given message with a timestamp in the TEST category and the ERROR priority. * * \param fmt Message to be logged */ diff --git a/include/SDL3/SDL_test_md5.h b/include/SDL3/SDL_test_md5.h index bf680c150bff5..0a4e9f05ea648 100644 --- a/include/SDL3/SDL_test_md5.h +++ b/include/SDL3/SDL_test_md5.h @@ -22,7 +22,7 @@ /** * \file SDL_test_md5.h * - * \brief MD5 related functions of SDL test framework. + * MD5 related functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -78,7 +78,7 @@ extern "C" { /* ---------- Function Prototypes ------------- */ /** - * \brief initialize the context + * initialize the context * * \param mdContext pointer to context variable * @@ -90,7 +90,7 @@ extern "C" { /** - * \brief update digest from variable length data + * update digest from variable length data * * \param mdContext pointer to context variable * \param inBuf pointer to data array/string @@ -106,7 +106,7 @@ extern "C" { /** - * \brief complete digest computation + * complete digest computation * * \param mdContext pointer to context variable * diff --git a/include/SDL3/SDL_test_memory.h b/include/SDL3/SDL_test_memory.h index f2f12881a8a80..fb62b20f09060 100644 --- a/include/SDL3/SDL_test_memory.h +++ b/include/SDL3/SDL_test_memory.h @@ -22,7 +22,7 @@ /** * \file SDL_test_memory.h * - * \brief Memory tracking related functions of SDL test framework. + * Memory tracking related functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -38,21 +38,21 @@ extern "C" { /** - * \brief Start tracking SDL memory allocations + * Start tracking SDL memory allocations * * \note This should be called before any other SDL functions for complete tracking coverage */ void SDLTest_TrackAllocations(void); /** - * \brief Fill allocations with random data + * Fill allocations with random data * * \note This implicitly calls SDLTest_TrackAllocations() */ void SDLTest_RandFillAllocations(); /** - * \brief Print a log of any outstanding allocations + * Print a log of any outstanding allocations * * \note This can be called after SDL_Quit() */ diff --git a/include/SDL3/SDL_test_random.h b/include/SDL3/SDL_test_random.h index 50bc116b33c70..69c75c6a6282f 100644 --- a/include/SDL3/SDL_test_random.h +++ b/include/SDL3/SDL_test_random.h @@ -22,7 +22,7 @@ /** * \file SDL_test_random.h * - * \brief Random number generator related function of SDL test framework. + * Random number generator related function of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. */ @@ -68,7 +68,7 @@ extern "C" { /* --- Function prototypes */ /** - * \brief Initialize random number generator with two integers. + * Initialize random number generator with two integers. * * Note: The random sequence of numbers returned by ...Random() is the * same for the same two integers and has a period of 2^31. @@ -81,7 +81,7 @@ extern "C" { void SDLTest_RandomInit(SDLTest_RandomContext *rndContext, unsigned int xi, unsigned int ci); /** - * \brief Initialize random number generator based on current system time. + * Initialize random number generator based on current system time. * * \param rndContext pointer to context structure * @@ -90,7 +90,7 @@ extern "C" { /** - * \brief Initialize random number generator based on current system time. + * Initialize random number generator based on current system time. * * Note: ...RandomInit() or ...RandomInitTime() must have been called * before using this function. diff --git a/include/SDL3/SDL_thread.h b/include/SDL3/SDL_thread.h index 313dd3fb5f54c..d2979486d17ca 100644 --- a/include/SDL3/SDL_thread.h +++ b/include/SDL3/SDL_thread.h @@ -25,7 +25,7 @@ /** * \file SDL_thread.h * - * \brief Header for the SDL thread management routines. + * Header for the SDL thread management routines. */ #include diff --git a/include/SDL3/SDL_timer.h b/include/SDL3/SDL_timer.h index e8049df8a4725..99c4795c81727 100644 --- a/include/SDL3/SDL_timer.h +++ b/include/SDL3/SDL_timer.h @@ -25,7 +25,7 @@ /** * \file SDL_timer.h * - * \brief Header for the SDL time management routines. + * Header for the SDL time management routines. */ #include diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index c374ba6a87319..fc96305d95e2d 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -22,7 +22,7 @@ /** * \file SDL_touch.h * - * \brief Include file for SDL touch event handling. + * Include file for SDL touch event handling. */ #ifndef SDL_touch_h_ diff --git a/include/SDL3/SDL_version.h b/include/SDL3/SDL_version.h index 0c7a59899b072..4f34f9487c26d 100644 --- a/include/SDL3/SDL_version.h +++ b/include/SDL3/SDL_version.h @@ -22,7 +22,7 @@ /** * \file SDL_version.h * - * \brief This header defines the current SDL version. + * This header defines the current SDL version. */ #ifndef SDL_version_h_ diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 76b78ec9487ff..155adb53723a6 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -22,7 +22,7 @@ /** * \file SDL_video.h * - * \brief Header file for SDL video functions. + * Header file for SDL video functions. */ #ifndef SDL_video_h_ @@ -45,7 +45,7 @@ typedef Uint32 SDL_DisplayID; typedef Uint32 SDL_WindowID; /** - * \brief System theme + * System theme */ typedef enum { @@ -55,7 +55,7 @@ typedef enum } SDL_SystemTheme; /** - * \brief The structure that defines a display mode + * The structure that defines a display mode * * \sa SDL_GetFullscreenDisplayModes() * \sa SDL_GetDesktopDisplayMode() @@ -75,7 +75,7 @@ typedef struct } SDL_DisplayMode; /** - * \brief Display orientation + * Display orientation */ typedef enum { @@ -87,7 +87,7 @@ typedef enum } SDL_DisplayOrientation; /** - * \brief The type used to identify a window + * The type used to identify a window * * \sa SDL_CreateWindow() * \sa SDL_CreateWindowFrom() @@ -122,7 +122,7 @@ typedef enum typedef struct SDL_Window SDL_Window; /** - * \brief The flags on a window + * The flags on a window * * \sa SDL_GetWindowFlags() */ @@ -155,7 +155,7 @@ typedef enum } SDL_WindowFlags; /** - * \brief Used to indicate that you don't care what the window position is. + * Used to indicate that you don't care what the window position is. */ #define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X)) @@ -164,7 +164,7 @@ typedef enum (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK) /** - * \brief Used to indicate that the window position should be centered. + * Used to indicate that the window position should be centered. */ #define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u #define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X)) @@ -173,7 +173,7 @@ typedef enum (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK) /** - * \brief Window flash operation + * Window flash operation */ typedef enum { @@ -183,12 +183,12 @@ typedef enum } SDL_FlashOperation; /** - * \brief An opaque handle to an OpenGL context. + * An opaque handle to an OpenGL context. */ typedef void *SDL_GLContext; /** - * \brief Opaque EGL types. + * Opaque EGL types. */ typedef void *SDL_EGLDisplay; typedef void *SDL_EGLConfig; @@ -197,13 +197,13 @@ typedef intptr_t SDL_EGLAttrib; typedef int SDL_EGLint; /** - * \brief EGL attribute initialization callback types. + * EGL attribute initialization callback types. */ typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void); typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void); /** - * \brief OpenGL configuration attributes + * OpenGL configuration attributes */ typedef enum { diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index baa4eaaf5a37b..3b58efb55f654 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -22,7 +22,7 @@ /** * \file SDL_vulkan.h * - * \brief Header file for functions to creating Vulkan surfaces on SDL windows. + * Header file for functions to creating Vulkan surfaces on SDL windows. */ #ifndef SDL_vulkan_h_ diff --git a/include/build_config/SDL_build_config.h b/include/build_config/SDL_build_config.h index 675feae7f9ae3..138e571f8d945 100644 --- a/include/build_config/SDL_build_config.h +++ b/include/build_config/SDL_build_config.h @@ -27,7 +27,7 @@ /** * \file SDL_build_config.h * - * \brief This is a set of defines to configure the SDL features + * This is a set of defines to configure the SDL features */ /* Add any platform that doesn't build using the configure system. */ diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 32f6486af295a..9347bccafb1bb 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -22,7 +22,7 @@ /** * \file SDL_build_config.h * - * \brief This is a set of defines to configure the SDL features + * This is a set of defines to configure the SDL features */ #ifndef SDL_build_config_h_ diff --git a/include/build_config/SDL_revision.h.cmake b/include/build_config/SDL_revision.h.cmake index b2b96acdaa1c1..17aa1051d6fe9 100644 --- a/include/build_config/SDL_revision.h.cmake +++ b/include/build_config/SDL_revision.h.cmake @@ -22,7 +22,7 @@ /** * \file SDL_revision.h * -* \brief Header file containing the SDL revision. +* Header file containing the SDL revision. */ #ifndef SDL_revision_h_ diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h index 2f44e929452c0..ff6399e40f416 100644 --- a/src/core/linux/SDL_udev.h +++ b/src/core/linux/SDL_udev.h @@ -35,7 +35,7 @@ #include /** - * \brief Device type + * Device type */ typedef enum diff --git a/src/hidapi/doxygen/Doxyfile b/src/hidapi/doxygen/Doxyfile index 4e01360e09ce7..b0bc233d42da6 100644 --- a/src/hidapi/doxygen/Doxyfile +++ b/src/hidapi/doxygen/Doxyfile @@ -214,7 +214,7 @@ JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) +# requiring an explicit command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO diff --git a/src/render/software/SDL_rotate.c b/src/render/software/SDL_rotate.c index 9dddd60604a23..b40330786b567 100644 --- a/src/render/software/SDL_rotate.c +++ b/src/render/software/SDL_rotate.c @@ -44,7 +44,7 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net /* ---- Internally used structures */ /** -\brief A 32 bit RGBA pixel. +A 32 bit RGBA pixel. */ typedef struct tColorRGBA { @@ -55,7 +55,7 @@ typedef struct tColorRGBA } tColorRGBA; /** -\brief A 8bit Y/palette pixel. +A 8bit Y/palette pixel. */ typedef struct tColorY { @@ -63,7 +63,7 @@ typedef struct tColorY } tColorY; /** -\brief Number of guard rows added to destination surfaces. +Number of guard rows added to destination surfaces. This is a simple but effective workaround for observed issues. These rows allocate extra memory and are then hidden from the surface. @@ -75,7 +75,7 @@ to a situation where the program can segfault. #define GUARD_ROWS (2) /** -\brief Returns colorkey info for a surface +Returns colorkey info for a surface */ static Uint32 get_colorkey(SDL_Surface *src) { @@ -100,7 +100,7 @@ static void rotate(double sx, double sy, double sinangle, double cosangle, const } /** -\brief Internal target surface sizing function for rotations with trig result return. +Internal target surface sizing function for rotations with trig result return. \param width The source surface width. \param height The source surface height. @@ -249,7 +249,7 @@ static void transformSurfaceY90(SDL_Surface *src, SDL_Surface *dst, int angle, i #undef TRANSFORM_SURFACE_90 /** -\brief Internal 32 bit rotozoomer with optional anti-aliasing. +Internal 32 bit rotozoomer with optional anti-aliasing. Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface and applying optionally anti-aliasing @@ -391,7 +391,7 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i /** -\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. +Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface. @@ -462,7 +462,7 @@ static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int isin, int } /** -\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. +Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. Rotates a 32-bit or 8-bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees, 'center' the rotation center. If 'smooth' is set diff --git a/src/test/SDL_test_assert.c b/src/test/SDL_test_assert.c index e817dbe9a5194..b0dd71e9f4dcb 100644 --- a/src/test/SDL_test_assert.c +++ b/src/test/SDL_test_assert.c @@ -48,10 +48,10 @@ #define SDLTEST_ASSERT_SUMMARY_FORMAT "Assert Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_RED "Failed=%d" COLOR_END #define SDLTEST_ASSERT_SUMMARY_FORMAT_OK "Assert Summary: Total=%d " COLOR_GREEN "Passed=%d" COLOR_END " " COLOR_GREEN "Failed=%d" COLOR_END -/* ! \brief counts the failed asserts */ +/* ! counts the failed asserts */ static int SDLTest_AssertsFailed = 0; -/* ! \brief counts the passed asserts */ +/* ! counts the passed asserts */ static int SDLTest_AssertsPassed = 0; /* diff --git a/src/test/SDL_test_font.c b/src/test/SDL_test_font.c index 5920558056bc0..41c6adcd80b1c 100644 --- a/src/test/SDL_test_font.c +++ b/src/test/SDL_test_font.c @@ -3122,7 +3122,7 @@ struct SDLTest_CharTextureCache }; /*! -\brief List of per-renderer caches for 8x8 pixel font textures created at runtime. +List of per-renderer caches for 8x8 pixel font textures created at runtime. */ static struct SDLTest_CharTextureCache *SDLTest_CharTextureCacheList; diff --git a/src/test/SDL_test_harness.c b/src/test/SDL_test_harness.c index ffdc593ac7f4e..7414fe8ebfecb 100644 --- a/src/test/SDL_test_harness.c +++ b/src/test/SDL_test_harness.c @@ -47,7 +47,7 @@ /* Final result message format */ #define SDLTEST_FINAL_RESULT_FORMAT COLOR_YELLOW ">>> %s '%s':" COLOR_END " %s\n" -/* ! \brief Timeout for single test case execution */ +/* ! Timeout for single test case execution */ static Uint32 SDLTest_TestCaseTimeout = 3600; /** @@ -167,7 +167,7 @@ static Uint64 SDLTest_GenerateExecKey(const char *runSeed, const char *suiteName } /** - * \brief Set timeout handler for test. + * Set timeout handler for test. * * Note: SDL_Init(SDL_INIT_TIMER) will be called if it wasn't done so before. * @@ -211,7 +211,7 @@ static SDL_TimerID SDLTest_SetTestTimeout(int timeout, void(SDLCALL *callback)(v } /** - * \brief Timeout handler. Aborts test run and exits harness process. + * Timeout handler. Aborts test run and exits harness process. */ #ifdef __WATCOMC__ #pragma aux SDLTest_BailOut aborts; @@ -223,7 +223,7 @@ static SDL_NORETURN void SDLCALL SDLTest_BailOut(void) } /** - * \brief Execute a test using the given execution key. + * Execute a test using the given execution key. * * \param testSuite Suite containing the test case. * \param testCase Case to execute. @@ -356,7 +356,7 @@ static float GetClock(void) } /** - * \brief Execute a test suite using the given run seed and execution key. + * Execute a test suite using the given run seed and execution key. * * The filter string is matched to the suite name (full comparison) to select a single suite, * or if no suite matches, it is matched to the test names (full comparison) to select a single test. diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c index 7ae022684cf1c..71b20ff564c04 100644 --- a/test/testautomation_audio.c +++ b/test/testautomation_audio.c @@ -59,7 +59,7 @@ static SDL_AudioDeviceID g_audio_id = -1; /* Test case functions */ /** - * \brief Stop and restart audio subsystem + * Stop and restart audio subsystem * * \sa SDL_QuitSubSystem * \sa SDL_InitSubSystem @@ -77,7 +77,7 @@ static int audio_quitInitAudioSubSystem(void *arg) } /** - * \brief Start and stop audio directly + * Start and stop audio directly * * \sa SDL_InitAudio * \sa SDL_QuitAudio @@ -133,7 +133,7 @@ static int audio_initQuitAudio(void *arg) } /** - * \brief Start, open, close and stop audio + * Start, open, close and stop audio * * \sa SDL_InitAudio * \sa SDL_OpenAudioDevice @@ -219,7 +219,7 @@ static int audio_initOpenCloseQuitAudio(void *arg) } /** - * \brief Pause and unpause audio + * Pause and unpause audio * * \sa SDL_PauseAudioDevice * \sa SDL_PlayAudioDevice @@ -340,7 +340,7 @@ static int audio_pauseUnpauseAudio(void *arg) } /** - * \brief Enumerate and name available audio devices (output and capture). + * Enumerate and name available audio devices (output and capture). * * \sa SDL_GetNumAudioDevices * \sa SDL_GetAudioDeviceName @@ -381,7 +381,7 @@ static int audio_enumerateAndNameAudioDevices(void *arg) } /** - * \brief Negative tests around enumeration and naming of audio devices. + * Negative tests around enumeration and naming of audio devices. * * \sa SDL_GetNumAudioDevices * \sa SDL_GetAudioDeviceName @@ -392,7 +392,7 @@ static int audio_enumerateAndNameAudioDevicesNegativeTests(void *arg) } /** - * \brief Checks available audio driver names. + * Checks available audio driver names. * * \sa SDL_GetNumAudioDrivers * \sa SDL_GetAudioDriver @@ -423,7 +423,7 @@ static int audio_printAudioDrivers(void *arg) } /** - * \brief Checks current audio driver name with initialized audio. + * Checks current audio driver name with initialized audio. * * \sa SDL_GetCurrentAudioDriver */ @@ -470,7 +470,7 @@ SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32LE_FORMAT, SDL_AUDIO_F32LE == (SDL_AUDIO_BI SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32BE_FORMAT, SDL_AUDIO_F32BE == (SDL_AUDIO_F32LE | SDL_AUDIO_MASK_BIG_ENDIAN)); /** - * \brief Builds various audio conversion structures + * Builds various audio conversion structures * * \sa SDL_CreateAudioStream */ @@ -539,7 +539,7 @@ static int audio_buildAudioStream(void *arg) } /** - * \brief Checks calls with invalid input to SDL_CreateAudioStream + * Checks calls with invalid input to SDL_CreateAudioStream * * \sa SDL_CreateAudioStream */ @@ -619,7 +619,7 @@ static int audio_buildAudioStreamNegative(void *arg) } /** - * \brief Checks current audio status. + * Checks current audio status. * * \sa SDL_GetAudioDeviceStatus */ @@ -629,7 +629,7 @@ static int audio_getAudioStatus(void *arg) } /** - * \brief Opens, checks current audio status, and closes a device. + * Opens, checks current audio status, and closes a device. * * \sa SDL_GetAudioStatus */ @@ -639,7 +639,7 @@ static int audio_openCloseAndGetAudioStatus(void *arg) } /** - * \brief Locks and unlocks open audio device. + * Locks and unlocks open audio device. * * \sa SDL_LockAudioDevice * \sa SDL_UnlockAudioDevice @@ -650,7 +650,7 @@ static int audio_lockUnlockOpenAudioDevice(void *arg) } /** - * \brief Convert audio using various conversion structures + * Convert audio using various conversion structures * * \sa SDL_CreateAudioStream */ @@ -784,7 +784,7 @@ static int audio_convertAudio(void *arg) } /** - * \brief Opens, checks current connected status, and closes a device. + * Opens, checks current connected status, and closes a device. * * \sa SDL_AudioDeviceConnected */ @@ -806,7 +806,7 @@ static double sine_wave_sample(const Sint64 idx, const Sint64 rate, const Sint64 } /** - * \brief Check signal-to-noise ratio and maximum error of audio resampling. + * Check signal-to-noise ratio and maximum error of audio resampling. * * \sa https://wiki.libsdl.org/SDL_CreateAudioStream * \sa https://wiki.libsdl.org/SDL_DestroyAudioStream @@ -963,7 +963,7 @@ static int audio_resampleLoss(void *arg) } /** - * \brief Check accuracy converting between audio formats. + * Check accuracy converting between audio formats. * * \sa SDL_ConvertAudioSamples */ @@ -1098,7 +1098,7 @@ static int audio_convertAccuracy(void *arg) } /** - * \brief Check accuracy when switching between formats + * Check accuracy when switching between formats * * \sa SDL_SetAudioStreamFormat */ diff --git a/test/testautomation_clipboard.c b/test/testautomation_clipboard.c index c0be19684471b..bdc3b52d4904a 100644 --- a/test/testautomation_clipboard.c +++ b/test/testautomation_clipboard.c @@ -74,7 +74,7 @@ static void ClipboardCleanupCallback(void *userdata) /* Test case functions */ /** - * \brief End-to-end test of SDL_xyzClipboardData functions + * End-to-end test of SDL_xyzClipboardData functions * \sa SDL_HasClipboardData * \sa SDL_GetClipboardData * \sa SDL_SetClipboardData @@ -373,7 +373,7 @@ static int clipboard_testClipboardDataFunctions(void *arg) } /** - * \brief End-to-end test of SDL_xyzClipboardText functions + * End-to-end test of SDL_xyzClipboardText functions * \sa SDL_HasClipboardText * \sa SDL_GetClipboardText * \sa SDL_SetClipboardText @@ -457,7 +457,7 @@ static int clipboard_testClipboardTextFunctions(void *arg) } /** - * \brief End-to-end test of SDL_xyzPrimarySelectionText functions + * End-to-end test of SDL_xyzPrimarySelectionText functions * \sa SDL_HasPrimarySelectionText * \sa SDL_GetPrimarySelectionText * \sa SDL_SetPrimarySelectionText diff --git a/test/testautomation_events.c b/test/testautomation_events.c index faa27b644a24a..14418f76ccff2 100644 --- a/test/testautomation_events.c +++ b/test/testautomation_events.c @@ -38,7 +38,7 @@ static int SDLCALL events_sampleNullEventFilter(void *userdata, SDL_Event *event } /** - * \brief Test pumping and peeking events. + * Test pumping and peeking events. * * \sa SDL_PumpEvents * \sa SDL_PollEvent @@ -75,7 +75,7 @@ static int events_pushPumpAndPollUserevent(void *arg) } /** - * \brief Adds and deletes an event watch function with NULL userdata + * Adds and deletes an event watch function with NULL userdata * * \sa SDL_AddEventWatch * \sa SDL_DelEventWatch @@ -125,7 +125,7 @@ static int events_addDelEventWatch(void *arg) } /** - * \brief Adds and deletes an event watch function with userdata + * Adds and deletes an event watch function with userdata * * \sa SDL_AddEventWatch * \sa SDL_DelEventWatch diff --git a/test/testautomation_guid.c b/test/testautomation_guid.c index 1de17566040a0..ff3718a844b8c 100644 --- a/test/testautomation_guid.c +++ b/test/testautomation_guid.c @@ -70,7 +70,7 @@ upper_lower_to_bytestring(Uint8 *out, Uint64 upper, Uint64 lower) /* Test case functions */ /** - * \brief Check String-to-GUID conversion + * Check String-to-GUID conversion * * \sa SDL_GUIDFromString */ @@ -95,7 +95,7 @@ TestGuidFromString(void *arg) } /** - * \brief Check GUID-to-String conversion + * Check GUID-to-String conversion * * \sa SDL_GUIDToString */ diff --git a/test/testautomation_hints.c b/test/testautomation_hints.c index c1244b82b59fe..0a5ec42583042 100644 --- a/test/testautomation_hints.c +++ b/test/testautomation_hints.c @@ -60,7 +60,7 @@ static const int numHintsEnum = SDL_arraysize(HintsEnum); /* Test case functions */ /** - * \brief Call to SDL_GetHint + * Call to SDL_GetHint */ static int hints_getHint(void *arg) { @@ -89,7 +89,7 @@ static void SDLCALL hints_testHintChanged(void *userdata, const char *name, cons } /** - * \brief Call to SDL_SetHint + * Call to SDL_SetHint */ static int hints_setHint(void *arg) { diff --git a/test/testautomation_images.c b/test/testautomation_images.c index 389d70151bd15..753324a82e1a9 100644 --- a/test/testautomation_images.c +++ b/test/testautomation_images.c @@ -528,7 +528,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlit = { }; /** - * \brief Returns the Blit test image as SDL_Surface. + * Returns the Blit test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlit(void) { @@ -1000,7 +1000,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitColor = { }; /** - * \brief Returns the BlitColor test image as SDL_Surface. + * Returns the BlitColor test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitColor(void) { @@ -1635,7 +1635,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitAlpha = { }; /** - * \brief Returns the BlitAlpha test image as SDL_Surface. + * Returns the BlitAlpha test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitAlpha(void) { @@ -2203,7 +2203,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitBlendAdd = { }; /** - * \brief Returns the BlitBlendAdd test image as SDL_Surface. + * Returns the BlitBlendAdd test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitBlendAdd(void) { @@ -2792,7 +2792,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitBlend = { }; /** - * \brief Returns the BlitBlend test image as SDL_Surface. + * Returns the BlitBlend test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitBlend(void) { @@ -3211,7 +3211,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitBlendMod = { }; /** - * \brief Returns the BlitBlendMod test image as SDL_Surface. + * Returns the BlitBlendMod test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitBlendMod(void) { @@ -4013,7 +4013,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitBlendNone = { }; /** - * \brief Returns the BlitBlendNone test image as SDL_Surface. + * Returns the BlitBlendNone test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitBlendNone(void) { @@ -4547,7 +4547,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageBlitBlendAll = { }; /** - * \brief Returns the BlitBlendAll test image as SDL_Surface. + * Returns the BlitBlendAll test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageBlitBlendAll(void) { @@ -4758,7 +4758,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imageFace = { }; /** - * \brief Returns the Face test image as SDL_Surface. + * Returns the Face test image as SDL_Surface. */ SDL_Surface *SDLTest_ImageFace(void) { @@ -5251,7 +5251,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imagePrimitives = { }; /** - * \brief Returns the Primitives test image as SDL_Surface. + * Returns the Primitives test image as SDL_Surface. */ SDL_Surface *SDLTest_ImagePrimitives(void) { @@ -5916,7 +5916,7 @@ static const SDLTest_SurfaceImage_t SDLTest_imagePrimitivesBlend = { }; /** - * \brief Returns the PrimitivesBlend test image as SDL_Surface. + * Returns the PrimitivesBlend test image as SDL_Surface. */ SDL_Surface *SDLTest_ImagePrimitivesBlend(void) { diff --git a/test/testautomation_intrinsics.c b/test/testautomation_intrinsics.c index da4617b6c80f5..566be51cdb770 100644 --- a/test/testautomation_intrinsics.c +++ b/test/testautomation_intrinsics.c @@ -86,7 +86,7 @@ static void free_arrays(void *dest, void *a, void *b) { } /** - * \brief Verify element-wise addition of 2 int arrays. + * Verify element-wise addition of 2 int arrays. */ static void verify_ints_addition(const Sint32 *dest, const Sint32 *a, const Sint32 *b, size_t size, const char *desc) { size_t i; @@ -106,7 +106,7 @@ static void verify_ints_addition(const Sint32 *dest, const Sint32 *a, const Sint } /** - * \brief Verify element-wise multiplication of 2 int arrays. + * Verify element-wise multiplication of 2 int arrays. */ static void verify_ints_multiplication(const Sint32 *dest, const Sint32 *a, const Sint32 *b, size_t size, const char *desc) { size_t i; @@ -126,7 +126,7 @@ static void verify_ints_multiplication(const Sint32 *dest, const Sint32 *a, cons } /** - * \brief Verify element-wise addition of 2 float arrays. + * Verify element-wise addition of 2 float arrays. */ static void verify_floats_addition(const float *dest, const float *a, const float *b, size_t size, const char *desc) { size_t i; @@ -147,7 +147,7 @@ static void verify_floats_addition(const float *dest, const float *a, const floa } /** - * \brief Verify element-wise addition of 2 double arrays. + * Verify element-wise addition of 2 double arrays. */ static void verify_doubles_addition(const double *dest, const double *a, const double *b, size_t size, const char *desc) { size_t i; diff --git a/test/testautomation_joystick.c b/test/testautomation_joystick.c index 54b9b3e486ab5..d1c76831e44ee 100644 --- a/test/testautomation_joystick.c +++ b/test/testautomation_joystick.c @@ -12,7 +12,7 @@ /* Test case functions */ /** - * \brief Check virtual joystick creation + * Check virtual joystick creation * * \sa SDL_AttachVirtualJoystickEx */ diff --git a/test/testautomation_keyboard.c b/test/testautomation_keyboard.c index 5a3d0e900a080..b7a3f19d0e11c 100644 --- a/test/testautomation_keyboard.c +++ b/test/testautomation_keyboard.c @@ -11,7 +11,7 @@ /* Test case functions */ /** - * \brief Check call to SDL_GetKeyboardState with and without numkeys reference. + * Check call to SDL_GetKeyboardState with and without numkeys reference. * * \sa SDL_GetKeyboardState */ @@ -36,7 +36,7 @@ static int keyboard_getKeyboardState(void *arg) } /** - * \brief Check call to SDL_GetKeyboardFocus + * Check call to SDL_GetKeyboardFocus * * \sa SDL_GetKeyboardFocus */ @@ -50,7 +50,7 @@ static int keyboard_getKeyboardFocus(void *arg) } /** - * \brief Check call to SDL_GetKeyFromName for known, unknown and invalid name. + * Check call to SDL_GetKeyFromName for known, unknown and invalid name. * * \sa SDL_GetKeyFromName */ @@ -115,7 +115,7 @@ static void checkInvalidScancodeError(void) } /** - * \brief Check call to SDL_GetKeyFromScancode + * Check call to SDL_GetKeyFromScancode * * \sa SDL_GetKeyFromScancode */ @@ -153,7 +153,7 @@ static int keyboard_getKeyFromScancode(void *arg) } /** - * \brief Check call to SDL_GetKeyName + * Check call to SDL_GetKeyName * * \sa SDL_GetKeyName */ @@ -208,7 +208,7 @@ static int keyboard_getKeyName(void *arg) } /** - * \brief SDL_GetScancodeName negative cases + * SDL_GetScancodeName negative cases * * \sa SDL_GetScancodeName */ @@ -234,7 +234,7 @@ static int keyboard_getScancodeNameNegative(void *arg) } /** - * \brief SDL_GetKeyName negative cases + * SDL_GetKeyName negative cases * * \sa SDL_GetKeyName */ @@ -270,7 +270,7 @@ static int keyboard_getKeyNameNegative(void *arg) } /** - * \brief Check call to SDL_GetModState and SDL_SetModState + * Check call to SDL_GetModState and SDL_SetModState * * \sa SDL_GetModState * \sa SDL_SetModState @@ -329,7 +329,7 @@ static int keyboard_getSetModState(void *arg) } /** - * \brief Check call to SDL_StartTextInput and SDL_StopTextInput + * Check call to SDL_StartTextInput and SDL_StopTextInput * * \sa SDL_StartTextInput * \sa SDL_StopTextInput @@ -375,7 +375,7 @@ static void testSetTextInputRect(SDL_Rect refRect) } /** - * \brief Check call to SDL_SetTextInputRect + * Check call to SDL_SetTextInputRect * * \sa SDL_SetTextInputRect */ @@ -454,7 +454,7 @@ static int keyboard_setTextInputRect(void *arg) } /** - * \brief Check call to SDL_SetTextInputRect with invalid data + * Check call to SDL_SetTextInputRect with invalid data * * \sa SDL_SetTextInputRect */ @@ -491,7 +491,7 @@ static int keyboard_setTextInputRectNegative(void *arg) } /** - * \brief Check call to SDL_GetScancodeFromKey + * Check call to SDL_GetScancodeFromKey * * \sa SDL_GetScancodeFromKey * \sa SDL_Keycode @@ -514,7 +514,7 @@ static int keyboard_getScancodeFromKey(void *arg) } /** - * \brief Check call to SDL_GetScancodeFromName + * Check call to SDL_GetScancodeFromName * * \sa SDL_GetScancodeFromName * \sa SDL_Keycode @@ -585,7 +585,7 @@ static void checkInvalidNameError(void) } /** - * \brief Check call to SDL_GetScancodeFromName with invalid data + * Check call to SDL_GetScancodeFromName with invalid data * * \sa SDL_GetScancodeFromName * \sa SDL_Keycode diff --git a/test/testautomation_main.c b/test/testautomation_main.c index 7c350eda1530c..01276ac3f80d7 100644 --- a/test/testautomation_main.c +++ b/test/testautomation_main.c @@ -11,7 +11,7 @@ #include "testautomation_suites.h" /** - * \brief Tests SDL_InitSubSystem() and SDL_QuitSubSystem() + * Tests SDL_InitSubSystem() and SDL_QuitSubSystem() * \sa SDL_Init * \sa SDL_Quit */ diff --git a/test/testautomation_math.c b/test/testautomation_math.c index 1e922264f3e0c..9d62809d59774 100644 --- a/test/testautomation_math.c +++ b/test/testautomation_math.c @@ -62,7 +62,7 @@ typedef double(SDLCALL *d_to_d_func)(double); typedef double(SDLCALL *dd_to_d_func)(double, double); /** - * \brief Runs all the cases on a given function with a signature double -> double. + * Runs all the cases on a given function with a signature double -> double. * The result is expected to be exact. * * \param func_name a printable name for the tested function. @@ -88,7 +88,7 @@ helper_dtod(const char *func_name, d_to_d_func func, } /** - * \brief Runs all the cases on a given function with a signature double -> double. + * Runs all the cases on a given function with a signature double -> double. * Checks if the result between expected +/- EPSILON. * * \param func_name a printable name for the tested function. @@ -117,7 +117,7 @@ helper_dtod_inexact(const char *func_name, d_to_d_func func, } /** - * \brief Runs all the cases on a given function with a signature + * Runs all the cases on a given function with a signature * (double, double) -> double. The result is expected to be exact. * * \param func_name a printable name for the tested function. @@ -143,7 +143,7 @@ helper_ddtod(const char *func_name, dd_to_d_func func, } /** - * \brief Runs all the cases on a given function with a signature + * Runs all the cases on a given function with a signature * (double, double) -> double. Checks if the result between expected +/- EPSILON. * * \param func_name a printable name for the tested function. @@ -172,7 +172,7 @@ helper_ddtod_inexact(const char *func_name, dd_to_d_func func, } /** - * \brief Runs a range of values on a given function with a signature double -> double + * Runs a range of values on a given function with a signature double -> double * * This function is only meant to test functions that returns the input value if it is * integral: f(x) -> x for x in N. diff --git a/test/testautomation_mouse.c b/test/testautomation_mouse.c index 783f1f294c662..2397b992a581f 100644 --- a/test/testautomation_mouse.c +++ b/test/testautomation_mouse.c @@ -25,7 +25,7 @@ static int mouseStateCheck(Uint32 state) } /** - * \brief Check call to SDL_GetMouseState + * Check call to SDL_GetMouseState * */ static int mouse_getMouseState(void *arg) @@ -70,7 +70,7 @@ static int mouse_getMouseState(void *arg) } /** - * \brief Check call to SDL_GetRelativeMouseState + * Check call to SDL_GetRelativeMouseState * */ static int mouse_getRelativeMouseState(void *arg) @@ -188,7 +188,7 @@ static SDL_Cursor *initArrowCursor(const char *image[]) } /** - * \brief Check call to SDL_CreateCursor and SDL_DestroyCursor + * Check call to SDL_CreateCursor and SDL_DestroyCursor * * \sa SDL_CreateCursor * \sa SDL_DestroyCursor @@ -213,7 +213,7 @@ static int mouse_createFreeCursor(void *arg) } /** - * \brief Check call to SDL_CreateColorCursor and SDL_DestroyCursor + * Check call to SDL_CreateColorCursor and SDL_DestroyCursor * * \sa SDL_CreateColorCursor * \sa SDL_DestroyCursor @@ -269,7 +269,7 @@ static void changeCursorVisibility(SDL_bool state) } /** - * \brief Check call to SDL_ShowCursor + * Check call to SDL_ShowCursor * * \sa SDL_ShowCursor */ @@ -294,7 +294,7 @@ static int mouse_showCursor(void *arg) } /** - * \brief Check call to SDL_SetCursor + * Check call to SDL_SetCursor * * \sa SDL_SetCursor */ @@ -326,7 +326,7 @@ static int mouse_setCursor(void *arg) } /** - * \brief Check call to SDL_GetCursor + * Check call to SDL_GetCursor * * \sa SDL_GetCursor */ @@ -343,7 +343,7 @@ static int mouse_getCursor(void *arg) } /** - * \brief Check call to SDL_GetRelativeMouseMode and SDL_SetRelativeMouseMode + * Check call to SDL_GetRelativeMouseMode and SDL_SetRelativeMouseMode * * \sa SDL_GetRelativeMouseMode * \sa SDL_SetRelativeMouseMode @@ -426,7 +426,7 @@ static void destroyMouseSuiteTestWindow(SDL_Window *window) } /** - * \brief Check call to SDL_WarpMouseInWindow + * Check call to SDL_WarpMouseInWindow * * \sa SDL_WarpMouseInWindow */ @@ -489,7 +489,7 @@ static int mouse_warpMouseInWindow(void *arg) } /** - * \brief Check call to SDL_GetMouseFocus + * Check call to SDL_GetMouseFocus * * \sa SDL_GetMouseFocus */ @@ -555,7 +555,7 @@ static int mouse_getMouseFocus(void *arg) } /** - * \brief Check call to SDL_GetDefaultCursor + * Check call to SDL_GetDefaultCursor * * \sa SDL_GetDefaultCursor */ @@ -572,7 +572,7 @@ static int mouse_getDefaultCursor(void *arg) } /** - * \brief Check call to SDL_GetGlobalMouseState + * Check call to SDL_GetGlobalMouseState * * \sa SDL_GetGlobalMouseState */ diff --git a/test/testautomation_pixels.c b/test/testautomation_pixels.c index f05c9a981398b..62d1b1b5cb5c7 100644 --- a/test/testautomation_pixels.c +++ b/test/testautomation_pixels.c @@ -111,7 +111,7 @@ static const char *g_invalidPixelFormatsVerbose[] = { /* Test case functions */ /** - * \brief Call to SDL_CreatePixelFormat and SDL_DestroyPixelFormat + * Call to SDL_CreatePixelFormat and SDL_DestroyPixelFormat * * \sa SDL_CreatePixelFormat * \sa SDL_DestroyPixelFormat @@ -204,7 +204,7 @@ static int pixels_allocFreeFormat(void *arg) } /** - * \brief Call to SDL_GetPixelFormatName + * Call to SDL_GetPixelFormatName * * \sa SDL_GetPixelFormatName */ @@ -271,7 +271,7 @@ static int pixels_getPixelFormatName(void *arg) } /** - * \brief Call to SDL_CreatePalette and SDL_DestroyPalette + * Call to SDL_CreatePalette and SDL_DestroyPalette * * \sa SDL_CreatePalette * \sa SDL_DestroyPalette diff --git a/test/testautomation_platform.c b/test/testautomation_platform.c index 516c186f084c9..dcb379b8763b8 100644 --- a/test/testautomation_platform.c +++ b/test/testautomation_platform.c @@ -11,7 +11,7 @@ /* Helper functions */ /** - * \brief Compare sizes of types. + * Compare sizes of types. * * @note Watcom C flags these as Warning 201: "Unreachable code" if you just * compare them directly, so we push it through a function to keep the @@ -25,7 +25,7 @@ static int compareSizeOfType(size_t sizeoftype, size_t hardcodetype) /* Test case functions */ /** - * \brief Tests type sizes. + * Tests type sizes. */ static int platform_testTypes(void *arg) { @@ -47,7 +47,7 @@ static int platform_testTypes(void *arg) } /** - * \brief Tests platform endianness and SDL_SwapXY functions. + * Tests platform endianness and SDL_SwapXY functions. */ static int platform_testEndianessAndSwap(void *arg) { @@ -118,7 +118,7 @@ static int platform_testEndianessAndSwap(void *arg) } /** - * \brief Tests SDL_GetXYZ() functions + * Tests SDL_GetXYZ() functions * \sa SDL_GetPlatform * \sa SDL_GetCPUCount * \sa SDL_GetRevision @@ -162,7 +162,7 @@ static int platform_testGetFunctions(void *arg) } /** - * \brief Tests SDL_HasXYZ() functions + * Tests SDL_HasXYZ() functions * \sa SDL_HasAltiVec * \sa SDL_HasMMX * \sa SDL_HasSSE @@ -204,7 +204,7 @@ static int platform_testHasFunctions(void *arg) } /** - * \brief Tests SDL_GetVersion + * Tests SDL_GetVersion * \sa SDL_GetVersion */ static int platform_testGetVersion(void *arg) @@ -227,7 +227,7 @@ static int platform_testGetVersion(void *arg) } /** - * \brief Tests SDL_VERSION macro + * Tests SDL_VERSION macro */ static int platform_testSDLVersion(void *arg) { @@ -249,7 +249,7 @@ static int platform_testSDLVersion(void *arg) } /** - * \brief Tests default SDL_Init + * Tests default SDL_Init */ static int platform_testDefaultInit(void *arg) { @@ -271,7 +271,7 @@ static int platform_testDefaultInit(void *arg) } /** - * \brief Tests SDL_Get/Set/ClearError + * Tests SDL_Get/Set/ClearError * \sa SDL_GetError * \sa SDL_SetError * \sa SDL_ClearError @@ -322,7 +322,7 @@ static int platform_testGetSetClearError(void *arg) } /** - * \brief Tests SDL_SetError with empty input + * Tests SDL_SetError with empty input * \sa SDL_SetError */ static int platform_testSetErrorEmptyInput(void *arg) @@ -363,7 +363,7 @@ static int platform_testSetErrorEmptyInput(void *arg) #endif /** - * \brief Tests SDL_SetError with invalid input + * Tests SDL_SetError with invalid input * \sa SDL_SetError */ static int platform_testSetErrorInvalidInput(void *arg) @@ -446,7 +446,7 @@ static int platform_testSetErrorInvalidInput(void *arg) #endif /** - * \brief Tests SDL_GetPowerInfo + * Tests SDL_GetPowerInfo * \sa SDL_GetPowerInfo */ static int platform_testGetPowerInfo(void *arg) diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index a02edff674b3e..ff49e80247a62 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -9,7 +9,7 @@ /* Test case functions */ /** - * \brief Test basic functionality + * Test basic functionality */ static int properties_testBasic(void *arg) { @@ -54,7 +54,7 @@ static int properties_testBasic(void *arg) } /** - * \brief Test cleanup functionality + * Test cleanup functionality */ static void SDLCALL cleanup(void *userdata, void *value) { @@ -91,7 +91,7 @@ static int properties_testCleanup(void *arg) } /** - * \brief Test locking functionality + * Test locking functionality */ struct properties_thread_data { diff --git a/test/testautomation_rect.c b/test/testautomation_rect.c index ba6ac4720687a..72823a06e90fa 100644 --- a/test/testautomation_rect.c +++ b/test/testautomation_rect.c @@ -11,7 +11,7 @@ /* Helper functions */ /** - * \brief Private helper to check SDL_GetRectAndLineIntersection results + * Private helper to check SDL_GetRectAndLineIntersection results */ static void validateIntersectRectAndLineResults( SDL_bool intersection, SDL_bool expectedIntersection, @@ -38,7 +38,7 @@ static void validateIntersectRectAndLineResults( /* Test case functions */ /** - * \brief Tests SDL_GetRectAndLineIntersection() clipping cases + * Tests SDL_GetRectAndLineIntersection() clipping cases * * \sa SDL_GetRectAndLineIntersection */ @@ -107,7 +107,7 @@ static int rect_testIntersectRectAndLine(void *arg) } /** - * \brief Tests SDL_GetRectAndLineIntersection() non-clipping case line inside + * Tests SDL_GetRectAndLineIntersection() non-clipping case line inside * * \sa SDL_GetRectAndLineIntersection */ @@ -172,7 +172,7 @@ static int rect_testIntersectRectAndLineInside(void *arg) } /** - * \brief Tests SDL_GetRectAndLineIntersection() non-clipping cases outside + * Tests SDL_GetRectAndLineIntersection() non-clipping cases outside * * \sa SDL_GetRectAndLineIntersection */ @@ -225,7 +225,7 @@ static int rect_testIntersectRectAndLineOutside(void *arg) } /** - * \brief Tests SDL_GetRectAndLineIntersection() with empty rectangle + * Tests SDL_GetRectAndLineIntersection() with empty rectangle * * \sa SDL_GetRectAndLineIntersection */ @@ -258,7 +258,7 @@ static int rect_testIntersectRectAndLineEmpty(void *arg) } /** - * \brief Negative tests against SDL_GetRectAndLineIntersection() with invalid parameters + * Negative tests against SDL_GetRectAndLineIntersection() with invalid parameters * * \sa SDL_GetRectAndLineIntersection */ @@ -291,7 +291,7 @@ static int rect_testIntersectRectAndLineParam(void *arg) } /** - * \brief Private helper to check SDL_HasRectIntersection results + * Private helper to check SDL_HasRectIntersection results */ static void validateHasIntersectionResults( SDL_bool intersection, SDL_bool expectedIntersection, @@ -314,7 +314,7 @@ static void validateHasIntersectionResults( } /** - * \brief Private helper to check SDL_GetRectIntersection results + * Private helper to check SDL_GetRectIntersection results */ static void validateIntersectRectResults( SDL_bool intersection, SDL_bool expectedIntersection, @@ -333,7 +333,7 @@ static void validateIntersectRectResults( } /** - * \brief Private helper to check SDL_GetRectUnion results + * Private helper to check SDL_GetRectUnion results */ static void validateUnionRectResults( SDL_Rect *rectA, SDL_Rect *rectB, SDL_Rect *refRectA, SDL_Rect *refRectB, @@ -356,7 +356,7 @@ static void validateUnionRectResults( } /** - * \brief Private helper to check SDL_RectEmpty results + * Private helper to check SDL_RectEmpty results */ static void validateRectEmptyResults( SDL_bool empty, SDL_bool expectedEmpty, @@ -374,7 +374,7 @@ static void validateRectEmptyResults( } /** - * \brief Private helper to check SDL_RectsEqual results + * Private helper to check SDL_RectsEqual results */ static void validateRectEqualsResults( SDL_bool equals, SDL_bool expectedEquals, @@ -397,7 +397,7 @@ static void validateRectEqualsResults( } /** - * \brief Private helper to check SDL_RectsEqualFloat results + * Private helper to check SDL_RectsEqualFloat results */ static void validateFRectEqualsResults( SDL_bool equals, SDL_bool expectedEquals, @@ -423,7 +423,7 @@ static void validateFRectEqualsResults( } /** - * \brief Tests SDL_GetRectIntersection() with B fully inside A + * Tests SDL_GetRectIntersection() with B fully inside A * * \sa SDL_GetRectIntersection */ @@ -450,7 +450,7 @@ static int rect_testIntersectRectInside(void *arg) } /** - * \brief Tests SDL_GetRectIntersection() with B fully outside A + * Tests SDL_GetRectIntersection() with B fully outside A * * \sa SDL_GetRectIntersection */ @@ -477,7 +477,7 @@ static int rect_testIntersectRectOutside(void *arg) } /** - * \brief Tests SDL_GetRectIntersection() with B partially intersecting A + * Tests SDL_GetRectIntersection() with B partially intersecting A * * \sa SDL_GetRectIntersection */ @@ -565,7 +565,7 @@ static int rect_testIntersectRectPartial(void *arg) } /** - * \brief Tests SDL_GetRectIntersection() with 1x1 pixel sized rectangles + * Tests SDL_GetRectIntersection() with 1x1 pixel sized rectangles * * \sa SDL_GetRectIntersection */ @@ -611,7 +611,7 @@ static int rect_testIntersectRectPoint(void *arg) } /** - * \brief Tests SDL_GetRectIntersection() with empty rectangles + * Tests SDL_GetRectIntersection() with empty rectangles * * \sa SDL_GetRectIntersection */ @@ -682,7 +682,7 @@ static int rect_testIntersectRectEmpty(void *arg) } /** - * \brief Negative tests against SDL_GetRectIntersection() with invalid parameters + * Negative tests against SDL_GetRectIntersection() with invalid parameters * * \sa SDL_GetRectIntersection */ @@ -711,7 +711,7 @@ static int rect_testIntersectRectParam(void *arg) } /** - * \brief Tests SDL_HasRectIntersection() with B fully inside A + * Tests SDL_HasRectIntersection() with B fully inside A * * \sa SDL_HasRectIntersection */ @@ -737,7 +737,7 @@ static int rect_testHasIntersectionInside(void *arg) } /** - * \brief Tests SDL_HasRectIntersection() with B fully outside A + * Tests SDL_HasRectIntersection() with B fully outside A * * \sa SDL_HasRectIntersection */ @@ -763,7 +763,7 @@ static int rect_testHasIntersectionOutside(void *arg) } /** - * \brief Tests SDL_HasRectIntersection() with B partially intersecting A + * Tests SDL_HasRectIntersection() with B partially intersecting A * * \sa SDL_HasRectIntersection */ @@ -829,7 +829,7 @@ static int rect_testHasIntersectionPartial(void *arg) } /** - * \brief Tests SDL_HasRectIntersection() with 1x1 pixel sized rectangles + * Tests SDL_HasRectIntersection() with 1x1 pixel sized rectangles * * \sa SDL_HasRectIntersection */ @@ -874,7 +874,7 @@ static int rect_testHasIntersectionPoint(void *arg) } /** - * \brief Tests SDL_HasRectIntersection() with empty rectangles + * Tests SDL_HasRectIntersection() with empty rectangles * * \sa SDL_HasRectIntersection */ @@ -931,7 +931,7 @@ static int rect_testHasIntersectionEmpty(void *arg) } /** - * \brief Negative tests against SDL_HasRectIntersection() with invalid parameters + * Negative tests against SDL_HasRectIntersection() with invalid parameters * * \sa SDL_HasRectIntersection */ @@ -953,7 +953,7 @@ static int rect_testHasIntersectionParam(void *arg) } /** - * \brief Test SDL_GetRectEnclosingPoints() without clipping + * Test SDL_GetRectEnclosingPoints() without clipping * * \sa SDL_GetRectEnclosingPoints */ @@ -1030,7 +1030,7 @@ static int rect_testEnclosePoints(void *arg) } /** - * \brief Test SDL_GetRectEnclosingPoints() with repeated input points + * Test SDL_GetRectEnclosingPoints() with repeated input points * * \sa SDL_GetRectEnclosingPoints */ @@ -1113,7 +1113,7 @@ static int rect_testEnclosePointsRepeatedInput(void *arg) } /** - * \brief Test SDL_GetRectEnclosingPoints() with clipping + * Test SDL_GetRectEnclosingPoints() with clipping * * \sa SDL_GetRectEnclosingPoints */ @@ -1219,7 +1219,7 @@ static int rect_testEnclosePointsWithClipping(void *arg) } /** - * \brief Negative tests against SDL_GetRectEnclosingPoints() with invalid parameters + * Negative tests against SDL_GetRectEnclosingPoints() with invalid parameters * * \sa SDL_GetRectEnclosingPoints */ @@ -1246,7 +1246,7 @@ static int rect_testEnclosePointsParam(void *arg) } /** - * \brief Tests SDL_GetRectUnion() where rect B is outside rect A + * Tests SDL_GetRectUnion() where rect B is outside rect A * * \sa SDL_GetRectUnion */ @@ -1324,7 +1324,7 @@ static int rect_testUnionRectOutside(void *arg) } /** - * \brief Tests SDL_GetRectUnion() where rect A or rect B are empty + * Tests SDL_GetRectUnion() where rect A or rect B are empty * * \sa SDL_GetRectUnion */ @@ -1388,7 +1388,7 @@ static int rect_testUnionRectEmpty(void *arg) } /** - * \brief Tests SDL_GetRectUnion() where rect B is inside rect A + * Tests SDL_GetRectUnion() where rect B is inside rect A * * \sa SDL_GetRectUnion */ @@ -1459,7 +1459,7 @@ static int rect_testUnionRectInside(void *arg) } /** - * \brief Negative tests against SDL_GetRectUnion() with invalid parameters + * Negative tests against SDL_GetRectUnion() with invalid parameters * * \sa SDL_GetRectUnion */ @@ -1486,7 +1486,7 @@ static int rect_testUnionRectParam(void *arg) } /** - * \brief Tests SDL_RectEmpty() with various inputs + * Tests SDL_RectEmpty() with various inputs * * \sa SDL_RectEmpty */ @@ -1528,7 +1528,7 @@ static int rect_testRectEmpty(void *arg) } /** - * \brief Negative tests against SDL_RectEmpty() with invalid parameters + * Negative tests against SDL_RectEmpty() with invalid parameters * * \sa SDL_RectEmpty */ @@ -1544,7 +1544,7 @@ static int rect_testRectEmptyParam(void *arg) } /** - * \brief Tests SDL_RectsEqual() with various inputs + * Tests SDL_RectsEqual() with various inputs * * \sa SDL_RectsEqual */ @@ -1573,7 +1573,7 @@ static int rect_testRectEquals(void *arg) } /** - * \brief Negative tests against SDL_RectsEqual() with invalid parameters + * Negative tests against SDL_RectsEqual() with invalid parameters * * \sa SDL_RectsEqual */ @@ -1605,7 +1605,7 @@ static int rect_testRectEqualsParam(void *arg) } /** - * \brief Tests SDL_RectsEqualFloat() with various inputs + * Tests SDL_RectsEqualFloat() with various inputs * * \sa SDL_RectsEqualFloat */ @@ -1634,7 +1634,7 @@ static int rect_testFRectEquals(void *arg) } /** - * \brief Negative tests against SDL_RectsEqualFloat() with invalid parameters + * Negative tests against SDL_RectsEqualFloat() with invalid parameters * * \sa SDL_RectsEqualFloat */ @@ -1804,7 +1804,7 @@ static const SDLTest_TestCaseReference rectTest31 = { }; /** - * \brief Sequence of Rect test cases; functions that handle simple rectangles including overlaps and merges. + * Sequence of Rect test cases; functions that handle simple rectangles including overlaps and merges. */ static const SDLTest_TestCaseReference *rectTests[] = { &rectTest1, &rectTest2, &rectTest3, &rectTest4, &rectTest5, &rectTest6, &rectTest7, &rectTest8, &rectTest9, &rectTest10, &rectTest11, &rectTest12, &rectTest13, &rectTest14, diff --git a/test/testautomation_render.c b/test/testautomation_render.c index e775ea604fda3..5e7ca3579e4c0 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -90,7 +90,7 @@ static void CleanupDestroyRenderer(void *arg) } /** - * \brief Tests call to SDL_GetNumRenderDrivers + * Tests call to SDL_GetNumRenderDrivers * * \sa SDL_GetNumRenderDrivers */ @@ -103,7 +103,7 @@ static int render_testGetNumRenderDrivers(void *arg) } /** - * \brief Tests the SDL primitives for rendering. + * Tests the SDL primitives for rendering. * * \sa SDL_SetRenderDrawColor * \sa SDL_RenderFillRect @@ -190,7 +190,7 @@ static int render_testPrimitives(void *arg) } /** - * \brief Tests the SDL primitives with alpha for rendering. + * Tests the SDL primitives with alpha for rendering. * * \sa SDL_SetRenderDrawColor * \sa SDL_SetRenderDrawBlendMode @@ -333,7 +333,7 @@ static int render_testPrimitivesBlend(void *arg) } /** - * \brief Tests some blitting routines. + * Tests some blitting routines. * * \sa SDL_RenderTexture * \sa SDL_DestroyTexture @@ -400,7 +400,7 @@ static int render_testBlit(void *arg) } /** - * \brief Blits doing color tests. + * Blits doing color tests. * * \sa SDL_SetTextureColorMod * \sa SDL_RenderTexture @@ -474,7 +474,7 @@ static int render_testBlitColor(void *arg) } /** - * \brief Tests blitting with alpha. + * Tests blitting with alpha. * * \sa SDL_SetTextureAlphaMod * \sa SDL_RenderTexture @@ -551,7 +551,7 @@ static int render_testBlitAlpha(void *arg) } /** - * \brief Tests a blend mode. + * Tests a blend mode. * * \sa SDL_SetTextureBlendMode * \sa SDL_RenderTexture @@ -602,7 +602,7 @@ testBlitBlendMode(SDL_Texture *tface, int mode) } /** - * \brief Tests some more blitting routines. + * Tests some more blitting routines. * * \sa SDL_SetTextureColorMod * \sa SDL_SetTextureAlphaMod @@ -759,7 +759,7 @@ static int render_testBlitBlend(void *arg) } /** - * \brief Test viewport + * Test viewport */ static int render_testViewport(void *arg) { @@ -816,7 +816,7 @@ static int render_testViewport(void *arg) } /** - * \brief Test logical size + * Test logical size */ static int render_testLogicalSize(void *arg) { @@ -926,7 +926,7 @@ static int render_testLogicalSize(void *arg) /* Helper functions */ /** - * \brief Checks to see if functionality is supported. Helper function. + * Checks to see if functionality is supported. Helper function. */ static int isSupported(int code) @@ -935,7 +935,7 @@ isSupported(int code) } /** - * \brief Test to see if we can vary the draw color. Helper function. + * Test to see if we can vary the draw color. Helper function. * * \sa SDL_SetRenderDrawColor * \sa SDL_GetRenderDrawColor @@ -976,7 +976,7 @@ hasDrawColor(void) } /** - * \brief Test to see if we can vary the blend mode. Helper function. + * Test to see if we can vary the blend mode. Helper function. * * \sa SDL_SetRenderDrawBlendMode * \sa SDL_GetRenderDrawBlendMode @@ -1043,7 +1043,7 @@ hasBlendModes(void) } /** - * \brief Loads the test image 'Face' as texture. Helper function. + * Loads the test image 'Face' as texture. Helper function. * * \sa SDL_CreateTextureFromSurface */ @@ -1069,7 +1069,7 @@ loadTestFace(void) } /** - * \brief Test to see if can set texture color mode. Helper function. + * Test to see if can set texture color mode. Helper function. * * \sa SDL_SetTextureColorMod * \sa SDL_GetTextureColorMod @@ -1112,7 +1112,7 @@ hasTexColor(void) } /** - * \brief Test to see if we can vary the alpha of the texture. Helper function. + * Test to see if we can vary the alpha of the texture. Helper function. * * \sa SDL_SetTextureAlphaMod * \sa SDL_GetTextureAlphaMod @@ -1155,7 +1155,7 @@ hasTexAlpha(void) } /** - * \brief Compares screen pixels with image pixels. Helper function. + * Compares screen pixels with image pixels. Helper function. * * \param referenceSurface Image to compare against. * \param allowable_error allowed difference from the reference image @@ -1200,7 +1200,7 @@ compare(SDL_Surface *referenceSurface, int allowable_error) } /** - * \brief Clears the screen. Helper function. + * Clears the screen. Helper function. * * \sa SDL_SetRenderDrawColor * \sa SDL_RenderClear diff --git a/test/testautomation_rwops.c b/test/testautomation_rwops.c index 59487e36463bf..f7199f09af21f 100644 --- a/test/testautomation_rwops.c +++ b/test/testautomation_rwops.c @@ -90,7 +90,7 @@ static void RWopsTearDown(void *arg) } /** - * \brief Makes sure parameters work properly. Local helper function. + * Makes sure parameters work properly. Local helper function. * * \sa SDL_RWseek * \sa SDL_RWread @@ -245,7 +245,7 @@ static int rwops_testParamNegative(void *arg) } /** - * \brief Tests opening from memory. + * Tests opening from memory. * * \sa SDL_RWFromMem * \sa SDL_RWClose @@ -284,7 +284,7 @@ static int rwops_testMem(void *arg) } /** - * \brief Tests opening from memory. + * Tests opening from memory. * * \sa SDL_RWFromConstMem * \sa SDL_RWClose @@ -319,7 +319,7 @@ static int rwops_testConstMem(void *arg) } /** - * \brief Tests reading from file. + * Tests reading from file. * * \sa SDL_RWFromFile * \sa SDL_RWClose @@ -366,7 +366,7 @@ static int rwops_testFileRead(void *arg) } /** - * \brief Tests writing from file. + * Tests writing from file. * * \sa SDL_RWFromFile * \sa SDL_RWClose @@ -413,7 +413,7 @@ static int rwops_testFileWrite(void *arg) } /** - * \brief Tests alloc and free RW context. + * Tests alloc and free RW context. * * \sa SDL_CreateRW * \sa SDL_DestroyRW @@ -441,7 +441,7 @@ static int rwops_testAllocFree(void *arg) } /** - * \brief Compare memory and file reads + * Compare memory and file reads * * \sa SDL_RWFromMem * \sa SDL_RWFromFile @@ -504,7 +504,7 @@ static int rwops_testCompareRWFromMemWithRWFromFile(void *arg) } /** - * \brief Tests writing and reading from file using endian aware functions. + * Tests writing and reading from file using endian aware functions. * * \sa SDL_RWFromFile * \sa SDL_RWClose diff --git a/test/testautomation_sdltest.c b/test/testautomation_sdltest.c index e04645041282e..1f29c07308b92 100644 --- a/test/testautomation_sdltest.c +++ b/test/testautomation_sdltest.c @@ -12,7 +12,7 @@ /* Test case functions */ /** - * \brief Calls to SDLTest_GenerateRunSeed() + * Calls to SDLTest_GenerateRunSeed() */ static int sdltest_generateRunSeed(void *arg) { @@ -42,7 +42,7 @@ static int sdltest_generateRunSeed(void *arg) } /** - * \brief Calls to SDLTest_GetFuzzerInvocationCount() + * Calls to SDLTest_GetFuzzerInvocationCount() */ static int sdltest_getFuzzerInvocationCount(void *arg) { @@ -64,7 +64,7 @@ static int sdltest_getFuzzerInvocationCount(void *arg) } /** - * \brief Calls to random number generators + * Calls to random number generators */ static int sdltest_randomNumber(void *arg) { @@ -131,7 +131,7 @@ static int sdltest_randomNumber(void *arg) } /** - * \brief Calls to random boundary number generators for Uint8 + * Calls to random boundary number generators for Uint8 */ static int sdltest_randomBoundaryNumberUint8(void *arg) { @@ -240,7 +240,7 @@ static int sdltest_randomBoundaryNumberUint8(void *arg) } /** - * \brief Calls to random boundary number generators for Uint16 + * Calls to random boundary number generators for Uint16 */ static int sdltest_randomBoundaryNumberUint16(void *arg) { @@ -349,7 +349,7 @@ static int sdltest_randomBoundaryNumberUint16(void *arg) } /** - * \brief Calls to random boundary number generators for Uint32 + * Calls to random boundary number generators for Uint32 */ static int sdltest_randomBoundaryNumberUint32(void *arg) { @@ -458,7 +458,7 @@ static int sdltest_randomBoundaryNumberUint32(void *arg) } /** - * \brief Calls to random boundary number generators for Uint64 + * Calls to random boundary number generators for Uint64 */ static int sdltest_randomBoundaryNumberUint64(void *arg) { @@ -567,7 +567,7 @@ static int sdltest_randomBoundaryNumberUint64(void *arg) } /** - * \brief Calls to random boundary number generators for Sint8 + * Calls to random boundary number generators for Sint8 */ static int sdltest_randomBoundaryNumberSint8(void *arg) { @@ -676,7 +676,7 @@ static int sdltest_randomBoundaryNumberSint8(void *arg) } /** - * \brief Calls to random boundary number generators for Sint16 + * Calls to random boundary number generators for Sint16 */ static int sdltest_randomBoundaryNumberSint16(void *arg) { @@ -785,7 +785,7 @@ static int sdltest_randomBoundaryNumberSint16(void *arg) } /** - * \brief Calls to random boundary number generators for Sint32 + * Calls to random boundary number generators for Sint32 */ static int sdltest_randomBoundaryNumberSint32(void *arg) { @@ -901,7 +901,7 @@ static int sdltest_randomBoundaryNumberSint32(void *arg) } /** - * \brief Calls to random boundary number generators for Sint64 + * Calls to random boundary number generators for Sint64 */ static int sdltest_randomBoundaryNumberSint64(void *arg) { @@ -1010,7 +1010,7 @@ static int sdltest_randomBoundaryNumberSint64(void *arg) } /** - * \brief Calls to SDLTest_RandomIntegerInRange + * Calls to SDLTest_RandomIntegerInRange */ static int sdltest_randomIntegerInRange(void *arg) { @@ -1084,7 +1084,7 @@ static int sdltest_randomIntegerInRange(void *arg) } /** - * \brief Calls to SDLTest_RandomAsciiString + * Calls to SDLTest_RandomAsciiString */ static int sdltest_randomAsciiString(void *arg) { @@ -1116,7 +1116,7 @@ static int sdltest_randomAsciiString(void *arg) } /** - * \brief Calls to SDLTest_RandomAsciiStringWithMaximumLength + * Calls to SDLTest_RandomAsciiStringWithMaximumLength */ static int sdltest_randomAsciiStringWithMaximumLength(void *arg) { @@ -1168,7 +1168,7 @@ static int sdltest_randomAsciiStringWithMaximumLength(void *arg) } /** - * \brief Calls to SDLTest_RandomAsciiStringOfSize + * Calls to SDLTest_RandomAsciiStringOfSize */ static int sdltest_randomAsciiStringOfSize(void *arg) { diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index ce2493990e2c2..e797e4824b36f 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -8,7 +8,7 @@ /* Test case functions */ /** - * \brief Call to SDL_strnlen + * Call to SDL_strnlen */ #undef SDL_strnlen static int stdlib_strnlen(void *arg) @@ -36,7 +36,7 @@ static int stdlib_strnlen(void *arg) } /** - * \brief Call to SDL_strlcpy + * Call to SDL_strlcpy */ #undef SDL_strlcpy static int stdlib_strlcpy(void *arg) @@ -71,7 +71,7 @@ static int stdlib_strlcpy(void *arg) #endif /** - * \brief Call to SDL_snprintf + * Call to SDL_snprintf */ #undef SDL_snprintf static int stdlib_snprintf(void *arg) @@ -262,7 +262,7 @@ static int stdlib_snprintf(void *arg) } /** - * \brief Call to SDL_swprintf + * Call to SDL_swprintf */ #undef SDL_swprintf static int stdlib_swprintf(void *arg) @@ -429,7 +429,7 @@ static int stdlib_swprintf(void *arg) #endif /** - * \brief Call to SDL_getenv and SDL_setenv + * Call to SDL_getenv and SDL_setenv */ static int stdlib_getsetenv(void *arg) { @@ -572,7 +572,7 @@ static int stdlib_getsetenv(void *arg) #endif /** - * \brief Call to SDL_sscanf + * Call to SDL_sscanf */ #undef SDL_sscanf static int stdlib_sscanf(void *arg) @@ -741,7 +741,7 @@ static int stdlib_sscanf(void *arg) #endif /** - * \brief Call to SDL_aligned_alloc + * Call to SDL_aligned_alloc */ static int stdlib_aligned_alloc(void *arg) { diff --git a/test/testautomation_subsystems.c b/test/testautomation_subsystems.c index 1bbc6410da1a2..b60927a0bf7ba 100644 --- a/test/testautomation_subsystems.c +++ b/test/testautomation_subsystems.c @@ -34,7 +34,7 @@ static void subsystemsTearDown(void *arg) /* Test case functions */ /** - * \brief Inits and Quits particular subsystem, checking its Init status. + * Inits and Quits particular subsystem, checking its Init status. * * \sa SDL_InitSubSystem * \sa SDL_QuitSubSystem @@ -83,7 +83,7 @@ static int subsystems_referenceCount() } /** - * \brief Inits and Quits subsystems that have another as dependency; + * Inits and Quits subsystems that have another as dependency; * check that the dependency is not removed before the last of its dependents. * * \sa SDL_InitSubSystem @@ -121,7 +121,7 @@ static int subsystems_dependRefCountInitAllQuitByOne() } /** - * \brief Inits and Quits subsystems that have another as dependency; + * Inits and Quits subsystems that have another as dependency; * check that the dependency is not removed before the last of its dependents. * * \sa SDL_InitSubSystem @@ -155,7 +155,7 @@ static int subsystems_dependRefCountInitByOneQuitAll() } /** - * \brief Inits and Quits subsystems that have another as dependency, + * Inits and Quits subsystems that have another as dependency, * but also inits that dependency explicitly, giving it extra ref count. * Check that the dependency is not removed before the last reference is gone. * diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index e338927e74790..5567ece46bebd 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -209,7 +209,7 @@ static void AssertFileExist(const char *filename) /* Test case functions */ /** - * \brief Tests sprite saving and loading + * Tests sprite saving and loading */ static int surface_testSaveLoadBitmap(void *arg) { @@ -389,7 +389,7 @@ static int surface_testCompleteSurfaceConversion(void *arg) } /** - * \brief Tests sprite loading. A failure case. + * Tests sprite loading. A failure case. */ static int surface_testLoadFailure(void *arg) { @@ -400,7 +400,7 @@ static int surface_testLoadFailure(void *arg) } /** - * \brief Tests some blitting routines. + * Tests some blitting routines. */ static int surface_testBlit(void *arg) { @@ -422,7 +422,7 @@ static int surface_testBlit(void *arg) } /** - * \brief Tests some blitting routines with color mod + * Tests some blitting routines with color mod */ static int surface_testBlitColorMod(void *arg) { @@ -444,7 +444,7 @@ static int surface_testBlitColorMod(void *arg) } /** - * \brief Tests some blitting routines with alpha mod + * Tests some blitting routines with alpha mod */ static int surface_testBlitAlphaMod(void *arg) { @@ -466,7 +466,7 @@ static int surface_testBlitAlphaMod(void *arg) } /** - * \brief Tests some more blitting routines. + * Tests some more blitting routines. */ static int surface_testBlitBlendNone(void *arg) { @@ -488,7 +488,7 @@ static int surface_testBlitBlendNone(void *arg) } /** - * \brief Tests some more blitting routines. + * Tests some more blitting routines. */ static int surface_testBlitBlendBlend(void *arg) { @@ -510,7 +510,7 @@ static int surface_testBlitBlendBlend(void *arg) } /** - * \brief Tests some more blitting routines. + * Tests some more blitting routines. */ static int surface_testBlitBlendAdd(void *arg) { @@ -532,7 +532,7 @@ static int surface_testBlitBlendAdd(void *arg) } /** - * \brief Tests some more blitting routines. + * Tests some more blitting routines. */ static int surface_testBlitBlendMod(void *arg) { @@ -554,7 +554,7 @@ static int surface_testBlitBlendMod(void *arg) } /** - * \brief Tests some more blitting routines with loop + * Tests some more blitting routines with loop */ static int surface_testBlitBlendLoop(void *arg) { diff --git a/test/testautomation_syswm.c b/test/testautomation_syswm.c index 069c4b13cce9e..e05f114915823 100644 --- a/test/testautomation_syswm.c +++ b/test/testautomation_syswm.c @@ -13,7 +13,7 @@ /* Test case functions */ /** - * \brief Call to SDL_GetWindowWMInfo + * Call to SDL_GetWindowWMInfo */ static int syswm_getWindowWMInfo(void *arg) { diff --git a/test/testautomation_timer.c b/test/testautomation_timer.c index f2b320395212a..d7d6449e2d127 100644 --- a/test/testautomation_timer.c +++ b/test/testautomation_timer.c @@ -30,7 +30,7 @@ static void timerSetUp(void *arg) /* Test case functions */ /** - * \brief Call to SDL_GetPerformanceCounter + * Call to SDL_GetPerformanceCounter */ static int timer_getPerformanceCounter(void *arg) { @@ -44,7 +44,7 @@ static int timer_getPerformanceCounter(void *arg) } /** - * \brief Call to SDL_GetPerformanceFrequency + * Call to SDL_GetPerformanceFrequency */ static int timer_getPerformanceFrequency(void *arg) { @@ -58,7 +58,7 @@ static int timer_getPerformanceFrequency(void *arg) } /** - * \brief Call to SDL_Delay and SDL_GetTicks + * Call to SDL_Delay and SDL_GetTicks */ static int timer_delayAndGetTicks(void *arg) { @@ -116,7 +116,7 @@ static Uint32 SDLCALL timerTestCallback(Uint32 interval, void *param) } /** - * \brief Call to SDL_AddTimer and SDL_RemoveTimer + * Call to SDL_AddTimer and SDL_RemoveTimer */ static int timer_addRemoveTimer(void *arg) { diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 5d0523f21f7a6..d45a9a40f0eb0 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -73,7 +73,7 @@ static void destroyVideoSuiteTestWindow(SDL_Window *window) /* Test case functions */ /** - * \brief Enable and disable screensaver while checking state + * Enable and disable screensaver while checking state */ static int video_enableDisableScreensaver(void *arg) { @@ -124,7 +124,7 @@ static int video_enableDisableScreensaver(void *arg) } /** - * \brief Tests the functionality of the SDL_CreateWindow function using different sizes + * Tests the functionality of the SDL_CreateWindow function using different sizes */ static int video_createWindowVariousSizes(void *arg) { @@ -178,7 +178,7 @@ static int video_createWindowVariousSizes(void *arg) } /** - * \brief Tests the functionality of the SDL_CreateWindow function using different flags + * Tests the functionality of the SDL_CreateWindow function using different flags */ static int video_createWindowVariousFlags(void *arg) { @@ -252,7 +252,7 @@ static int video_createWindowVariousFlags(void *arg) } /** - * \brief Tests the functionality of the SDL_GetWindowFlags function + * Tests the functionality of the SDL_GetWindowFlags function */ static int video_getWindowFlags(void *arg) { @@ -279,7 +279,7 @@ static int video_getWindowFlags(void *arg) } /** - * \brief Tests the functionality of the SDL_GetFullscreenDisplayModes function + * Tests the functionality of the SDL_GetFullscreenDisplayModes function */ static int video_getFullscreenDisplayModes(void *arg) { @@ -308,7 +308,7 @@ static int video_getFullscreenDisplayModes(void *arg) } /** - * \brief Tests the functionality of the SDL_GetClosestFullscreenDisplayMode function against current resolution + * Tests the functionality of the SDL_GetClosestFullscreenDisplayMode function against current resolution */ static int video_getClosestDisplayModeCurrentResolution(void *arg) { @@ -358,7 +358,7 @@ static int video_getClosestDisplayModeCurrentResolution(void *arg) } /** - * \brief Tests the functionality of the SDL_GetClosestFullscreenDisplayMode function against random resolution + * Tests the functionality of the SDL_GetClosestFullscreenDisplayMode function against random resolution */ static int video_getClosestDisplayModeRandomResolution(void *arg) { @@ -396,7 +396,7 @@ static int video_getClosestDisplayModeRandomResolution(void *arg) } /** - * \brief Tests call to SDL_GetWindowFullscreenMode + * Tests call to SDL_GetWindowFullscreenMode * * \sa SDL_GetWindowFullscreenMode */ @@ -440,7 +440,7 @@ static void checkInvalidWindowError(void) } /** - * \brief Tests call to SDL_GetWindowFullscreenMode with invalid input + * Tests call to SDL_GetWindowFullscreenMode with invalid input * * \sa SDL_GetWindowFullscreenMode */ @@ -528,7 +528,7 @@ static void setAndCheckWindowKeyboardGrabState(SDL_Window *window, SDL_bool desi } /** - * \brief Tests keyboard and mouse grab support + * Tests keyboard and mouse grab support * * \sa SDL_GetWindowGrab * \sa SDL_SetWindowGrab @@ -689,7 +689,7 @@ static int video_getSetWindowGrab(void *arg) } /** - * \brief Tests call to SDL_GetWindowID and SDL_GetWindowFromID + * Tests call to SDL_GetWindowID and SDL_GetWindowFromID * * \sa SDL_GetWindowID * \sa SDL_SetWindowFromID @@ -746,7 +746,7 @@ static int video_getWindowId(void *arg) } /** - * \brief Tests call to SDL_GetWindowPixelFormat + * Tests call to SDL_GetWindowPixelFormat * * \sa SDL_GetWindowPixelFormat */ @@ -812,7 +812,7 @@ static SDL_bool getSizeFromEvent(int *w, int *h) } /** - * \brief Tests call to SDL_GetWindowPosition and SDL_SetWindowPosition + * Tests call to SDL_GetWindowPosition and SDL_SetWindowPosition * * \sa SDL_GetWindowPosition * \sa SDL_SetWindowPosition @@ -973,7 +973,7 @@ static void checkInvalidParameterError(void) } /** - * \brief Tests call to SDL_GetWindowSize and SDL_SetWindowSize + * Tests call to SDL_GetWindowSize and SDL_SetWindowSize * * \sa SDL_GetWindowSize * \sa SDL_SetWindowSize @@ -1158,7 +1158,7 @@ static int video_getSetWindowSize(void *arg) } /** - * \brief Tests call to SDL_GetWindowMinimumSize and SDL_SetWindowMinimumSize + * Tests call to SDL_GetWindowMinimumSize and SDL_SetWindowMinimumSize * */ static int video_getSetWindowMinimumSize(void *arg) @@ -1301,7 +1301,7 @@ static int video_getSetWindowMinimumSize(void *arg) } /** - * \brief Tests call to SDL_GetWindowMaximumSize and SDL_SetWindowMaximumSize + * Tests call to SDL_GetWindowMaximumSize and SDL_SetWindowMaximumSize * */ static int video_getSetWindowMaximumSize(void *arg) @@ -1439,7 +1439,7 @@ static int video_getSetWindowMaximumSize(void *arg) } /** - * \brief Tests call to SDL_SetWindowData and SDL_GetWindowData + * Tests call to SDL_SetWindowData and SDL_GetWindowData * * \sa SDL_SetWindowData * \sa SDL_GetWindowData @@ -1629,7 +1629,7 @@ static int video_getSetWindowData(void *arg) } /** - * \brief Tests the functionality of the SDL_WINDOWPOS_CENTERED_DISPLAY along with SDL_WINDOW_FULLSCREEN. + * Tests the functionality of the SDL_WINDOWPOS_CENTERED_DISPLAY along with SDL_WINDOW_FULLSCREEN. * * Especially useful when run on a multi-monitor system with different DPI scales per monitor, * to test that the window size is maintained when moving between monitors. diff --git a/test/testhaptic.c b/test/testhaptic.c index 6a6d686981f6d..44fbb152e6232 100644 --- a/test/testhaptic.c +++ b/test/testhaptic.c @@ -27,7 +27,7 @@ static void abort_execution(void); static void HapticPrintSupported(SDL_Haptic *); /** - * \brief The entry point of this force feedback demo. + * The entry point of this force feedback demo. * \param[in] argc Number of arguments. * \param[in] argv Array of argc arguments. */ diff --git a/test/testrumble.c b/test/testrumble.c index a3c6dee37760f..965179e76d347 100644 --- a/test/testrumble.c +++ b/test/testrumble.c @@ -29,7 +29,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND static SDL_Haptic *haptic; /** - * \brief The entry point of this force feedback demo. + * The entry point of this force feedback demo. * \param[in] argc Number of arguments. * \param[in] argv Array of argc arguments. */ From 2f92807087f49c830481cc5689ae53cb7cdb42e2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 13:30:56 -0500 Subject: [PATCH 257/725] vulkan: SDL_Vulkan_CreateSurface now accepts an app-provided allocator. Fixes #3638. --- docs/README-migration.md | 2 ++ include/SDL3/SDL_vulkan.h | 7 +++++++ src/dynapi/SDL_dynapi_procs.h | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 3 ++- src/video/SDL_vulkan_internal.h | 1 + src/video/SDL_vulkan_utils.c | 3 ++- src/video/android/SDL_androidvulkan.c | 4 ++-- src/video/android/SDL_androidvulkan.h | 1 + src/video/cocoa/SDL_cocoavulkan.h | 1 + src/video/cocoa/SDL_cocoavulkan.m | 10 ++++++---- src/video/kmsdrm/SDL_kmsdrmvulkan.c | 3 ++- src/video/kmsdrm/SDL_kmsdrmvulkan.h | 1 + src/video/uikit/SDL_uikitvulkan.h | 1 + src/video/vivante/SDL_vivantevulkan.c | 3 ++- src/video/vivante/SDL_vivantevulkan.h | 1 + src/video/wayland/SDL_waylandvulkan.c | 4 ++-- src/video/wayland/SDL_waylandvulkan.h | 1 + src/video/windows/SDL_windowsvulkan.c | 4 ++-- src/video/windows/SDL_windowsvulkan.h | 1 + src/video/x11/SDL_x11vulkan.c | 7 +++---- src/video/x11/SDL_x11vulkan.h | 1 + test/testvulkan.c | 1 + 23 files changed, 44 insertions(+), 20 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index ab156c3e65458..7ddd7fb90e648 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1312,4 +1312,6 @@ SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no lo SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr. +SDL_Vulkan_CreateSurface() now takes a VkAllocationCallbacks pointer as its third parameter. If you don't have an allocator to supply, pass a NULL here to use the system default allocator (SDL2 always used the system default allocator here). + SDL_Vulkan_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 3b58efb55f654..6d84e655ca982 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -51,6 +51,7 @@ extern "C" { VK_DEFINE_HANDLE(VkInstance) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) +struct VkAllocationCallbacks; #endif /* !NO_SDL_VULKAN_TYPEDEFS */ @@ -165,8 +166,13 @@ extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint * `instance` must have been created with extensions returned by * SDL_Vulkan_GetInstanceExtensions() enabled. * + * If `allocator` is NULL, Vulkan will use the system default allocator. + * This argument is passed directly to Vulkan and isn't used by SDL itself. + * * \param window The window to which to attach the Vulkan surface * \param instance The Vulkan instance handle + * \param allocator A VkAllocationCallbacks struct, which lets the app + * set the allocator that creates the surface. Can be NULL. * \param surface A pointer to a VkSurfaceKHR handle to output the newly * created surface * \returns SDL_TRUE on success, SDL_FALSE on error. @@ -177,6 +183,7 @@ extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint */ extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR* surface); /* @} *//* Vulkan support functions */ diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 48a999e32c710..048aba36fef78 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -719,7 +719,7 @@ SDL_DYNAPI_PROC(int,SDL_UpdateTexture,(SDL_Texture *a, const SDL_Rect *b, const SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurfaceRects,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, VkSurfaceKHR *c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, const struct VkAllocationCallbacks *c, VkSurfaceKHR *d),(a,b,c,d),return) SDL_DYNAPI_PROC(char const* const*,SDL_Vulkan_GetInstanceExtensions,(Uint32 *a),(a),return) SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_Vulkan_GetVkGetInstanceProcAddr,(void),(),return) SDL_DYNAPI_PROC(int,SDL_Vulkan_LoadLibrary,(const char *a),(a),return) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 40ca819422804..b318d75db0b74 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -291,7 +291,7 @@ struct SDL_VideoDevice int (*Vulkan_LoadLibrary)(SDL_VideoDevice *_this, const char *path); void (*Vulkan_UnloadLibrary)(SDL_VideoDevice *_this); char const* const* (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, Uint32 *count); - SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface); + SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); /* * * */ /* diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 232d0a0379984..665009100de2c 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -5147,6 +5147,7 @@ char const* const* SDL_Vulkan_GetInstanceExtensions(Uint32 *count) SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { CHECK_WINDOW_MAGIC(window, SDL_FALSE); @@ -5166,7 +5167,7 @@ SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window, return SDL_FALSE; } - return _this->Vulkan_CreateSurface(_this, window, instance, surface); + return _this->Vulkan_CreateSurface(_this, window, instance, allocator, surface); } SDL_MetalView SDL_Metal_CreateView(SDL_Window *window) diff --git a/src/video/SDL_vulkan_internal.h b/src/video/SDL_vulkan_internal.h index 74452134bd52f..4d749fa6324f8 100644 --- a/src/video/SDL_vulkan_internal.h +++ b/src/video/SDL_vulkan_internal.h @@ -69,6 +69,7 @@ extern VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList( * extension. */ extern SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #else diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index 5ce81a7b0804b..e44275a9c3b66 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -177,6 +177,7 @@ static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = { SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = @@ -459,7 +460,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, createInfo.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; createInfo.globalAlpha = 1.0f; - result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo, NULL, surface); + result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); return SDL_FALSE; diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c index d47d422a97146..85f044f48bdfc 100644 --- a/src/video/android/SDL_androidvulkan.c +++ b/src/video/android/SDL_androidvulkan.c @@ -126,6 +126,7 @@ char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { SDL_WindowData *windowData = window->driverdata; @@ -153,8 +154,7 @@ SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.pNext = NULL; createInfo.flags = 0; createInfo.window = windowData->native_window; - result = vkCreateAndroidSurfaceKHR(instance, &createInfo, - NULL, surface); + result = vkCreateAndroidSurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); diff --git a/src/video/android/SDL_androidvulkan.h b/src/video/android/SDL_androidvulkan.h index e538ca917a2e4..d477ad106fc26 100644 --- a/src/video/android/SDL_androidvulkan.h +++ b/src/video/android/SDL_androidvulkan.h @@ -41,6 +41,7 @@ char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/cocoa/SDL_cocoavulkan.h b/src/video/cocoa/SDL_cocoavulkan.h index 155dac30888bc..fdc4a7e69f5f7 100644 --- a/src/video/cocoa/SDL_cocoavulkan.h +++ b/src/video/cocoa/SDL_cocoavulkan.h @@ -41,6 +41,7 @@ char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index 55d1f352fb0d1..d5d3cb88da69f 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -178,6 +178,7 @@ void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface, PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT, PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK) @@ -195,7 +196,7 @@ static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.pLayer = (__bridge const CAMetalLayer *) Cocoa_Metal_GetLayer(_this, metalview); - result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface); + result = vkCreateMetalSurfaceEXT(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { Cocoa_Metal_DestroyView(_this, metalview); SDL_SetError("vkCreateMetalSurfaceEXT failed: %s", @@ -231,6 +232,7 @@ static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this, SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = @@ -269,7 +271,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.pNext = NULL; createInfo.flags = 0; createInfo.pLayer = (CAMetalLayer *)data.sdlContentView.layer; - result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface); + result = vkCreateMetalSurfaceEXT(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateMetalSurfaceEXT failed: %s", SDL_Vulkan_GetResultString(result)); @@ -282,7 +284,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.pView = (__bridge const void *)data.sdlContentView; result = vkCreateMacOSSurfaceMVK(instance, &createInfo, - NULL, surface); + allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s", SDL_Vulkan_GetResultString(result)); @@ -291,7 +293,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, } } } else { - return Cocoa_Vulkan_CreateSurfaceViaMetalView(_this, window, instance, surface, vkCreateMetalSurfaceEXT, vkCreateMacOSSurfaceMVK); + return Cocoa_Vulkan_CreateSurfaceViaMetalView(_this, window, instance, allocator, surface, vkCreateMetalSurfaceEXT, vkCreateMacOSSurfaceMVK); } return SDL_TRUE; diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index fba00b6585cd4..20b6516e35410 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -163,6 +163,7 @@ char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { VkPhysicalDevice gpu = NULL; @@ -476,7 +477,7 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, display_plane_surface_create_info.alphaMode = alpha_mode; result = vkCreateDisplayPlaneSurfaceKHR(instance, &display_plane_surface_create_info, - NULL, + allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s", diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.h b/src/video/kmsdrm/SDL_kmsdrmvulkan.h index 7db828d93a525..5b327197d6666 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.h +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.h @@ -41,6 +41,7 @@ char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/uikit/SDL_uikitvulkan.h b/src/video/uikit/SDL_uikitvulkan.h index 432edda9460d7..540ccca468713 100644 --- a/src/video/uikit/SDL_uikitvulkan.h +++ b/src/video/uikit/SDL_uikitvulkan.h @@ -41,6 +41,7 @@ char const* const* UIKit_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c index d5a30e79e96eb..9244bf0b256bf 100644 --- a/src/video/vivante/SDL_vivantevulkan.c +++ b/src/video/vivante/SDL_vivantevulkan.c @@ -133,13 +133,14 @@ char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { if (!_this->vulkan_config.loader_handle) { SDL_SetError("Vulkan is not loaded"); return SDL_FALSE; } - return SDL_Vulkan_Display_CreateSurface(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface); + return SDL_Vulkan_Display_CreateSurface(_this->vulkan_config.vkGetInstanceProcAddr, instance, allocator, surface); } #endif diff --git a/src/video/vivante/SDL_vivantevulkan.h b/src/video/vivante/SDL_vivantevulkan.h index b39fd2b9f0af5..5a0fa9133a4d4 100644 --- a/src/video/vivante/SDL_vivantevulkan.h +++ b/src/video/vivante/SDL_vivantevulkan.h @@ -40,6 +40,7 @@ char const* const* VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index b07aaf95e895d..99a9cd13e40fc 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -134,6 +134,7 @@ char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { SDL_WindowData *windowData = window->driverdata; @@ -162,8 +163,7 @@ SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.display = windowData->waylandData->display; createInfo.surface = windowData->surface; - result = vkCreateWaylandSurfaceKHR(instance, &createInfo, - NULL, surface); + result = vkCreateWaylandSurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateWaylandSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); diff --git a/src/video/wayland/SDL_waylandvulkan.h b/src/video/wayland/SDL_waylandvulkan.h index ebcd4c1c5656f..c3ba76dc2c250 100644 --- a/src/video/wayland/SDL_waylandvulkan.h +++ b/src/video/wayland/SDL_waylandvulkan.h @@ -41,6 +41,7 @@ char const* const* Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c index 79b64ffd8f77e..e2e2a39a60c60 100644 --- a/src/video/windows/SDL_windowsvulkan.c +++ b/src/video/windows/SDL_windowsvulkan.c @@ -125,6 +125,7 @@ char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { SDL_WindowData *windowData = window->driverdata; @@ -152,8 +153,7 @@ SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.hinstance = windowData->hinstance; createInfo.hwnd = windowData->hwnd; - result = vkCreateWin32SurfaceKHR(instance, &createInfo, - NULL, surface); + result = vkCreateWin32SurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateWin32SurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); diff --git a/src/video/windows/SDL_windowsvulkan.h b/src/video/windows/SDL_windowsvulkan.h index 0fffcbf4278c9..95e6c12ae4a57 100644 --- a/src/video/windows/SDL_windowsvulkan.h +++ b/src/video/windows/SDL_windowsvulkan.h @@ -41,6 +41,7 @@ char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c index 7eea5a34bba82..a5aa38b9a2e1c 100644 --- a/src/video/x11/SDL_x11vulkan.c +++ b/src/video/x11/SDL_x11vulkan.c @@ -170,6 +170,7 @@ char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { SDL_VideoData *videoData = _this->driverdata; @@ -199,8 +200,7 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, return SDL_FALSE; } createInfo.window = (xcb_window_t)windowData->xwindow; - result = vkCreateXcbSurfaceKHR(instance, &createInfo, - NULL, surface); + result = vkCreateXcbSurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateXcbSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); return SDL_FALSE; @@ -221,8 +221,7 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; createInfo.dpy = videoData->display; createInfo.window = (xcb_window_t)windowData->xwindow; - result = vkCreateXlibSurfaceKHR(instance, &createInfo, - NULL, surface); + result = vkCreateXlibSurfaceKHR(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { SDL_SetError("vkCreateXlibSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); return SDL_FALSE; diff --git a/src/video/x11/SDL_x11vulkan.h b/src/video/x11/SDL_x11vulkan.h index acaf5d65cbc65..e26727e5505a9 100644 --- a/src/video/x11/SDL_x11vulkan.h +++ b/src/video/x11/SDL_x11vulkan.h @@ -37,6 +37,7 @@ char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface); #endif diff --git a/test/testvulkan.c b/test/testvulkan.c index e13e3ace84210..4555f8705a2ee 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -261,6 +261,7 @@ static void createSurface(void) { if (!SDL_Vulkan_CreateSurface(vulkanContext->window, vulkanContext->instance, + NULL, &vulkanContext->surface)) { vulkanContext->surface = VK_NULL_HANDLE; SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Vulkan_CreateSurface(): %s\n", SDL_GetError()); From fccec65afe890fb62e774633866ca9e60b0a4482 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 6 Nov 2023 18:32:15 +0000 Subject: [PATCH 258/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_vulkan.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 6d84e655ca982..98590786e56fc 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -166,13 +166,13 @@ extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint * `instance` must have been created with extensions returned by * SDL_Vulkan_GetInstanceExtensions() enabled. * - * If `allocator` is NULL, Vulkan will use the system default allocator. - * This argument is passed directly to Vulkan and isn't used by SDL itself. + * If `allocator` is NULL, Vulkan will use the system default allocator. This + * argument is passed directly to Vulkan and isn't used by SDL itself. * * \param window The window to which to attach the Vulkan surface * \param instance The Vulkan instance handle - * \param allocator A VkAllocationCallbacks struct, which lets the app - * set the allocator that creates the surface. Can be NULL. + * \param allocator A VkAllocationCallbacks struct, which lets the app set the + * allocator that creates the surface. Can be NULL. * \param surface A pointer to a VkSurfaceKHR handle to output the newly * created surface * \returns SDL_TRUE on success, SDL_FALSE on error. From 4d1aecc22571e0f43c2f5937dfcc541e18d1f35d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 13:34:29 -0500 Subject: [PATCH 259/725] vulkan: Patched to compile on iOS. --- src/video/uikit/SDL_uikitvulkan.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m index 833485062ba53..b6191ae0b3c08 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -184,6 +184,7 @@ void UIKit_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, + const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = @@ -222,7 +223,7 @@ SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.pLayer = (__bridge const CAMetalLayer *) UIKit_Metal_GetLayer(_this, metalview); - result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface); + result = vkCreateMetalSurfaceEXT(instance, &createInfo, allocator, surface); if (result != VK_SUCCESS) { UIKit_Metal_DestroyView(_this, metalview); SDL_SetError("vkCreateMetalSurfaceEXT failed: %s", @@ -236,7 +237,7 @@ SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this, createInfo.flags = 0; createInfo.pView = (const void *)metalview; result = vkCreateIOSSurfaceMVK(instance, &createInfo, - NULL, surface); + allocator, surface); if (result != VK_SUCCESS) { UIKit_Metal_DestroyView(_this, metalview); SDL_SetError("vkCreateIOSSurfaceMVK failed: %s", From c6d9fb1ad71462bc844c6ca41e2ac7fe7cec3883 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 13:48:07 -0500 Subject: [PATCH 260/725] hidapi: Avoid memcpy'ing to NULL. (This fix was originally from @themightyoarfish on GitHub. Thanks!) Fixes #8428. Reference PR #8431. --- src/hidapi/mac/hid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c index 20c664501d5ec..1eb49b5d3120b 100644 --- a/src/hidapi/mac/hid.c +++ b/src/hidapi/mac/hid.c @@ -1230,7 +1230,9 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; size_t len = (length < rpt->len)? length: rpt->len; - memcpy(data, rpt->data, len); + if (data != NULL) { + memcpy(data, rpt->data, len); + } dev->input_reports = rpt->next; free(rpt->data); free(rpt); From 869257a5c1c68882eb875d92f2223191aee8f8a9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Nov 2023 19:16:38 -0500 Subject: [PATCH 261/725] SDL_migration.cocci: Added a thing for SDL_Vulkan_CreateSurface. --- build-scripts/SDL_migration.cocci | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 8a6012e28086a..e4ac8a9899735 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -2745,3 +2745,8 @@ expression e, n, v; @@ - SDL_SetWindowData(e, n, v) + SDL_SetProperty(SDL_GetWindowProperties(e), n, v, NULL, NULL) +@@ +expression w, i, s; +@@ +- SDL_Vulkan_CreateSurface(w, i, s) ++ SDL_Vulkan_CreateSurface(w, i, NULL, s) \ No newline at end of file From 07cb7c10a15b95387431bcb3a1ae77cfd432707b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 17:10:03 -0800 Subject: [PATCH 262/725] Fixed connecting and disconnecting real-joysticks closing virtual joysticks in Emscripten (thanks David!) Emscripten was using its own, private integer in order to allocate new SDL_JoystickIDs. SDL keeps a similar integer for allocating joystick-ids, one which is shared across multiple joystick backends. SDL 2.0.13 introduces a new joystick-backend, a Virtual joystick backend, which allows for software-driven joysticks, and which is designed to sit alongside joystick-backends that provide access to physical joysticks. The Emscripten and the Virtual backends were, at times, getting allocated the same SDL_JoystickIDs, if and when both backends were used simultaneously. This could happen if, for example, an application was using a virtual joystick in order to drive a touch-screen based joystick, while also supporting physical joysticks through the Emscripten backend. When two joysticks end up with the same SDL_JoystickID, conflicts can occur. For example, disconnecting a physical joystick with the same SDL_JoystickID as a virtual one, can lead to the virtual joystick being closed, inadvertently. This fix makes the Emscripten backend use SDL's cross-joystick-backend integer counter, which is shared among joystick backends, for allocating new SDL_JoystickIDs, rather than a private, Emscripten-specific counter. Fixes https://github.com/libsdl-org/SDL/issues/3647 --- src/joystick/emscripten/SDL_sysjoystick.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 902c91d00fe13..4f9dffaaae93b 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -33,7 +33,6 @@ static SDL_joylist_item *JoystickByIndex(int index); static SDL_joylist_item *SDL_joylist = NULL; static SDL_joylist_item *SDL_joylist_tail = NULL; static int numjoysticks = 0; -static int instance_counter = 0; static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { @@ -68,7 +67,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep item->naxes = gamepadEvent->numAxes; item->nbuttons = gamepadEvent->numButtons; - item->device_instance = instance_counter++; + item->device_instance = SDL_GetNextJoystickInstanceID(); item->timestamp = gamepadEvent->timestamp; @@ -164,7 +163,6 @@ static void EMSCRIPTEN_JoystickQuit(void) SDL_joylist = SDL_joylist_tail = NULL; numjoysticks = 0; - instance_counter = 0; emscripten_set_gamepadconnected_callback(NULL, 0, NULL); emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL); From dbcd390cdf1a6f711c8c050489ada897331b2057 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 18:53:06 -0800 Subject: [PATCH 263/725] Log drag and drop position updates in SDL test programs --- src/test/SDL_test_common.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 0a3360f81679c..25cf72c23c467 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1820,13 +1820,16 @@ static void SDLTest_PrintEvent(const SDL_Event *event) SDL_Log("SDL EVENT: App entered the foreground"); break; case SDL_EVENT_DROP_BEGIN: - SDL_Log("SDL EVENT: Drag and drop beginning"); + SDL_Log("SDL EVENT: Drag and drop beginning in window %" SDL_PRIu32 "", event->drop.windowID); + break; + case SDL_EVENT_DROP_POSITION: + SDL_Log("SDL EVENT: Drag and drop moving in window %" SDL_PRIu32 ": %g,%g", event->drop.windowID, event->drop.x, event->drop.y); break; case SDL_EVENT_DROP_FILE: - SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.data); + SDL_Log("SDL EVENT: Drag and drop file in window %" SDL_PRIu32 ": '%s'", event->drop.windowID, event->drop.data); break; case SDL_EVENT_DROP_TEXT: - SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.data); + SDL_Log("SDL EVENT: Drag and drop text in window %" SDL_PRIu32 ": '%s'", event->drop.windowID, event->drop.data); break; case SDL_EVENT_DROP_COMPLETE: SDL_Log("SDL EVENT: Drag and drop ending"); From 66cf30c2de4f12c1b99b8d51ea5d77b62b373907 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 19:33:22 -0800 Subject: [PATCH 264/725] Removed misleading comment Fixes https://github.com/libsdl-org/SDL/issues/5069 --- src/haptic/linux/SDL_syshaptic.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 549354e395b7b..a32e391f60679 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -640,17 +640,6 @@ static int SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection *src) switch (src->type) { case SDL_HAPTIC_POLAR: - /* Linux directions start from south. - (and range from 0 to 0xFFFF) - Quoting include/linux/input.h, line 926: - Direction of the effect is encoded as follows: - 0 deg -> 0x0000 (down) - 90 deg -> 0x4000 (left) - 180 deg -> 0x8000 (up) - 270 deg -> 0xC000 (right) - The force pulls into the direction specified by Linux directions, - i.e. the opposite convention of SDL directions. - */ tmp = ((src->dir[0] % 36000) * 0x8000) / 18000; /* convert to range [0,0xFFFF] */ *dest = (Uint16)tmp; break; From 22016b4eae50fab0698ff3a33672f57283f1cccd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 20:14:50 -0800 Subject: [PATCH 265/725] Enable the 5th player LED on the DualSense controller Fixes https://github.com/libsdl-org/SDL/issues/5152 --- src/joystick/hidapi/SDL_hidapi_ps5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 6a6f7b1e2f566..f4b628a18c78a 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -351,7 +351,8 @@ static void SetLightsForPlayerIndex(DS5EffectsState_t *effects, int player_index 0x04, 0x0A, 0x15, - 0x1B + 0x1B, + 0x1F }; if (player_index >= 0) { From 5f920d663928178327c1e078d482d3334958a726 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Tue, 7 Nov 2023 07:55:30 +0300 Subject: [PATCH 266/725] fix emscripten build after commit 07cb7c10 --- src/joystick/emscripten/SDL_sysjoystick.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 4f9dffaaae93b..dbce1337513d9 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -67,7 +67,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep item->naxes = gamepadEvent->numAxes; item->nbuttons = gamepadEvent->numButtons; - item->device_instance = SDL_GetNextJoystickInstanceID(); + item->device_instance = SDL_GetNextObjectID(); item->timestamp = gamepadEvent->timestamp; @@ -94,7 +94,6 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep #ifdef DEBUG_JOYSTICK SDL_Log("Number of joysticks is %d", numjoysticks); #endif - #ifdef DEBUG_JOYSTICK SDL_Log("Added joystick with index %d", item->index); #endif From 1a57f6bb297583d1ba2ec8e92e7f1932df3a7fb8 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 7 Nov 2023 10:36:07 -0500 Subject: [PATCH 267/725] wayland: Remove QtWayland extensions These were added a very long time ago and seem to serve no purpose now, as the functionality they provided is now in core Wayland protocols, current information on their usage and status is nonexistent, no modern compositor seems to support them, and the code paths are untested and subject to bit-rot at this point. It also causes duplicate symbol issues when statically linking an application to both Qt and SDL. --- CMakeLists.txt | 1 - cmake/sdlchecks.cmake | 5 - include/build_config/SDL_build_config.h.cmake | 1 - src/video/wayland/SDL_waylandtouch.c | 283 --------------- src/video/wayland/SDL_waylandtouch.h | 334 ------------------ src/video/wayland/SDL_waylandvideo.c | 42 --- src/video/wayland/SDL_waylandvideo.h | 12 - src/video/wayland/SDL_waylandwindow.c | 137 ------- src/video/wayland/SDL_waylandwindow.h | 4 - 9 files changed, 819 deletions(-) delete mode 100644 src/video/wayland/SDL_waylandtouch.c delete mode 100644 src/video/wayland/SDL_waylandtouch.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d07d9ade658b..5159cbd5864fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,7 +329,6 @@ set_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS}) dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND" OFF) dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF) dep_option(SDL_WAYLAND_LIBDECOR_SHARED "Dynamically load libdecor support" ON "SDL_WAYLAND_LIBDECOR;SDL_WAYLAND_SHARED" OFF) -dep_option(SDL_WAYLAND_QT_TOUCH "QtWayland server support for Wayland video driver" ON "SDL_WAYLAND" OFF) dep_option(SDL_RPI "Use Raspberry Pi video driver" ON "UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) dep_option(SDL_ROCKCHIP "Use ROCKCHIP Hardware Acceleration video driver" ON "UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) set_option(SDL_COCOA "Use Cocoa video driver" ${APPLE}) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 87ca76b1c1dc2..e6beb747467a7 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -533,11 +533,6 @@ macro(CheckWayland) WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_SCANNER_CODE_MODE}" "${SDL3_SOURCE_DIR}/wayland-protocols/${_XML}" "${_PROTL}") endforeach() - if(SDL_WAYLAND_QT_TOUCH) - set(HAVE_WAYLAND_QT_TOUCH TRUE) - set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1) - endif() - if(SDL_WAYLAND_SHARED AND NOT HAVE_SDL_LOADSO) message(WARNING "You must have SDL_LoadObject() support for dynamic Wayland loading") endif() diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 9347bccafb1bb..091751fb3fb0f 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -393,7 +393,6 @@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@ -#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@ #cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@ #cmakedefine SDL_VIDEO_DRIVER_WINRT @SDL_VIDEO_DRIVER_WINRT@ #cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@ diff --git a/src/video/wayland/SDL_waylandtouch.c b/src/video/wayland/SDL_waylandtouch.c deleted file mode 100644 index f7348aecdc263..0000000000000 --- a/src/video/wayland/SDL_waylandtouch.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* Contributed by Thomas Perl */ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - -#include "SDL_waylandtouch.h" -#include "SDL_waylandevents_c.h" -#include "../../events/SDL_touch_c.h" - -struct SDL_WaylandTouch -{ - struct qt_touch_extension *touch_extension; -}; - -/** - * Qt TouchPointState - * adapted from qtbase/src/corelib/global/qnamespace.h - **/ -enum QtWaylandTouchPointState -{ - QtWaylandTouchPointPressed = 0x01, - QtWaylandTouchPointMoved = 0x02, - /* - Never sent by the server: - QtWaylandTouchPointStationary = 0x04, - */ - QtWaylandTouchPointReleased = 0x08, -}; - -static void touch_handle_touch(void *data, - struct qt_touch_extension *qt_touch_extension, - uint32_t time, - uint32_t id, - uint32_t state, - int32_t x, - int32_t y, - int32_t normalized_x, - int32_t normalized_y, - int32_t width, - int32_t height, - uint32_t pressure, - int32_t velocity_x, - int32_t velocity_y, - uint32_t flags, - struct wl_array *rawdata) -{ - /** - * Event is assembled in QtWayland in TouchExtensionGlobal::postTouchEvent - * (src/compositor/wayland_wrapper/qwltouch.cpp) - **/ - - SDL_VideoData *viddata = data; - - float FIXED_TO_FLOAT = 1. / 10000.; - float xf = FIXED_TO_FLOAT * normalized_x; - float yf = FIXED_TO_FLOAT * normalized_y; - - float PRESSURE_TO_FLOAT = 1. / 255.; - float pressuref = PRESSURE_TO_FLOAT * pressure; - - uint32_t touchState = state & 0xFFFF; - /* - Other fields that are sent by the server (qwltouch.cpp), - but not used at the moment can be decoded in this way: - - uint32_t sentPointCount = state >> 16; - uint32_t touchFlags = flags & 0xFFFF; - uint32_t capabilities = flags >> 16; - */ - - SDL_Window *window = NULL; - - SDL_TouchID deviceId = 1; - if (SDL_AddTouch(deviceId, SDL_TOUCH_DEVICE_DIRECT, "qt_touch_extension") < 0) { - SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__); - } - - /* FIXME: This should be the window the given wayland surface is associated - * with, but how do we get the wayland surface? */ - window = SDL_GetMouseFocus(); - if (window == NULL) { - window = SDL_GetKeyboardFocus(); - } - - switch (touchState) { - case QtWaylandTouchPointPressed: - case QtWaylandTouchPointReleased: - SDL_SendTouch(Wayland_GetTouchTimestamp(viddata->input, time), deviceId, (SDL_FingerID)id, - window, (touchState == QtWaylandTouchPointPressed), xf, yf, pressuref); - break; - case QtWaylandTouchPointMoved: - SDL_SendTouchMotion(Wayland_GetTouchTimestamp(viddata->input, time), deviceId, (SDL_FingerID)id, - window, xf, yf, pressuref); - break; - default: - /* Should not happen */ - break; - } -} - -static void touch_handle_configure(void *data, - struct qt_touch_extension *qt_touch_extension, - uint32_t flags) -{ -} - -/* wayland-qt-touch-extension.c BEGINS */ - -static const struct qt_touch_extension_listener touch_listener = { - touch_handle_touch, - touch_handle_configure, -}; - -static const struct wl_interface *qt_touch_extension_types[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static const struct wl_message qt_touch_extension_requests[] = { - { "dummy", "", qt_touch_extension_types + 0 }, -}; - -static const struct wl_message qt_touch_extension_events[] = { - { "touch", "uuuiiiiiiuiiua", qt_touch_extension_types + 0 }, - { "configure", "u", qt_touch_extension_types + 0 }, -}; - -const struct wl_interface qt_touch_extension_interface = { - "qt_touch_extension", - 1, - 1, - qt_touch_extension_requests, - 2, - qt_touch_extension_events, -}; - -/* wayland-qt-touch-extension.c ENDS */ - -/* wayland-qt-windowmanager.c BEGINS */ -static const struct wl_interface *qt_windowmanager_types[] = { - NULL, - NULL, -}; - -static const struct wl_message qt_windowmanager_requests[] = { - { "open_url", "us", qt_windowmanager_types + 0 }, -}; - -static const struct wl_message qt_windowmanager_events[] = { - { "hints", "i", qt_windowmanager_types + 0 }, - { "quit", "", qt_windowmanager_types + 0 }, -}; - -const struct wl_interface qt_windowmanager_interface = { - "qt_windowmanager", - 1, - 1, - qt_windowmanager_requests, - 2, - qt_windowmanager_events, -}; -/* wayland-qt-windowmanager.c ENDS */ - -/* wayland-qt-surface-extension.c BEGINS */ -#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC -extern const struct wl_interface wl_surface_interface; -#endif - -static const struct wl_interface *qt_surface_extension_types[] = { - NULL, - NULL, - &qt_extended_surface_interface, -#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC - /* FIXME: Set this dynamically to (*WAYLAND_wl_surface_interface) ? - * The value comes from auto generated code and does - * not appear to actually be used anywhere - */ - NULL, -#else - &wl_surface_interface, -#endif -}; - -static const struct wl_message qt_surface_extension_requests[] = { - { "get_extended_surface", "no", qt_surface_extension_types + 2 }, -}; - -const struct wl_interface qt_surface_extension_interface = { - "qt_surface_extension", - 1, - 1, - qt_surface_extension_requests, - 0, - NULL, -}; - -static const struct wl_message qt_extended_surface_requests[] = { - { "update_generic_property", "sa", qt_surface_extension_types + 0 }, - { "set_content_orientation", "i", qt_surface_extension_types + 0 }, - { "set_window_flags", "i", qt_surface_extension_types + 0 }, -}; - -static const struct wl_message qt_extended_surface_events[] = { - { "onscreen_visibility", "i", qt_surface_extension_types + 0 }, - { "set_generic_property", "sa", qt_surface_extension_types + 0 }, - { "close", "", qt_surface_extension_types + 0 }, -}; - -const struct wl_interface qt_extended_surface_interface = { - "qt_extended_surface", - 1, - 3, - qt_extended_surface_requests, - 3, - qt_extended_surface_events, -}; - -/* wayland-qt-surface-extension.c ENDS */ - -void Wayland_touch_create(SDL_VideoData *data, uint32_t id) -{ - struct SDL_WaylandTouch *touch; - - if (data->touch) { - Wayland_touch_destroy(data); - } - - /* !!! FIXME: check for failure, call SDL_OutOfMemory() */ - data->touch = SDL_malloc(sizeof(struct SDL_WaylandTouch)); - - touch = data->touch; - touch->touch_extension = wl_registry_bind(data->registry, id, &qt_touch_extension_interface, 1); - qt_touch_extension_add_listener(touch->touch_extension, &touch_listener, data); -} - -void Wayland_touch_destroy(SDL_VideoData *data) -{ - if (data->touch) { - struct SDL_WaylandTouch *touch = data->touch; - if (touch->touch_extension) { - qt_touch_extension_destroy(touch->touch_extension); - } - - SDL_free(data->touch); - data->touch = NULL; - } -} - -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ diff --git a/src/video/wayland/SDL_waylandtouch.h b/src/video/wayland/SDL_waylandtouch.h deleted file mode 100644 index 59150d8cc6323..0000000000000 --- a/src/video/wayland/SDL_waylandtouch.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SDL_waylandtouch_h_ -#define SDL_waylandtouch_h_ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - -#include "SDL_waylandvideo.h" -#include -#include -#include "wayland-util.h" - -void Wayland_touch_create(SDL_VideoData *data, uint32_t id); -void Wayland_touch_destroy(SDL_VideoData *data); - -struct qt_touch_extension; - -/* Autogenerated QT headers */ - -/* - Support for Wayland with QmlCompositor as Server -================================================ - -The Wayland video driver has support for some additional features when -using QtWayland's "qmlcompositor" as Wayland server. This is needed for touch -input when running SDL applications under a qmlcompositor Wayland server. - -The files following headers have been -generated from the Wayland XML Protocol Definition in QtWayland as follows: - -Clone QtWayland from Git: - http://qt.gitorious.org/qt/qtwayland/ - -Generate headers and glue code: - for extension in touch-extension surface-extension windowmanager; do - wayland-scanner client-header < src/extensions/$extension.xml > wayland-qt-$extension.h - wayland-scanner code < src/extensions/$extension.xml > wayland-qt-$extension.c - done - -*/ - -/* wayland-qt-surface-extension.h */ - -struct wl_client; -struct wl_resource; - -struct qt_surface_extension; -struct qt_extended_surface; - -extern const struct wl_interface qt_surface_extension_interface; -extern const struct wl_interface qt_extended_surface_interface; - -#define QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE 0 - -static inline void qt_surface_extension_set_user_data(struct qt_surface_extension *qt_surface_extension, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *)qt_surface_extension, user_data); -} - -static inline void *qt_surface_extension_get_user_data(struct qt_surface_extension *qt_surface_extension) -{ - return wl_proxy_get_user_data((struct wl_proxy *)qt_surface_extension); -} - -static inline void qt_surface_extension_destroy(struct qt_surface_extension *qt_surface_extension) -{ - WAYLAND_wl_proxy_destroy((struct wl_proxy *)qt_surface_extension); -} - -static inline struct qt_extended_surface *qt_surface_extension_get_extended_surface(struct qt_surface_extension *qt_surface_extension, struct wl_surface *surface) -{ - struct wl_proxy *id; - - id = wl_proxy_create((struct wl_proxy *)qt_surface_extension, - &qt_extended_surface_interface); - if (id == NULL) - return NULL; - - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_surface_extension, - QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE, id, surface); - - return (struct qt_extended_surface *)id; -} - -#ifndef QT_EXTENDED_SURFACE_ORIENTATION_ENUM -#define QT_EXTENDED_SURFACE_ORIENTATION_ENUM -enum qt_extended_surface_orientation -{ - QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION = 0, - QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION = 1, - QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION = 2, - QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION = 4, - QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION = 8, -}; -#endif /* QT_EXTENDED_SURFACE_ORIENTATION_ENUM */ - -#ifndef QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM -#define QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM -enum qt_extended_surface_windowflag -{ - QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES = 1, - QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP = 2, -}; -#endif /* QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM */ - -struct qt_extended_surface_listener -{ - /** - * onscreen_visibility - (none) - * @visible: (none) - */ - void (*onscreen_visibility)(void *data, - struct qt_extended_surface *qt_extended_surface, - int32_t visible); - /** - * set_generic_property - (none) - * @name: (none) - * @value: (none) - */ - void (*set_generic_property)(void *data, - struct qt_extended_surface *qt_extended_surface, - const char *name, - struct wl_array *value); - /** - * close - (none) - */ - void (*close)(void *data, - struct qt_extended_surface *qt_extended_surface); -}; - -static inline int qt_extended_surface_add_listener(struct qt_extended_surface *qt_extended_surface, - const struct qt_extended_surface_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *)qt_extended_surface, - (void (**)(void))listener, data); -} - -#define QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY 0 -#define QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION 1 -#define QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS 2 - -static inline void qt_extended_surface_set_user_data(struct qt_extended_surface *qt_extended_surface, void *user_data) -{ - WAYLAND_wl_proxy_set_user_data((struct wl_proxy *)qt_extended_surface, user_data); -} - -static inline void *qt_extended_surface_get_user_data(struct qt_extended_surface *qt_extended_surface) -{ - return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *)qt_extended_surface); -} - -static inline void qt_extended_surface_destroy(struct qt_extended_surface *qt_extended_surface) -{ - WAYLAND_wl_proxy_destroy((struct wl_proxy *)qt_extended_surface); -} - -static inline void qt_extended_surface_update_generic_property(struct qt_extended_surface *qt_extended_surface, const char *name, struct wl_array *value) -{ - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_extended_surface, - QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY, name, value); -} - -static inline void qt_extended_surface_set_content_orientation(struct qt_extended_surface *qt_extended_surface, int32_t orientation) -{ - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_extended_surface, - QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION, orientation); -} - -static inline void qt_extended_surface_set_window_flags(struct qt_extended_surface *qt_extended_surface, int32_t flags) -{ - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_extended_surface, - QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS, flags); -} - -/* wayland-qt-touch-extension.h */ - -extern const struct wl_interface qt_touch_extension_interface; - -#ifndef QT_TOUCH_EXTENSION_FLAGS_ENUM -#define QT_TOUCH_EXTENSION_FLAGS_ENUM -enum qt_touch_extension_flags -{ - QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH = 0x1, -}; -#endif /* QT_TOUCH_EXTENSION_FLAGS_ENUM */ - -struct qt_touch_extension_listener -{ - /** - * touch - (none) - * @time: (none) - * @id: (none) - * @state: (none) - * @x: (none) - * @y: (none) - * @normalized_x: (none) - * @normalized_y: (none) - * @width: (none) - * @height: (none) - * @pressure: (none) - * @velocity_x: (none) - * @velocity_y: (none) - * @flags: (none) - * @rawdata: (none) - */ - void (*touch)(void *data, - struct qt_touch_extension *qt_touch_extension, - uint32_t time, - uint32_t id, - uint32_t state, - int32_t x, - int32_t y, - int32_t normalized_x, - int32_t normalized_y, - int32_t width, - int32_t height, - uint32_t pressure, - int32_t velocity_x, - int32_t velocity_y, - uint32_t flags, - struct wl_array *rawdata); - /** - * configure - (none) - * @flags: (none) - */ - void (*configure)(void *data, - struct qt_touch_extension *qt_touch_extension, - uint32_t flags); -}; - -static inline int qt_touch_extension_add_listener(struct qt_touch_extension *qt_touch_extension, - const struct qt_touch_extension_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *)qt_touch_extension, - (void (**)(void))listener, data); -} - -#define QT_TOUCH_EXTENSION_DUMMY 0 - -static inline void qt_touch_extension_set_user_data(struct qt_touch_extension *qt_touch_extension, void *user_data) -{ - WAYLAND_wl_proxy_set_user_data((struct wl_proxy *)qt_touch_extension, user_data); -} - -static inline void *qt_touch_extension_get_user_data(struct qt_touch_extension *qt_touch_extension) -{ - return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *)qt_touch_extension); -} - -static inline void qt_touch_extension_destroy(struct qt_touch_extension *qt_touch_extension) -{ - WAYLAND_wl_proxy_destroy((struct wl_proxy *)qt_touch_extension); -} - -static inline void qt_touch_extension_dummy(struct qt_touch_extension *qt_touch_extension) -{ - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_touch_extension, - QT_TOUCH_EXTENSION_DUMMY); -} - -/* wayland-qt-windowmanager.h */ - -extern const struct wl_interface qt_windowmanager_interface; - -struct qt_windowmanager_listener -{ - /** - * hints - (none) - * @show_is_fullscreen: (none) - */ - void (*hints)(void *data, - struct qt_windowmanager *qt_windowmanager, - int32_t show_is_fullscreen); - /** - * quit - (none) - */ - void (*quit)(void *data, - struct qt_windowmanager *qt_windowmanager); -}; - -static inline int qt_windowmanager_add_listener(struct qt_windowmanager *qt_windowmanager, - const struct qt_windowmanager_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *)qt_windowmanager, - (void (**)(void))listener, data); -} - -#define QT_WINDOWMANAGER_OPEN_URL 0 - -static inline void qt_windowmanager_set_user_data(struct qt_windowmanager *qt_windowmanager, void *user_data) -{ - WAYLAND_wl_proxy_set_user_data((struct wl_proxy *)qt_windowmanager, user_data); -} - -static inline void *qt_windowmanager_get_user_data(struct qt_windowmanager *qt_windowmanager) -{ - return WAYLAND_wl_proxy_get_user_data((struct wl_proxy *)qt_windowmanager); -} - -static inline void qt_windowmanager_destroy(struct qt_windowmanager *qt_windowmanager) -{ - WAYLAND_wl_proxy_destroy((struct wl_proxy *)qt_windowmanager); -} - -static inline void qt_windowmanager_open_url(struct qt_windowmanager *qt_windowmanager, uint32_t remaining, const char *url) -{ - WAYLAND_wl_proxy_marshal((struct wl_proxy *)qt_windowmanager, - QT_WINDOWMANAGER_OPEN_URL, remaining, url); -} - -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - -#endif /* SDL_waylandtouch_h_ */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index b7d8d05a33a7f..d4a30bdf05465 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -32,7 +32,6 @@ #include "SDL_waylandopengles.h" #include "SDL_waylandmouse.h" #include "SDL_waylandkeyboard.h" -#include "SDL_waylandtouch.h" #include "SDL_waylandclipboard.h" #include "SDL_waylandvulkan.h" @@ -711,23 +710,6 @@ static void Wayland_init_xdg_output(SDL_VideoData *d) } } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH -static void windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager, - int32_t show_is_fullscreen) -{ -} - -static void windowmanager_quit(void *data, struct qt_windowmanager *qt_windowmanager) -{ - SDL_SendQuit(); -} - -static const struct qt_windowmanager_listener windowmanager_listener = { - windowmanager_hints, - windowmanager_quit, -}; -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - static void handle_ping_xdg_wm_base(void *data, struct xdg_wm_base *xdg, uint32_t serial) { xdg_wm_base_pong(xdg, serial); @@ -804,17 +786,6 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint if (d->input) { Wayland_RegisterTimestampListeners(d->input); } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - } else if (SDL_strcmp(interface, "qt_touch_extension") == 0) { - Wayland_touch_create(d, id); - } else if (SDL_strcmp(interface, "qt_surface_extension") == 0) { - d->surface_extension = wl_registry_bind(registry, id, - &qt_surface_extension_interface, 1); - } else if (SDL_strcmp(interface, "qt_windowmanager") == 0) { - d->windowmanager = wl_registry_bind(registry, id, - &qt_windowmanager_interface, 1); - qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d); -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ } } @@ -991,19 +962,6 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this) WAYLAND_xkb_context_unref(data->xkb_context); data->xkb_context = NULL; } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - if (data->windowmanager) { - qt_windowmanager_destroy(data->windowmanager); - data->windowmanager = NULL; - } - - if (data->surface_extension) { - qt_surface_extension_destroy(data->surface_extension); - data->surface_extension = NULL; - } - - Wayland_touch_destroy(data); -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ if (data->tablet_manager) { zwp_tablet_manager_v2_destroy((struct zwp_tablet_manager_v2 *)data->tablet_manager); diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index bc55ee3e67f29..461a2395bf30c 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -35,12 +35,6 @@ struct xkb_context; struct SDL_WaylandInput; struct SDL_WaylandTabletManager; -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH -struct SDL_WaylandTouch; -struct qt_surface_extension; -struct qt_windowmanager; -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - typedef struct { struct wl_cursor_theme *theme; @@ -84,12 +78,6 @@ struct SDL_VideoData struct SDL_WaylandTabletManager *tablet_manager; struct wl_list output_list; -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - struct SDL_WaylandTouch *touch; - struct qt_surface_extension *surface_extension; - struct qt_windowmanager *windowmanager; -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - int relative_mouse_mode; }; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index dce908cdd16a0..f0927f08cff18 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -30,7 +30,6 @@ #include "SDL_waylandevents_c.h" #include "SDL_waylandwindow.h" #include "SDL_waylandvideo.h" -#include "SDL_waylandtouch.h" #include "../../SDL_hints_c.h" #include "xdg-shell-client-protocol.h" @@ -1100,31 +1099,6 @@ static struct libdecor_frame_interface libdecor_frame_interface = { }; #endif -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH -static void handle_onscreen_visibility(void *data, - struct qt_extended_surface *qt_extended_surface, int32_t visible) -{ -} - -static void handle_set_generic_property(void *data, - struct qt_extended_surface *qt_extended_surface, const char *name, - struct wl_array *value) -{ -} - -static void handle_close(void *data, struct qt_extended_surface *qt_extended_surface) -{ - SDL_WindowData *window = (SDL_WindowData *)data; - SDL_SendWindowEvent(window->sdlwindow, SDL_EVENT_WINDOW_CLOSE_REQUESTED, 0, 0); -} - -static const struct qt_extended_surface_listener extended_surface_listener = { - handle_onscreen_visibility, - handle_set_generic_property, - handle_close, -}; -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - static void Wayland_HandlePreferredScaleChanged(SDL_WindowData *window_data, float factor) { const float old_factor = window_data->windowed_scale_factor; @@ -1785,92 +1759,6 @@ int Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOpe return 0; } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH -static void SDLCALL QtExtendedSurface_OnHintChanged(void *userdata, const char *name, - const char *oldValue, const char *newValue) -{ - struct qt_extended_surface *qt_extended_surface = userdata; - int i; - - static struct - { - const char *name; - int32_t value; - } orientations[] = { - { "portrait", QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION }, - { "landscape", QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION }, - { "inverted-portrait", QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION }, - { "inverted-landscape", QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION } - }; - - if (name == NULL) { - return; - } - - if (SDL_strcmp(name, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION) == 0) { - int32_t orientation = QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION; - - if (newValue != NULL) { - const char *value_attempt = newValue; - - orientation = 0; - while (value_attempt != NULL && *value_attempt != 0) { - const char *value_attempt_end = SDL_strchr(value_attempt, ','); - size_t value_attempt_len = (value_attempt_end != NULL) ? (value_attempt_end - value_attempt) - : SDL_strlen(value_attempt); - - for (i = 0; i < SDL_arraysize(orientations); i += 1) { - if ((value_attempt_len == SDL_strlen(orientations[i].name)) && - (SDL_strncasecmp(orientations[i].name, value_attempt, value_attempt_len) == 0)) { - orientation |= orientations[i].value; - break; - } - } - - value_attempt = (value_attempt_end != NULL) ? (value_attempt_end + 1) : NULL; - } - } - - qt_extended_surface_set_content_orientation(qt_extended_surface, orientation); - } else if (SDL_strcmp(name, SDL_HINT_QTWAYLAND_WINDOW_FLAGS) == 0) { - uint32_t flags = 0; - - if (newValue != NULL) { - char *tmp = SDL_strdup(newValue); - char *saveptr = NULL; - - char *flag = SDL_strtok_r(tmp, " ", &saveptr); - while (flag) { - if (SDL_strcmp(flag, "OverridesSystemGestures") == 0) { - flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES; - } else if (SDL_strcmp(flag, "StaysOnTop") == 0) { - flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP; - } else if (SDL_strcmp(flag, "BypassWindowManager") == 0) { - // See https://github.com/qtproject/qtwayland/commit/fb4267103d - flags |= 4 /* QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER */; - } - - flag = SDL_strtok_r(NULL, " ", &saveptr); - } - - SDL_free(tmp); - } - - qt_extended_surface_set_window_flags(qt_extended_surface, flags); - } -} - -static void QtExtendedSurface_Subscribe(struct qt_extended_surface *surface, const char *name) -{ - SDL_AddHintCallback(name, QtExtendedSurface_OnHintChanged, surface); -} - -static void QtExtendedSurface_Unsubscribe(struct qt_extended_surface *surface, const char *name) -{ - SDL_DelHintCallback(name, QtExtendedSurface_OnHintChanged, surface); -} -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - void Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { @@ -2173,16 +2061,6 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) data->surface_frame_callback = wl_surface_frame(data->surface); wl_callback_add_listener(data->surface_frame_callback, &surface_frame_listener, data); -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - if (c->surface_extension) { - data->extended_surface = qt_surface_extension_get_extended_surface( - c->surface_extension, data->surface); - - QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION); - QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS); - } -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - if (window->flags & SDL_WINDOW_TRANSPARENT) { if (_this->gl_config.alpha_size == 0) { _this->gl_config.alpha_size = 8; @@ -2202,14 +2080,6 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) #endif } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - if (data->extended_surface) { - qt_extended_surface_set_user_data(data->extended_surface, data); - qt_extended_surface_add_listener(data->extended_surface, - &extended_surface_listener, data); - } -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - if (c->relative_mouse_mode) { Wayland_input_lock_pointer(c->input); } @@ -2434,13 +2304,6 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) wl_callback_destroy(wind->surface_frame_callback); } -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - if (wind->extended_surface) { - QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION); - QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS); - qt_extended_surface_destroy(wind->extended_surface); - } -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ wl_surface_destroy(wind->surface); SDL_free(wind); diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index dc13561adad54..a7d9ba4e9e679 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -102,10 +102,6 @@ struct SDL_WindowData SDL_AtomicInt swap_interval_ready; -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - struct qt_extended_surface *extended_surface; -#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ - SDL_DisplayData **outputs; int num_outputs; From 9458cbf75e8a52b5290552984845218ceb6fc8bb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 09:14:17 -0800 Subject: [PATCH 268/725] Removed unused SDL_OSEvent --- include/SDL3/SDL_events.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index ee4e43d9626dd..427e9416b7a49 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -559,15 +559,6 @@ typedef struct SDL_QuitEvent Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_QuitEvent; -/** - * OS Specific event - */ -typedef struct SDL_OSEvent -{ - Uint32 type; /**< ::SDL_EVENT_QUIT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ -} SDL_OSEvent; - /** * A user-defined event type (event.user.*) */ From b5057edf29a1ba0902226e34b1af3ffba0a63cdb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 09:23:26 -0800 Subject: [PATCH 269/725] Remove unused SDL_TextureModulate enum Fixes https://github.com/libsdl-org/SDL/issues/6387 --- include/SDL3/SDL_render.h | 10 ---------- src/render/SDL_render.c | 10 ---------- src/render/SDL_sysrender.h | 1 - 3 files changed, 21 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 120c3968fd600..0a58fadf5fdc1 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -115,16 +115,6 @@ typedef enum SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */ } SDL_TextureAccess; -/** - * The texture channel modulation used in SDL_RenderTexture(). - */ -typedef enum -{ - SDL_TEXTUREMODULATE_NONE = 0x00000000, /**< No modulation */ - SDL_TEXTUREMODULATE_COLOR = 0x00000001, /**< srcC = srcC * color */ - SDL_TEXTUREMODULATE_ALPHA = 0x00000002 /**< srcA = srcA * alpha */ -} SDL_TextureModulate; - /** * Flip constants for SDL_RenderTextureRotated */ diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index dfcd8a97d0f51..b4dc16fe5e068 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1408,11 +1408,6 @@ int SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b) { CHECK_TEXTURE_MAGIC(texture, -1); - if (r < 255 || g < 255 || b < 255) { - texture->modMode |= SDL_TEXTUREMODULATE_COLOR; - } else { - texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR; - } texture->color.r = r; texture->color.g = g; texture->color.b = b; @@ -1442,11 +1437,6 @@ int SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha) { CHECK_TEXTURE_MAGIC(texture, -1); - if (alpha < 255) { - texture->modMode |= SDL_TEXTUREMODULATE_ALPHA; - } else { - texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA; - } texture->color.a = alpha; if (texture->native) { return SDL_SetTextureAlphaMod(texture->native, alpha); diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 38bc703b3cb3c..afa2f652352b4 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -65,7 +65,6 @@ struct SDL_Texture int access; /**< SDL_TextureAccess */ int w; /**< The width of the texture */ int h; /**< The height of the texture */ - int modMode; /**< The texture modulation mode */ SDL_BlendMode blendMode; /**< The texture blend mode */ SDL_ScaleMode scaleMode; /**< The texture scale mode */ SDL_Color color; /**< Texture modulation values */ From 4106697774ff533b2eeb223f87103fa464fc598a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 16:24:08 -0800 Subject: [PATCH 270/725] Make sure we include the null terminator in XLookupStringAsUTF8() Fixes https://github.com/libsdl-org/SDL/issues/6728 --- src/video/x11/SDL_x11events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 9c7afcf445208..2c8ed6b5900e0 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -779,7 +779,7 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int { int result = X11_XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return, status_in_out); if (IsHighLatin1(buffer_return, result)) { - char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", buffer_return, result); + char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", buffer_return, result + 1); if (utf8_text) { SDL_strlcpy(buffer_return, utf8_text, bytes_buffer); SDL_free(utf8_text); From 28e623c504558c0e438011207bcee254003b0f81 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 18:08:11 -0800 Subject: [PATCH 271/725] Added a mapping for the Atari VCS controller connected over Bluetooth (thanks @WizzardSK!) Fixes https://github.com/libsdl-org/SDL/issues/7116 --- src/joystick/SDL_gamepad_db.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 00e6a244eeec7..bbeb0260c7700 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -593,6 +593,7 @@ static const char *s_GamepadMappings[] = { "05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,", "03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", "05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,", + "05000000503200000210000000000000128804098,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,", "030000005e0400008e02000047010000,Atari Xbox 360 Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", From 521bbcc15e8ccc541a14e870159345ff616db90c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 21:44:18 -0800 Subject: [PATCH 272/725] Destroy the window surface if we've created it for the software renderer Fixes https://github.com/libsdl-org/SDL/issues/8011 --- src/render/software/SDL_render_sw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 762680f219a7b..24e15c3e34b81 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -990,8 +990,12 @@ static void SW_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) static void SW_DestroyRenderer(SDL_Renderer *renderer) { + SDL_Window *window = renderer->window; SW_RenderData *data = (SW_RenderData *)renderer->driverdata; + if (window) { + SDL_DestroyWindowSurface(window); + } SDL_free(data); SDL_free(renderer); } @@ -1140,8 +1144,6 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) SW_SelectBestFormats(renderer, surface->format->format); - SW_ActivateRenderer(renderer); - return renderer; } From 04e98d2236c02cbb10d0b88e1782b4dd4bf9d44a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 21:57:15 -0800 Subject: [PATCH 273/725] Added missing calls to SDL_InvalidParamError("surface") --- src/video/SDL_surface.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index ac0d97e410f93..00e747fcb0c7c 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -285,7 +285,7 @@ int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) int flags; if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } flags = surface->map->info.flags; @@ -468,7 +468,7 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) int flags; if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } surface->map->info.r = r; @@ -490,7 +490,7 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b) { if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } if (r) { @@ -510,7 +510,7 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) int flags; if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } surface->map->info.a = alpha; @@ -530,7 +530,7 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha) { if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } if (alpha) { @@ -544,7 +544,7 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode) int flags, status; if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } status = 0; @@ -581,7 +581,7 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode) int SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode) { if (surface == NULL) { - return -1; + return SDL_InvalidParamError("surface"); } if (blendMode == NULL) { From fea2504a377ef707d61601a0cd5c7016e547143b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 22:02:27 -0800 Subject: [PATCH 274/725] Prioritize the pipewire audio driver over ALSA ALSA is used very rarely anymore and the pipewire ALSA emulation isn't as good as using pipewire directly. The Pulseaudio emulation is very good, and Pulseaudio is still commonly available on Linux systems, so we'll default to that first and fall back to pipewire if it's not available. We'll finally try ALSA, to handle very old systems. Fixes https://github.com/libsdl-org/SDL/issues/7541 --- src/audio/SDL_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index ef93f82817254..f8f24c3920877 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -30,6 +30,9 @@ static const AudioBootStrap *const bootstrap[] = { #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO &PULSEAUDIO_bootstrap, #endif +#ifdef SDL_AUDIO_DRIVER_PIPEWIRE + &PIPEWIRE_bootstrap, +#endif #ifdef SDL_AUDIO_DRIVER_ALSA &ALSA_bootstrap, #endif @@ -78,9 +81,6 @@ static const AudioBootStrap *const bootstrap[] = { #ifdef SDL_AUDIO_DRIVER_JACK &JACK_bootstrap, #endif -#ifdef SDL_AUDIO_DRIVER_PIPEWIRE - &PIPEWIRE_bootstrap, -#endif #ifdef SDL_AUDIO_DRIVER_OSS &DSP_bootstrap, #endif From 415283ef38918321c177a00244986a06b6b4485e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 23:44:58 -0800 Subject: [PATCH 275/725] Fixed checking for linux/input.h --- CMakeLists.txt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5159cbd5864fe..a1beb5f84af66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1479,14 +1479,12 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) if(UNIX) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/unix/*.c") - if (HAVE_LINUX_INPUT_H) - check_c_source_compiles(" - #include - #ifndef EVIOCGNAME - #error EVIOCGNAME() ioctl not available - #endif - int main(int argc, char** argv) { return 0; }" HAVE_LINUX_INPUT_H) - endif() + check_c_source_compiles(" + #include + #ifndef EVIOCGNAME + #error EVIOCGNAME() ioctl not available + #endif + int main(int argc, char** argv) { return 0; }" HAVE_LINUX_INPUT_H) if(LINUX) check_c_source_compiles(" From ed1e0c1530e7902d6562f8e8cab2aa38e829a834 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 00:11:55 -0800 Subject: [PATCH 276/725] Make sure joysticks are locked when adding and removing them Fixes https://github.com/libsdl-org/SDL/issues/8146 --- src/joystick/linux/SDL_sysjoystick.c | 90 ++++++++++++++++++---------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 7d9a62ff06898..9d776f5435ecf 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -145,8 +145,8 @@ typedef enum static EnumerationMethod enumeration_method = ENUMERATION_UNSET; static SDL_bool IsJoystickJSNode(const char *node); -static int MaybeAddDevice(const char *path); -static int MaybeRemoveDevice(const char *path); +static void MaybeAddDevice(const char *path); +static void MaybeRemoveDevice(const char *path); /* A linked list of available joysticks */ typedef struct SDL_joylist_item @@ -176,10 +176,10 @@ typedef struct SDL_sensorlist_item } SDL_sensorlist_item; static SDL_bool SDL_classic_joysticks = SDL_FALSE; -static SDL_joylist_item *SDL_joylist = NULL; -static SDL_joylist_item *SDL_joylist_tail = NULL; -static int numjoysticks = 0; -static SDL_sensorlist_item *SDL_sensorlist = NULL; +static SDL_joylist_item *SDL_joylist SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static SDL_joylist_item *SDL_joylist_tail SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static int numjoysticks SDL_GUARDED_BY(SDL_joystick_lock) = 0; +static SDL_sensorlist_item *SDL_sensorlist SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static int inotify_fd = -1; static Uint64 last_joy_detect_time; @@ -384,7 +384,7 @@ static void FreeSensorlistItem(SDL_sensorlist_item *item) SDL_free(item); } -static int MaybeAddDevice(const char *path) +static void MaybeAddDevice(const char *path) { struct stat sb; int fd = -1; @@ -394,28 +394,30 @@ static int MaybeAddDevice(const char *path) SDL_sensorlist_item *item_sensor; if (path == NULL) { - return -1; + return; } if (stat(path, &sb) == -1) { - return -1; + return; } + SDL_LockJoysticks(); + /* Check to make sure it's not already in list. */ for (item = SDL_joylist; item != NULL; item = item->next) { if (sb.st_rdev == item->devnum) { - return -1; /* already have this one */ + goto done; /* already have this one */ } } for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) { if (sb.st_rdev == item_sensor->devnum) { - return -1; /* already have this one */ + goto done; /* already have this one */ } } fd = open(path, O_RDONLY | O_CLOEXEC, 0); if (fd < 0) { - return -1; + goto done; } #ifdef DEBUG_INPUT_EVENTS @@ -430,7 +432,7 @@ static int MaybeAddDevice(const char *path) item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); if (item == NULL) { SDL_free(name); - return -1; + goto done; } item->devnum = sb.st_rdev; @@ -440,7 +442,7 @@ static int MaybeAddDevice(const char *path) if ((item->path == NULL) || (item->name == NULL)) { FreeJoylistItem(item); - return -1; + goto done; } item->device_instance = SDL_GetNextObjectID(); @@ -455,7 +457,7 @@ static int MaybeAddDevice(const char *path) ++numjoysticks; SDL_PrivateJoystickAdded(item->device_instance); - return numjoysticks; + goto done; } if (IsSensor(path, fd)) { @@ -465,27 +467,30 @@ static int MaybeAddDevice(const char *path) close(fd); item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item)); if (item_sensor == NULL) { - return -1; + goto done; } item_sensor->devnum = sb.st_rdev; item_sensor->path = SDL_strdup(path); if (item_sensor->path == NULL) { FreeSensorlistItem(item_sensor); - return -1; + goto done; } item_sensor->next = SDL_sensorlist; SDL_sensorlist = item_sensor; - return -1; + goto done; } close(fd); - return -1; +done: + SDL_UnlockJoysticks(); } static void RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev) { + SDL_AssertJoysticksLocked(); + if (item->hwdata) { item->hwdata->item = NULL; } @@ -510,6 +515,8 @@ static void RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev) static void RemoveSensorlistItem(SDL_sensorlist_item *item, SDL_sensorlist_item *prev) { + SDL_AssertJoysticksLocked(); + if (item->hwdata) { item->hwdata->item_sensor = NULL; } @@ -526,7 +533,7 @@ static void RemoveSensorlistItem(SDL_sensorlist_item *item, SDL_sensorlist_item FreeSensorlistItem(item); } -static int MaybeRemoveDevice(const char *path) +static void MaybeRemoveDevice(const char *path) { SDL_joylist_item *item; SDL_joylist_item *prev = NULL; @@ -534,15 +541,15 @@ static int MaybeRemoveDevice(const char *path) SDL_sensorlist_item *prev_sensor = NULL; if (path == NULL) { - return -1; + return; } + SDL_LockJoysticks(); for (item = SDL_joylist; item != NULL; item = item->next) { /* found it, remove it. */ if (SDL_strcmp(path, item->path) == 0) { - const int retval = item->device_instance; RemoveJoylistItem(item, prev); - return retval; + goto done; } prev = item; } @@ -550,21 +557,24 @@ static int MaybeRemoveDevice(const char *path) /* found it, remove it. */ if (SDL_strcmp(path, item_sensor->path) == 0) { RemoveSensorlistItem(item_sensor, prev_sensor); - return -1; + goto done; } prev_sensor = item_sensor; } - - return -1; +done: + SDL_UnlockJoysticks(); } static void HandlePendingRemovals(void) { SDL_joylist_item *prev = NULL; - SDL_joylist_item *item = SDL_joylist; + SDL_joylist_item *item = NULL; SDL_sensorlist_item *prev_sensor = NULL; - SDL_sensorlist_item *item_sensor = SDL_sensorlist; + SDL_sensorlist_item *item_sensor = NULL; + + SDL_AssertJoysticksLocked(); + item = SDL_joylist; while (item != NULL) { if (item->hwdata && item->hwdata->gone) { RemoveJoylistItem(item, prev); @@ -580,6 +590,7 @@ static void HandlePendingRemovals(void) } } + item_sensor = SDL_sensorlist; while (item_sensor != NULL) { if (item_sensor->hwdata && item_sensor->hwdata->sensor_gone) { RemoveSensorlistItem(item_sensor, prev_sensor); @@ -616,6 +627,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG } *device_instance = item->device_instance = SDL_GetNextObjectID(); + SDL_LockJoysticks(); if (SDL_joylist_tail == NULL) { SDL_joylist = SDL_joylist_tail = item; } else { @@ -627,6 +639,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG ++numjoysticks; SDL_PrivateJoystickAdded(item->device_instance); + SDL_UnlockJoysticks(); return SDL_TRUE; } @@ -636,14 +649,16 @@ static void SteamControllerDisconnectedCallback(SDL_JoystickID device_instance) SDL_joylist_item *item; SDL_joylist_item *prev = NULL; + SDL_LockJoysticks(); for (item = SDL_joylist; item != NULL; item = item->next) { /* found it, remove it. */ if (item->device_instance == device_instance) { RemoveJoylistItem(item, prev); - return; + break; } prev = item; } + SDL_UnlockJoysticks(); } static int StrHasPrefix(const char *string, const char *prefix) @@ -969,17 +984,22 @@ static int LINUX_JoystickInit(void) static int LINUX_JoystickGetCount(void) { + SDL_AssertJoysticksLocked(); + return numjoysticks; } static SDL_joylist_item *GetJoystickByDevIndex(int device_index) { - SDL_joylist_item *item = SDL_joylist; + SDL_joylist_item *item; + + SDL_AssertJoysticksLocked(); if ((device_index < 0) || (device_index >= numjoysticks)) { return NULL; } + item = SDL_joylist; while (device_index > 0) { SDL_assert(item != NULL); device_index--; @@ -1382,6 +1402,8 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item) char uniq_item[128]; int fd_item = -1; + SDL_AssertJoysticksLocked(); + if (item == NULL || SDL_sensorlist == NULL) { return NULL; } @@ -1435,11 +1457,12 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item) */ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) { - SDL_joylist_item *item = GetJoystickByDevIndex(device_index); - SDL_sensorlist_item *item_sensor = GetSensor(item); + SDL_joylist_item *item; + SDL_sensorlist_item *item_sensor; SDL_AssertJoysticksLocked(); + item = GetJoystickByDevIndex(device_index); if (item == NULL) { return SDL_SetError("No such device"); } @@ -1451,6 +1474,7 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) return SDL_OutOfMemory(); } + item_sensor = GetSensor(item); if (PrepareJoystickHwdata(joystick, item, item_sensor) == -1) { SDL_free(joystick->hwdata); joystick->hwdata = NULL; @@ -2051,6 +2075,8 @@ static void LINUX_JoystickQuit(void) SDL_sensorlist_item *item_sensor = NULL; SDL_sensorlist_item *next_sensor = NULL; + SDL_AssertJoysticksLocked(); + if (inotify_fd >= 0) { close(inotify_fd); inotify_fd = -1; From 8049af3355975c25bc5ac29ac518893d776a769b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 00:34:50 -0800 Subject: [PATCH 277/725] Assume all 8BitDo Xbox controllers have a share button Fixes https://github.com/libsdl-org/SDL/issues/8174 --- src/joystick/SDL_joystick.c | 10 +++++++--- src/joystick/usb_ids.h | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index cd17d285cdc3f..439b1c179ab4a 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2503,9 +2503,13 @@ SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) } } if (vendor_id == USB_VENDOR_8BITDO) { - if (product_id == USB_PRODUCT_8BITDO_XBOX_CONTROLLER) { - return SDL_TRUE; - } + /* 8BitDo started making Xbox form factor controllers after the Series X + * release, so we'll assume for now that they all have the share button. + * + * We know for sure that the Ultimate Wired Controller for Xbox (0x2002) + * and the Ultimate Wireless / Pro 2 Wired Controller (0x3106) have them. + */ + return SDL_TRUE; } if (vendor_id == USB_VENDOR_GAMESIR) { if (product_id == USB_PRODUCT_GAMESIR_G7) { diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 3da1c24991321..172f56441984c 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -55,7 +55,6 @@ #define USB_VENDOR_VALVE 0x28de #define USB_VENDOR_ZEROPLUS 0x0c12 -#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER 0x2002 #define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419 #define USB_PRODUCT_ASTRO_C40_XBOX360 0x0024 #define USB_PRODUCT_BACKBONE_ONE_IOS 0x0103 From 15bc12165ab56e6fbf93b8f3d18f2a0bb5854d8c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 00:42:42 -0800 Subject: [PATCH 278/725] Actually we need to enumerate the 8BitDo Xbox SKUs At the point we're calling SDL_IsJoystickXboxSeriesX(), we don't know for sure that the controller is an Xbox controller. Fixes https://github.com/libsdl-org/SDL/issues/8174 --- src/joystick/SDL_joystick.c | 11 ++++------- src/joystick/usb_ids.h | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 439b1c179ab4a..062d0626af98d 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2503,13 +2503,10 @@ SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) } } if (vendor_id == USB_VENDOR_8BITDO) { - /* 8BitDo started making Xbox form factor controllers after the Series X - * release, so we'll assume for now that they all have the share button. - * - * We know for sure that the Ultimate Wired Controller for Xbox (0x2002) - * and the Ultimate Wireless / Pro 2 Wired Controller (0x3106) have them. - */ - return SDL_TRUE; + if (product_id == USB_PRODUCT_8BITDO_XBOX_CONTROLLER1 || + product_id == USB_PRODUCT_8BITDO_XBOX_CONTROLLER2) { + return SDL_TRUE; + } } if (vendor_id == USB_VENDOR_GAMESIR) { if (product_id == USB_PRODUCT_GAMESIR_G7) { diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 172f56441984c..875e988955969 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -55,6 +55,8 @@ #define USB_VENDOR_VALVE 0x28de #define USB_VENDOR_ZEROPLUS 0x0c12 +#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER1 0x2002 /* Ultimate Wired Controller for Xbox */ +#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER2 0x3106 /* Ultimate Wireless / Pro 2 Wired Controller */ #define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419 #define USB_PRODUCT_ASTRO_C40_XBOX360 0x0024 #define USB_PRODUCT_BACKBONE_ONE_IOS 0x0103 From 80b2bbad21f608b0ec2c508813cda60c26191714 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 01:34:42 -0800 Subject: [PATCH 279/725] Removed useless branch test Fixes https://github.com/libsdl-org/SDL/issues/8286 (cherry picked from commit e5ccc80aba60f4132823d71ea6952c87f2392d06) (cherry picked from commit 7e11bd1ac18855e804559ec3eb9d845e4bf30271) --- src/render/software/SDL_triangle.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index 090ebdf4ff461..576c8d9899239 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -338,12 +338,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin if (is_uniform) { Uint32 color; if (tmp) { - if (dst->format->Amask) { - color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a); - } else { - // color = SDL_MapRGB(tmp->format, c0.r, c0.g, c0.b); - color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a); - } + color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a); } else { color = SDL_MapRGBA(dst->format, c0.r, c0.g, c0.b, c0.a); } From 0a1b6b270f2048bbf777b70122aa7600561bc6e9 Mon Sep 17 00:00:00 2001 From: Wohlstand Date: Wed, 8 Nov 2023 13:33:56 +0300 Subject: [PATCH 280/725] sdlchecks.cmake: Clarified the reason why shared X11 mode doesn't work #6778 --- cmake/sdlchecks.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index e6beb747467a7..f4723b312d08a 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -307,7 +307,9 @@ macro(CheckX11) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/x11/*.c") set(SDL_VIDEO_DRIVER_X11 1) - # !!! FIXME: why is this disabled for Apple? + # Note: Disabled on Apple because the dynamic mode backend for X11 doesn't + # work properly on Apple during several issues like inconsistent paths + # among platforms. See #6778 (https://github.com/libsdl-org/SDL/issues/6778) if(APPLE) set(SDL_X11_SHARED OFF) endif() From ce9e1bd32485ae8a024d8147e3aa3a36f0cb0a19 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 03:25:22 -0800 Subject: [PATCH 281/725] Don't mute the console input if we can't read the keyboard This makes sure you can hit Ctrl-C if you don't have permission to access the raw keyboard device. Fixes https://github.com/libsdl-org/SDL/issues/4812 --- src/core/linux/SDL_evdev.c | 34 ++++++++++++++++++++-- src/core/linux/SDL_evdev.h | 1 + src/core/linux/SDL_evdev_kbd.c | 53 ++++++++++++++++++++++------------ src/core/linux/SDL_evdev_kbd.h | 1 + 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index c0bde0d7e92c6..4532857938319 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -73,6 +73,7 @@ typedef struct SDL_evdevlist_item { char *path; int fd; + int udev_class; /* TODO: use this for every device, not just touchscreen */ SDL_bool out_of_sync; @@ -155,6 +156,15 @@ static int SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled) return 0; } +static void SDL_EVDEV_UpdateKeyboardMute(void) +{ + if (SDL_EVDEV_GetDeviceCount(SDL_UDEV_DEVICE_KEYBOARD) > 0) { + SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_TRUE); + } else { + SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_FALSE); + } +} + int SDL_EVDEV_Init(void) { if (_this == NULL) { @@ -208,6 +218,8 @@ int SDL_EVDEV_Init(void) #endif /* SDL_USE_LIBUDEV */ _this->kbd = SDL_EVDEV_kbd_init(); + + SDL_EVDEV_UpdateKeyboardMute(); } SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode; @@ -231,13 +243,13 @@ void SDL_EVDEV_Quit(void) SDL_UDEV_Quit(); #endif /* SDL_USE_LIBUDEV */ - SDL_EVDEV_kbd_quit(_this->kbd); - /* Remove existing devices */ while (_this->first != NULL) { SDL_EVDEV_device_removed(_this->first->path); } + SDL_EVDEV_kbd_quit(_this->kbd); + SDL_assert(_this->first == NULL); SDL_assert(_this->last == NULL); SDL_assert(_this->num_devices == 0); @@ -276,6 +288,19 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl } #endif /* SDL_USE_LIBUDEV */ +int SDL_EVDEV_GetDeviceCount(int device_class) +{ + SDL_evdevlist_item *item; + int count = 0; + + for (item = _this->first; item != NULL; item = item->next) { + if ((item->udev_class & device_class) == device_class) { + ++count; + } + } + return count; +} + void SDL_EVDEV_Poll(void) { struct input_event events[32]; @@ -864,6 +889,8 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) return SDL_OutOfMemory(); } + item->udev_class = udev_class; + if (ioctl(item->fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) { item->relative_mouse = test_bit(REL_X, relbit) && test_bit(REL_Y, relbit); item->high_res_wheel = test_bit(REL_WHEEL_HI_RES, relbit); @@ -900,6 +927,8 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) SDL_EVDEV_sync_device(item); + SDL_EVDEV_UpdateKeyboardMute(); + return _this->num_devices++; } @@ -926,6 +955,7 @@ static int SDL_EVDEV_device_removed(const char *dev_path) close(item->fd); SDL_free(item->path); SDL_free(item); + SDL_EVDEV_UpdateKeyboardMute(); _this->num_devices--; return 0; } diff --git a/src/core/linux/SDL_evdev.h b/src/core/linux/SDL_evdev.h index ba58b91aa3a62..b0c6c7ef0e491 100644 --- a/src/core/linux/SDL_evdev.h +++ b/src/core/linux/SDL_evdev.h @@ -30,6 +30,7 @@ struct input_event; extern int SDL_EVDEV_Init(void); extern void SDL_EVDEV_Quit(void); +extern int SDL_EVDEV_GetDeviceCount(int device_class); extern void SDL_EVDEV_Poll(void); extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event); diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index 2754e51e4d404..a58129dea1a02 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -84,6 +84,7 @@ static fn_handler_fn *fn_handler[] = { struct SDL_EVDEV_keyboard_state { int console_fd; + SDL_bool muted; int old_kbd_mode; unsigned short **key_maps; unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ @@ -332,20 +333,6 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE); } - /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ - if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) { - /* Mute the keyboard so keystrokes only generate evdev events - * and do not leak through to the console - */ - ioctl(kbd->console_fd, KDSKBMODE, K_OFF); - - /* Make sure to restore keyboard if application fails to call - * SDL_Quit before exit or fatal signal is raised. - */ - if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { - kbd_register_emerg_cleanup(kbd); - } - } return kbd; } @@ -355,12 +342,9 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) return; } - kbd_unregister_emerg_cleanup(); + SDL_EVDEV_kbd_set_muted(state, SDL_FALSE); if (state->console_fd >= 0) { - /* Restore the original keyboard mode */ - ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); - close(state->console_fd); state->console_fd = -1; } @@ -378,6 +362,39 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) SDL_free(state); } +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +{ + if (state == NULL) { + return; + } + + if (muted == state->muted) { + return; + } + + if (muted) { + /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ + if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) { + /* Mute the keyboard so keystrokes only generate evdev events + * and do not leak through to the console + */ + ioctl(state->console_fd, KDSKBMODE, K_OFF); + + /* Make sure to restore keyboard if application fails to call + * SDL_Quit before exit or fatal signal is raised. + */ + if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { + kbd_register_emerg_cleanup(state); + } + } + } else { + kbd_unregister_emerg_cleanup(); + + /* Restore the original keyboard mode */ + ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); + } +} + /* * Helper Functions. */ diff --git a/src/core/linux/SDL_evdev_kbd.h b/src/core/linux/SDL_evdev_kbd.h index 6d592ef28e42d..e00ca0b1445a6 100644 --- a/src/core/linux/SDL_evdev_kbd.h +++ b/src/core/linux/SDL_evdev_kbd.h @@ -26,6 +26,7 @@ struct SDL_EVDEV_keyboard_state; typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state; extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void); +extern void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted); extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down); extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state); From 7cc3e94eb22f2ee76742bfb4c101757fcb70c4b7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 03:36:47 -0800 Subject: [PATCH 282/725] Store the requested muted state --- src/core/linux/SDL_evdev_kbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index a58129dea1a02..d7db2615f69dc 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -393,6 +393,7 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) /* Restore the original keyboard mode */ ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); } + state->muted = muted; } /* From d9e6dcc650fd96c66d1177438d1e0ee9b624c21c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 04:45:29 -0800 Subject: [PATCH 283/725] Fixed FreeBSD build --- src/core/linux/SDL_evdev_kbd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index d7db2615f69dc..d841e072d12c0 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -826,6 +826,9 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) return NULL; } +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +{ +} void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down) { } From a4c6b38fef2ff046e38072200b096c03389bfa28 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 07:46:02 -0800 Subject: [PATCH 284/725] Fixed FreeBSD build --- src/core/freebsd/SDL_evdev_kbd_freebsd.c | 4 ++++ src/core/linux/SDL_evdev_kbd.c | 1 + 2 files changed, 5 insertions(+) diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c index a30988c8acadc..19a7a7114811e 100644 --- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -467,6 +467,10 @@ static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ } } +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +{ +} + void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down) { keymap_t key_map; diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index d841e072d12c0..fb3036cd4447a 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -829,6 +829,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) { } + void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down) { } From 8668943746d868806a362a3671b2c7769572df17 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 09:56:05 -0800 Subject: [PATCH 285/725] Standardized property names for internal SDL properties --- include/SDL3/SDL_properties.h | 2 ++ src/render/SDL_render.c | 2 +- src/video/SDL_video.c | 2 +- src/video/dummy/SDL_nullframebuffer.c | 2 +- src/video/n3ds/SDL_n3dsframebuffer.c | 2 +- src/video/offscreen/SDL_offscreenframebuffer.c | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 56356d6b8f5df..66d12f6140ce0 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -95,6 +95,8 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); /** * Set a property on a set of properties * + * By convention, the names of properties that SDL exposes on objects will start with "SDL.", and properties that SDL uses internally will start with "SDL.internal.". These should be considered read-only and should not be modified by applications. + * * \param props the properties to modify * \param name the name of the property to modify * \param value the new value of the property, or NULL to delete the property diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index b4dc16fe5e068..647cb84ffcf8e 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -43,7 +43,7 @@ this should probably be removed at some point in the future. --ryan. */ #define DONT_DRAW_WHILE_HIDDEN 0 #endif -#define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData" +#define SDL_WINDOWRENDERDATA "SDL.internal.window.renderer" #define CHECK_RENDERER_MAGIC(renderer, retval) \ if (!(renderer) || (renderer)->magic != &renderer_magic) { \ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 665009100de2c..9b1a199fb45ae 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -183,7 +183,7 @@ static SDL_bool DisableUnsetFullscreenOnMinimize(SDL_VideoDevice *_this) /* Support for framebuffer emulation using an accelerated renderer */ -#define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData" +#define SDL_WINDOWTEXTUREDATA "SDL.internal.window.texturedata" typedef struct { diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index efdd6a377ebae..b2ef604458f07 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -25,7 +25,7 @@ #include "../SDL_sysvideo.h" #include "SDL_nullframebuffer_c.h" -#define DUMMY_SURFACE "_SDL_DummySurface" +#define DUMMY_SURFACE "SDL.internal.window.surface" static void CleanupSurface(void *userdata, void *value) { diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 57a55f5aab144..b2e0d93fe2c17 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -26,7 +26,7 @@ #include "SDL_n3dsframebuffer_c.h" #include "SDL_n3dsvideo.h" -#define N3DS_SURFACE "_SDL_N3DSSurface" +#define N3DS_SURFACE "SDL.internal.window.surface" typedef struct { diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index d51443932a504..cd5feba647121 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -25,7 +25,7 @@ #include "../SDL_sysvideo.h" #include "SDL_offscreenframebuffer_c.h" -#define OFFSCREEN_SURFACE "_SDL_DummySurface" +#define OFFSCREEN_SURFACE "SDL.internal.window.surface" static void CleanupSurface(void *userdata, void *value) { From a02afbaea58e00054144827f00bca8a2c88abcf0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 09:57:33 -0800 Subject: [PATCH 286/725] Clean up window properties when the window is destroyed --- src/video/SDL_video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 9b1a199fb45ae..3ef3cd98a474c 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3533,6 +3533,8 @@ void SDL_DestroyWindow(SDL_Window *window) SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_DESTROYED, 0, 0); + SDL_DestroyProperties(window->props); + /* If this is a child window, unlink it from its siblings */ if (window->parent) { if (window->next_sibling) { From 0cd4b7d3e389ba5e7e74c6bd65da7e52f9b7a92c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 09:58:49 -0800 Subject: [PATCH 287/725] Added display properties --- include/SDL3/SDL_video.h | 14 ++++++++++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/video/SDL_sysvideo.h | 2 ++ src/video/SDL_video.c | 13 +++++++++++++ 6 files changed, 32 insertions(+) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 155adb53723a6..3f79502556f02 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -339,6 +339,20 @@ extern DECLSPEC SDL_DisplayID *SDLCALL SDL_GetDisplays(int *count); */ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); +/** + * Get the properties associated with a display. + * + * \param displayID the instance ID of the display to query + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID); + /** * Get the name of a display in UTF-8 encoding. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 4d1999c23937c..651431e6745e3 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -923,6 +923,7 @@ SDL3_0.0.0 { SDL_RWprintf; SDL_RWvprintf; SDL_AllocateEventMemory; + SDL_GetDisplayProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 799e29f2f2388..08e9878eea2a0 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -948,3 +948,4 @@ #define SDL_RWprintf SDL_RWprintf_REAL #define SDL_RWvprintf SDL_RWvprintf_REAL #define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL +#define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 048aba36fef78..6943830f1849c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -981,3 +981,4 @@ SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b), SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return) SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index b318d75db0b74..3db2d85b1fedf 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -146,6 +146,8 @@ struct SDL_VideoDisplay SDL_VideoDevice *device; + SDL_PropertiesID props; + SDL_DisplayData *driverdata; }; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 3ef3cd98a474c..280260785ab62 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -717,6 +717,7 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_REMOVED, 0); } + SDL_DestroyProperties(display->props); SDL_free(display->name); SDL_ResetFullscreenDisplayModes(display); SDL_free(display->desktop_mode.driverdata); @@ -820,6 +821,18 @@ SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window) return SDL_GetDisplayDriverData(SDL_GetDisplayForWindow(window)); } +SDL_PropertiesID SDL_GetDisplayProperties(SDL_DisplayID displayID) +{ + SDL_VideoDisplay *display = SDL_GetVideoDisplay(displayID); + + CHECK_DISPLAY_MAGIC(display, 0); + + if (display->props == 0) { + display->props = SDL_CreateProperties(); + } + return display->props; +} + const char *SDL_GetDisplayName(SDL_DisplayID displayID) { SDL_VideoDisplay *display = SDL_GetVideoDisplay(displayID); From a1941fad6ceedfa9e90839aaff922a9185e592e9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 10:44:33 -0800 Subject: [PATCH 288/725] Replaced SDL_RenderGetD3D11Device(), SDL_RenderGetD3D12Device(), and SDL_RenderGetD3D9Device() with renderer properties. --- docs/README-migration.md | 7 ++-- include/SDL3/SDL_oldnames.h | 8 ---- include/SDL3/SDL_render.h | 5 +++ include/SDL3/SDL_system.h | 52 ------------------------ src/dynapi/SDL_dynapi.sym | 3 -- src/dynapi/SDL_dynapi_overrides.h | 3 -- src/dynapi/SDL_dynapi_procs.h | 3 -- src/render/SDL_render.c | 14 +++---- src/render/SDL_render_unsupported.c | 27 ------------ src/render/SDL_sysrender.h | 2 + src/render/direct3d/SDL_render_d3d.c | 28 ++----------- src/render/direct3d11/SDL_render_d3d11.c | 28 ++----------- src/render/direct3d12/SDL_render_d3d12.c | 33 ++------------- test/testffmpeg.c | 3 +- 14 files changed, 30 insertions(+), 186 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 7ddd7fb90e648..60b9209c7baff 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1152,9 +1152,10 @@ The following functions have been renamed: SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. -The following functions have been renamed: -* SDL_RenderGetD3D11Device() => SDL_GetRenderD3D11Device() -* SDL_RenderGetD3D9Device() => SDL_GetRenderD3D9Device() +The following functions have been removed: +* SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property +* SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property +* SDL_RenderGetD3D9Device() - replaced with the "SDL.renderer.d3d9.device" property ## SDL_syswm.h diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index bf5fd2a0a0325..5e266c1155954 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -462,10 +462,6 @@ #define SDL_UpperBlit SDL_BlitSurface #define SDL_UpperBlitScaled SDL_BlitSurfaceScaled -/* ##SDL_system.h */ -#define SDL_RenderGetD3D11Device SDL_GetRenderD3D11Device -#define SDL_RenderGetD3D9Device SDL_GetRenderD3D9Device - /* ##SDL_thread.h */ #define SDL_TLSCleanup SDL_CleanupTLS #define SDL_TLSCreate SDL_CreateTLS @@ -911,10 +907,6 @@ #define SDL_UpperBlit SDL_UpperBlit_renamed_SDL_BlitSurface #define SDL_UpperBlitScaled SDL_UpperBlitScaled_renamed_SDL_BlitSurfaceScaled -/* ##SDL_system.h */ -#define SDL_RenderGetD3D11Device SDL_RenderGetD3D11Device_renamed_SDL_GetRenderD3D11Device -#define SDL_RenderGetD3D9Device SDL_RenderGetD3D9Device_renamed_SDL_GetRenderD3D9Device - /* ##SDL_thread.h */ #define SDL_TLSCleanup SDL_TLSCleanup_renamed_SDL_CleanupTLS #define SDL_TLSCreate SDL_TLSCreate_renamed_SDL_CreateTLS diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 0a58fadf5fdc1..9fde47f2c6b3b 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -309,6 +309,11 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * + * The following properties are provided by SDL: + * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer + * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer + * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer + * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index f2c822112a788..14a25e00a13f1 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -73,60 +73,8 @@ extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook ca */ extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID); -typedef struct IDirect3DDevice9 IDirect3DDevice9; - -/** - * Get the D3D9 device associated with a renderer. - * - * Once you are done using the device, you should release it to avoid a - * resource leak. - * - * \param renderer the renderer from which to get the associated D3D device - * \returns the D3D9 device associated with given renderer or NULL if it is - * not a D3D9 renderer; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_GetRenderD3D9Device(SDL_Renderer * renderer); - -typedef struct ID3D11Device ID3D11Device; - -/** - * Get the D3D11 device associated with a renderer. - * - * Once you are done using the device, you should release it to avoid a - * resource leak. - * - * \param renderer the renderer from which to get the associated D3D11 device - * \returns the D3D11 device associated with given renderer or NULL if it is - * not a D3D11 renderer; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC ID3D11Device* SDLCALL SDL_GetRenderD3D11Device(SDL_Renderer * renderer); - #endif /* defined(__WIN32__) || defined(__WINGDK__) */ -#if defined(__WIN32__) || defined(__GDK__) - -typedef struct ID3D12Device ID3D12Device; - -/** - * Get the D3D12 device associated with a renderer. - * - * Once you are done using the device, you should release it to avoid a - * resource leak. - * - * \param renderer the renderer from which to get the associated D3D12 device - * \returns the D3D12 device associated with given renderer or NULL if it is - * not a D3D12 renderer; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC ID3D12Device* SDLCALL SDL_RenderGetD3D12Device(SDL_Renderer* renderer); - -#endif /* defined(__WIN32__) || defined(__GDK__) */ - #if defined(__WIN32__) || defined(__WINGDK__) /** diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 651431e6745e3..ea6f8d71f3153 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -286,8 +286,6 @@ SDL3_0.0.0 { SDL_GetRelativeMouseMode; SDL_GetRelativeMouseState; SDL_GetRenderClipRect; - SDL_GetRenderD3D11Device; - SDL_GetRenderD3D9Device; SDL_GetRenderDrawBlendMode; SDL_GetRenderDrawColor; SDL_GetRenderDriver; @@ -522,7 +520,6 @@ SDL3_0.0.0 { SDL_RenderFlush; SDL_RenderGeometry; SDL_RenderGeometryRaw; - SDL_RenderGetD3D12Device; SDL_RenderLine; SDL_RenderLines; SDL_RenderPoint; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 08e9878eea2a0..c158f325e4528 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -310,8 +310,6 @@ #define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_REAL #define SDL_GetRelativeMouseState SDL_GetRelativeMouseState_REAL #define SDL_GetRenderClipRect SDL_GetRenderClipRect_REAL -#define SDL_GetRenderD3D11Device SDL_GetRenderD3D11Device_REAL -#define SDL_GetRenderD3D9Device SDL_GetRenderD3D9Device_REAL #define SDL_GetRenderDrawBlendMode SDL_GetRenderDrawBlendMode_REAL #define SDL_GetRenderDrawColor SDL_GetRenderDrawColor_REAL #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL @@ -546,7 +544,6 @@ #define SDL_RenderFlush SDL_RenderFlush_REAL #define SDL_RenderGeometry SDL_RenderGeometry_REAL #define SDL_RenderGeometryRaw SDL_RenderGeometryRaw_REAL -#define SDL_RenderGetD3D12Device SDL_RenderGetD3D12Device_REAL #define SDL_RenderLine SDL_RenderLine_REAL #define SDL_RenderLines SDL_RenderLines_REAL #define SDL_RenderPoint SDL_RenderPoint_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6943830f1849c..512056b561e75 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -67,14 +67,11 @@ SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, #endif SDL_DYNAPI_PROC(int,SDL_RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(ID3D12Device*,SDL_RenderGetD3D12Device,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(void,SDL_SetWindowsMessageHook,(SDL_WindowsMessageHook a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(SDL_DisplayID a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_Direct3D9GetAdapterIndex,(SDL_DisplayID a),(a),return) -SDL_DYNAPI_PROC(ID3D11Device*,SDL_GetRenderD3D11Device,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(IDirect3DDevice9*,SDL_GetRenderD3D9Device,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GDKGetTaskQueue,(XTaskQueueHandle *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 647cb84ffcf8e..dbed72f0c102f 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -46,13 +46,13 @@ this should probably be removed at some point in the future. --ryan. */ #define SDL_WINDOWRENDERDATA "SDL.internal.window.renderer" #define CHECK_RENDERER_MAGIC(renderer, retval) \ - if (!(renderer) || (renderer)->magic != &renderer_magic) { \ + if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \ SDL_InvalidParamError("renderer"); \ return retval; \ } #define CHECK_TEXTURE_MAGIC(texture, retval) \ - if (!(texture) || (texture)->magic != &texture_magic) { \ + if (!(texture) || (texture)->magic != &SDL_texture_magic) { \ SDL_InvalidParamError("texture"); \ return retval; \ } @@ -122,8 +122,8 @@ static const SDL_RenderDriver *render_drivers[] = { }; #endif /* !SDL_RENDER_DISABLED */ -static char renderer_magic; -static char texture_magic; +char SDL_renderer_magic; +char SDL_texture_magic; static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd) { @@ -896,7 +896,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl } renderer->batching = batching; - renderer->magic = &renderer_magic; + renderer->magic = &SDL_renderer_magic; renderer->window = window; renderer->target_mutex = SDL_CreateMutex(); renderer->main_view.viewport.w = -1; @@ -965,7 +965,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) if (renderer) { VerifyDrawQueueFunctions(renderer); - renderer->magic = &renderer_magic; + renderer->magic = &SDL_renderer_magic; renderer->target_mutex = SDL_CreateMutex(); renderer->main_view.pixel_w = surface->w; renderer->main_view.pixel_h = surface->h; @@ -1150,7 +1150,7 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access SDL_OutOfMemory(); return NULL; } - texture->magic = &texture_magic; + texture->magic = &SDL_texture_magic; texture->format = format; texture->access = access; texture->w = w; diff --git a/src/render/SDL_render_unsupported.c b/src/render/SDL_render_unsupported.c index 4d223895f9413..89742d4b6ab86 100644 --- a/src/render/SDL_render_unsupported.c +++ b/src/render/SDL_render_unsupported.c @@ -20,30 +20,3 @@ */ #include "SDL_internal.h" -#if !(defined(__WIN32__) || defined(__WINGDK__)) - -DECLSPEC void *SDLCALL SDL_GetRenderD3D9Device(SDL_Renderer *renderer); /* returns IDirect3DDevice9 * */ -void *SDL_GetRenderD3D9Device(SDL_Renderer *renderer) -{ - (void)renderer; - SDL_Unsupported(); - return NULL; -} - -DECLSPEC void *SDLCALL SDL_GetRenderD3D11Device(SDL_Renderer *renderer); /* returns ID3D11Device * */ -void *SDL_GetRenderD3D11Device(SDL_Renderer *renderer) -{ - (void)renderer; - SDL_Unsupported(); - return NULL; -} - -DECLSPEC void *SDLCALL SDL_RenderGetD3D12Device(SDL_Renderer *renderer); /* return ID3D12Device * */ -void *SDL_RenderGetD3D12Device(SDL_Renderer *renderer) -{ - (void)renderer; - SDL_Unsupported(); - return NULL; -} - -#endif diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index afa2f652352b4..c2624084c9ebd 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -44,6 +44,8 @@ typedef struct SDL_DRect /* The SDL 2D rendering system */ typedef struct SDL_RenderDriver SDL_RenderDriver; +extern char SDL_renderer_magic; +extern char SDL_texture_magic; /* Rendering view state */ typedef struct SDL_RenderViewState diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 02c8cb3718cdf..cf2046e6cd93a 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1563,6 +1563,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_OutOfMemory(); return NULL; } + renderer->magic = &SDL_renderer_magic; data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data)); if (data == NULL) { @@ -1713,6 +1714,8 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) data->drawstate.cliprect_enabled_dirty = SDL_TRUE; data->drawstate.blend = SDL_BLENDMODE_INVALID; + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d9.device", data->device, NULL, NULL); + return renderer; } @@ -1726,28 +1729,3 @@ SDL_RenderDriver D3D_RenderDriver = { 0 } }; #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */ - -#if defined(__WIN32__) || defined(__WINGDK__) -/* This function needs to always exist on Windows, for the Dynamic API. */ -IDirect3DDevice9 *SDL_GetRenderD3D9Device(SDL_Renderer *renderer) -{ - IDirect3DDevice9 *device = NULL; - -#if defined(SDL_VIDEO_RENDER_D3D) && !defined(SDL_RENDER_DISABLED) - D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; - - /* Make sure that this is a D3D renderer */ - if (renderer->DestroyRenderer != D3D_DestroyRenderer) { - SDL_SetError("Renderer is not a D3D renderer"); - return NULL; - } - - device = data->device; - if (device) { - IDirect3DDevice9_AddRef(device); - } -#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */ - - return device; -} -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 5df9049e065a7..3e9716c2cc1b6 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -668,6 +668,8 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0); ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants); + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", data->d3dDevice, NULL, NULL); + done: SAFE_RELEASE(d3dDevice); SAFE_RELEASE(d3dContext); @@ -2411,6 +2413,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_OutOfMemory(); return NULL; } + renderer->magic = &SDL_renderer_magic; data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data)); if (data == NULL) { @@ -2506,28 +2509,3 @@ SDL_RenderDriver D3D11_RenderDriver = { }; #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */ - -#if defined(__WIN32__) || defined(__WINGDK__) -/* This function needs to always exist on Windows, for the Dynamic API. */ -ID3D11Device *SDL_GetRenderD3D11Device(SDL_Renderer *renderer) -{ - ID3D11Device *device = NULL; - -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) - D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; - - /* Make sure that this is a D3D renderer */ - if (renderer->DestroyRenderer != D3D11_DestroyRenderer) { - SDL_SetError("Renderer is not a D3D11 renderer"); - return NULL; - } - - device = (ID3D11Device *)data->d3dDevice; - if (device) { - ID3D11Device_AddRef(device); - } -#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */ - - return device; -} -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 0a5ddca37770d..ba4e1ebc196c9 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1069,6 +1069,9 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) } } data->srvPoolHead = &data->srvPoolNodes[0]; + + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d12.device", data->d3dDevice, NULL, NULL); + done: SAFE_RELEASE(d3dDevice); return result; @@ -2961,6 +2964,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_OutOfMemory(); return NULL; } + renderer->magic = &SDL_renderer_magic; data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data)); if (data == NULL) { @@ -3046,32 +3050,3 @@ SDL_RenderDriver D3D12_RenderDriver = { #endif #endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED */ - -#if defined(__WIN32__) || defined(__GDK__) -#ifdef __cplusplus -extern "C" -#endif -/* This function needs to always exist on Windows, for the Dynamic API. */ -ID3D12Device * -SDL_RenderGetD3D12Device(SDL_Renderer *renderer) -{ - ID3D12Device *device = NULL; - -#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) - D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata; - - /* Make sure that this is a D3D renderer */ - if (renderer->DestroyRenderer != D3D12_DestroyRenderer) { - SDL_SetError("Renderer is not a D3D12 renderer"); - return NULL; - } - - device = (ID3D12Device *)data->d3dDevice; - if (device) { - D3D_CALL(device, AddRef); - } -#endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED */ - - return device; -} -#endif /* defined(__WIN32__) || defined(__GDK__) */ diff --git a/test/testffmpeg.c b/test/testffmpeg.c index cc75a5fa05efd..ecaad773a7ad0 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -145,8 +145,9 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) #endif #ifdef __WIN32__ - d3d11_device = SDL_GetRenderD3D11Device(renderer); + d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device"); if (d3d11_device) { + ID3D11Device_AddRef(d3d11_device); ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context); } #endif From aea6e6de6f205bdcbb003d6de4030be72a8e5a6c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 12:33:43 -0800 Subject: [PATCH 289/725] Simplified SDL_SetProperty() and added SDL_SetPropertyWithCleanup() Most of the time people won't need to set a cleanup callback, so we can simplify the more commonly used API. --- include/SDL3/SDL_properties.h | 23 +++++++++++++++++-- src/SDL_properties.c | 9 ++++++-- src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 3 ++- src/render/SDL_render.c | 2 +- src/render/direct3d/SDL_render_d3d.c | 2 +- src/render/direct3d11/SDL_render_d3d11.c | 2 +- src/render/direct3d12/SDL_render_d3d12.c | 2 +- src/video/SDL_video.c | 2 +- src/video/dummy/SDL_nullframebuffer.c | 2 +- src/video/n3ds/SDL_n3dsframebuffer.c | 2 +- .../offscreen/SDL_offscreenframebuffer.c | 2 +- test/testautomation_properties.c | 18 +++++++-------- test/testautomation_video.c | 22 +++++++++--------- test/testffmpeg.c | 2 +- 16 files changed, 61 insertions(+), 34 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 66d12f6140ce0..9a6ebf3152c15 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -95,7 +95,23 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); /** * Set a property on a set of properties * - * By convention, the names of properties that SDL exposes on objects will start with "SDL.", and properties that SDL uses internally will start with "SDL.internal.". These should be considered read-only and should not be modified by applications. + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property, or NULL to delete the property + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetPropertyWithCleanup + */ +extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value); + +/** + * Set a property on a set of properties with a cleanup function that is called when the property is deleted * * \param props the properties to modify * \param name the name of the property to modify @@ -111,12 +127,15 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetProperty + * \sa SDL_SetProperty */ -extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); +extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); /** * Get a property on a set of properties * + * By convention, the names of properties that SDL exposes on objects will start with "SDL.", and properties that SDL uses internally will start with "SDL.internal.". These should be considered read-only and should not be modified by applications. + * * \param props the properties to query * \param name the name of the property to query * \returns the value of the property, or NULL if it is not set. diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 0b8d795347811..d0b9c60f17d7e 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -183,7 +183,12 @@ void SDL_UnlockProperties(SDL_PropertiesID props) SDL_UnlockMutex(properties->lock); } -int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) +int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) +{ + return SDL_SetPropertyWithCleanup(props, name, value, NULL, NULL); +} + +int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) { SDL_Properties *properties = NULL; SDL_Property *property = NULL; @@ -274,7 +279,7 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) int SDL_ClearProperty(SDL_PropertiesID props, const char *name) { - return SDL_SetProperty(props, name, NULL, NULL, NULL); + return SDL_SetProperty(props, name, NULL); } void SDL_DestroyProperties(SDL_PropertiesID props) diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index ea6f8d71f3153..dc1899f9bea3d 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -921,6 +921,7 @@ SDL3_0.0.0 { SDL_RWvprintf; SDL_AllocateEventMemory; SDL_GetDisplayProperties; + SDL_SetPropertyWithCleanup; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c158f325e4528..35fff15baf806 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -946,3 +946,4 @@ #define SDL_RWvprintf SDL_RWvprintf_REAL #define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL +#define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 512056b561e75..9f28f67448287 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -962,7 +962,7 @@ SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),r SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) -SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return) @@ -979,3 +979,4 @@ SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_fun SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return) SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) +SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index dbed72f0c102f..1d55c87b72b31 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -929,7 +929,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl renderer->hidden = SDL_FALSE; } - SDL_SetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, renderer, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, renderer); SDL_SetRenderViewport(renderer, NULL); diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index cf2046e6cd93a..abfe5d5e06d41 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1714,7 +1714,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) data->drawstate.cliprect_enabled_dirty = SDL_TRUE; data->drawstate.blend = SDL_BLENDMODE_INVALID; - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d9.device", data->device, NULL, NULL); + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d9.device", data->device); return renderer; } diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 3e9716c2cc1b6..f15344ad204fa 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -668,7 +668,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0); ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants); - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", data->d3dDevice, NULL, NULL); + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", data->d3dDevice); done: SAFE_RELEASE(d3dDevice); diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index ba4e1ebc196c9..7c0fa525aa021 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1070,7 +1070,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) } data->srvPoolHead = &data->srvPoolNodes[0]; - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d12.device", data->d3dDevice, NULL, NULL); + SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d12.device", data->d3dDevice); done: SAFE_RELEASE(d3dDevice); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 280260785ab62..a4f771b74c314 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -280,7 +280,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_DestroyRenderer(renderer); return SDL_OutOfMemory(); } - SDL_SetProperty(props, SDL_WINDOWTEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); + SDL_SetPropertyWithCleanup(props, SDL_WINDOWTEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); data->renderer = renderer; } else { diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index b2ef604458f07..5978d3b0a0c1e 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -48,7 +48,7 @@ int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window } /* Save the info and return! */ - SDL_SetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE, surface, CleanupSurface, NULL); + SDL_SetPropertyWithCleanup(SDL_GetWindowProperties(window), DUMMY_SURFACE, surface, CleanupSurface, NULL); *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index b2e0d93fe2c17..46fe98ea073a0 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -57,7 +57,7 @@ int SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, return SDL_OutOfMemory(); } - SDL_SetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, framebuffer, CleanupSurface, NULL); + SDL_SetPropertyWithCleanup(SDL_GetWindowProperties(window), N3DS_SURFACE, framebuffer, CleanupSurface, NULL); *format = FRAMEBUFFER_FORMAT; *pixels = framebuffer->pixels; *pitch = framebuffer->pitch; diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index cd5feba647121..7dea25a905dcd 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -48,7 +48,7 @@ int SDL_OFFSCREEN_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi } /* Save the info and return! */ - SDL_SetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE, surface, CleanupSurface, NULL); + SDL_SetPropertyWithCleanup(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE, surface, CleanupSurface, NULL); *format = surface_format; *pixels = surface->pixels; *pitch = surface->pitch; diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index ff49e80247a62..75ddc35b99a60 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -26,7 +26,7 @@ static int properties_testBasic(void *arg) for (i = 0; i < 10; ++i) { SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); - result = SDL_SetProperty(props, key, expected_value, NULL, NULL); + result = SDL_SetProperty(props, key, expected_value); SDLTest_AssertPass("Call to SDL_SetProperty()"); SDLTest_AssertCheck(result == 0, "Verify property value was set, got: %d", result); @@ -38,7 +38,7 @@ static int properties_testBasic(void *arg) for (i = 0; i < 10; ++i) { SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); - result = SDL_SetProperty(props, key, NULL, NULL, NULL); + result = SDL_SetProperty(props, key, NULL); SDLTest_AssertPass("Call to SDL_SetProperty(NULL)"); SDLTest_AssertCheck(result == 0, "Verify property value was set, got: %d", result); @@ -71,8 +71,8 @@ static int properties_testCleanup(void *arg) SDLTest_AssertPass("Call to SDL_SetProperty(cleanup)"); count = 0; - SDL_SetProperty(props, "a", "0", cleanup, &count); - SDL_SetProperty(props, "a", NULL, cleanup, &count); + SDL_SetPropertyWithCleanup(props, "a", "0", cleanup, &count); + SDL_SetPropertyWithCleanup(props, "a", NULL, cleanup, &count); SDLTest_AssertCheck(count == 1, "Verify cleanup for deleting property, got %d, expected 1", count); @@ -81,7 +81,7 @@ static int properties_testCleanup(void *arg) for (i = 0; i < 10; ++i) { SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); SDL_snprintf(expected_value, SDL_arraysize(expected_value), "%c", 'a' + i); - SDL_SetProperty(props, key, expected_value, cleanup, &count); + SDL_SetPropertyWithCleanup(props, key, expected_value, cleanup, &count); } SDL_DestroyProperties(props); SDLTest_AssertCheck(count == 10, @@ -104,11 +104,11 @@ static int properties_thread(void *arg) while (!data->done) { SDL_LockProperties(data->props); - SDL_SetProperty(data->props, "a", "thread_loop", NULL, NULL); + SDL_SetProperty(data->props, "a", "thread_loop"); SDL_UnlockProperties(data->props); } SDL_LockProperties(data->props); - SDL_SetProperty(data->props, "a", "thread_done", NULL, NULL); + SDL_SetProperty(data->props, "a", "thread_done"); SDL_UnlockProperties(data->props); return 0; } @@ -122,7 +122,7 @@ static int properties_testLocking(void *arg) data.done = SDL_FALSE; data.props = SDL_CreateProperties(); SDLTest_AssertPass("Setting property to 'init'"); - SDL_SetProperty(data.props, "a", "init", NULL, NULL); + SDL_SetProperty(data.props, "a", "init"); thread = SDL_CreateThread(properties_thread, "properties_thread", &data); if (thread) { SDLTest_AssertPass("Waiting for property to change to 'thread_loop'"); @@ -142,7 +142,7 @@ static int properties_testLocking(void *arg) SDLTest_AssertPass("Setting property to 'main'"); SDL_LockProperties(data.props); - SDL_SetProperty(data.props, "a", "main", NULL, NULL); + SDL_SetProperty(data.props, "a", "main"); SDL_Delay(100); value = SDL_GetProperty(data.props, "a"); SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "main") == 0, diff --git a/test/testautomation_video.c b/test/testautomation_video.c index d45a9a40f0eb0..a05d90267b035 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1498,7 +1498,7 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s)", name, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); @@ -1514,7 +1514,7 @@ static int video_getSetWindowData(void *arg) /* Set data again twice */ for (iteration = 1; iteration <= 2; iteration++) { - SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [iteration %d]", name, userdata, iteration); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); @@ -1527,14 +1527,14 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data with new data */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [new userdata]", name, userdata2); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Set data with new data again */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata2); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [new userdata again]", name, userdata2); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); @@ -1547,14 +1547,14 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data with NULL to clear */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,NULL)", name); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Set data with NULL to clear again */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,NULL) [again]", name); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); @@ -1573,7 +1573,7 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceName2, name2) == 0, "Validate that name2 was not changed, expected: %s, got: %s", referenceName2, name2); /* Set data (again) */ - SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), name, userdata); SDLTest_AssertPass("Call to SDL_SetWindowData(...%s,%s) [again, after clear]", name, userdata); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); @@ -1585,22 +1585,22 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Set data with NULL name, valid userdata */ - SDL_SetProperty(SDL_GetWindowProperties(window), NULL, userdata, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), NULL, userdata); SDLTest_AssertPass("Call to SDL_SetWindowData(name=NULL)"); checkInvalidParameterError(); /* Set data with empty name, valid userdata */ - SDL_SetProperty(SDL_GetWindowProperties(window), "", userdata, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), "", userdata); SDLTest_AssertPass("Call to SDL_SetWindowData(name='')"); checkInvalidParameterError(); /* Set data with NULL name, NULL userdata */ - SDL_SetProperty(SDL_GetWindowProperties(window), NULL, NULL, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), NULL, NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name=NULL,userdata=NULL)"); checkInvalidParameterError(); /* Set data with empty name, NULL userdata */ - SDL_SetProperty(SDL_GetWindowProperties(window), "", NULL, NULL, NULL); + SDL_SetProperty(SDL_GetWindowProperties(window), "", NULL); SDLTest_AssertPass("Call to SDL_SetWindowData(name='',userdata=NULL)"); checkInvalidParameterError(); diff --git a/test/testffmpeg.c b/test/testffmpeg.c index ecaad773a7ad0..519ae466f16c1 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -464,7 +464,7 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) SDL_OutOfMemory(); return SDL_FALSE; } - SDL_SetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL); + SDL_SetPropertyWithCleanup(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL); } sws_container->context = sws_getCachedContext(sws_container->context, frame->width, frame->height, frame->format, frame->width, frame->height, AV_PIX_FMT_BGRA, SWS_POINT, NULL, NULL, NULL); if (sws_container->context) { From fd4a2cce9effc2cc5a69c4bd6fdc4622794ebf23 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 14:38:19 -0800 Subject: [PATCH 290/725] SDL_syswm.h has been removed and replaced with window properties --- VisualC-GDK/SDL/SDL.vcxproj | 1 - VisualC-GDK/SDL/SDL.vcxproj.filters | 3 - VisualC-WinRT/SDL-UWP.vcxproj | 1 - VisualC-WinRT/SDL-UWP.vcxproj.filters | 3 - VisualC/SDL/SDL.vcxproj | 1 - VisualC/SDL/SDL.vcxproj.filters | 3 - .../testautomation/testautomation.vcxproj | 3 +- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 4 - docs/README-ios.md | 20 - docs/README-migration.md | 26 +- docs/README-winrt.md | 2 +- include/SDL3/SDL_events.h | 28 +- include/SDL3/SDL_hints.h | 1 - include/SDL3/SDL_oldnames.h | 2 - include/SDL3/SDL_system.h | 48 ++- include/SDL3/SDL_syswm.h | 387 ------------------ include/SDL3/SDL_video.h | 49 +++ include/build_config/SDL_build_config.h.cmake | 56 --- src/core/SDL_core_unsupported.c | 8 + src/core/linux/SDL_fcitx.c | 19 +- src/core/linux/SDL_ibus.c | 21 +- src/dynapi/SDL_dynapi.c | 1 - src/dynapi/SDL_dynapi.sym | 2 +- src/dynapi/SDL_dynapi_overrides.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 2 +- src/events/SDL_events.c | 34 -- src/events/SDL_events_c.h | 1 - src/render/direct3d/SDL_render_d3d.c | 11 +- src/render/direct3d11/SDL_render_d3d11.c | 15 +- src/render/direct3d11/SDL_render_winrt.cpp | 25 +- src/render/direct3d12/SDL_render_d3d12.c | 14 +- src/render/metal/SDL_render_metal.m | 60 ++- src/video/SDL_sysvideo.h | 6 - src/video/SDL_video.c | 51 --- src/video/android/SDL_androidvideo.c | 1 - src/video/android/SDL_androidvulkan.c | 1 - src/video/android/SDL_androidwindow.c | 18 +- src/video/android/SDL_androidwindow.h | 1 - src/video/cocoa/SDL_cocoametalview.m | 2 - src/video/cocoa/SDL_cocoavideo.m | 1 - src/video/cocoa/SDL_cocoavulkan.m | 2 - src/video/cocoa/SDL_cocoawindow.h | 3 +- src/video/cocoa/SDL_cocoawindow.m | 16 +- src/video/haiku/SDL_BWin.h | 2 - src/video/haiku/SDL_bvideo.cc | 1 - src/video/haiku/SDL_bwindow.cc | 9 - src/video/haiku/SDL_bwindow.h | 1 - src/video/kmsdrm/SDL_kmsdrmvideo.c | 23 +- src/video/kmsdrm/SDL_kmsdrmvideo.h | 3 - src/video/kmsdrm/SDL_kmsdrmvulkan.c | 2 - src/video/ngage/SDL_ngagewindow.h | 9 +- src/video/psp/SDL_pspvideo.c | 2 - src/video/raspberry/SDL_rpivideo.c | 2 - src/video/riscos/SDL_riscosvideo.c | 1 - src/video/riscos/SDL_riscoswindow.c | 8 - src/video/riscos/SDL_riscoswindow.h | 1 - src/video/uikit/SDL_uikitmetalview.m | 2 - src/video/uikit/SDL_uikitvideo.m | 1 - src/video/uikit/SDL_uikitvulkan.m | 2 - src/video/uikit/SDL_uikitwindow.h | 3 +- src/video/uikit/SDL_uikitwindow.m | 30 +- src/video/vita/SDL_vitavideo.c | 2 - src/video/vivante/SDL_vivantevideo.c | 22 +- src/video/vivante/SDL_vivantevideo.h | 3 - src/video/vivante/SDL_vivantevulkan.c | 1 - src/video/wayland/SDL_waylandvideo.c | 1 - src/video/wayland/SDL_waylandvulkan.c | 2 - src/video/wayland/SDL_waylandwindow.c | 59 ++- src/video/wayland/SDL_waylandwindow.h | 3 - src/video/windows/SDL_windowsevents.c | 23 +- src/video/windows/SDL_windowsvideo.c | 1 - src/video/windows/SDL_windowsvulkan.c | 2 - src/video/windows/SDL_windowswindow.c | 19 +- src/video/windows/SDL_windowswindow.h | 1 - src/video/winrt/SDL_winrtvideo.cpp | 14 +- src/video/x11/SDL_x11events.c | 45 +- src/video/x11/SDL_x11video.c | 1 - src/video/x11/SDL_x11window.c | 27 +- src/video/x11/SDL_x11window.h | 1 - test/testautomation.c | 1 - test/testautomation_suites.h | 1 - test/testautomation_syswm.c | 60 --- 82 files changed, 277 insertions(+), 1069 deletions(-) delete mode 100644 include/SDL3/SDL_syswm.h delete mode 100644 test/testautomation_syswm.c diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index b19bb5fba48ee..a2c5aa6db2803 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -345,7 +345,6 @@ - diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index ba454f428fe1e..a5772a7453409 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -348,9 +348,6 @@ API Headers - - API Headers - API Headers diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 0dee306b691fd..1085c0f452007 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -83,7 +83,6 @@ - diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 7d765c13c113a..ab0ca0cfb7ab8 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -147,9 +147,6 @@ Header Files - - Header Files - Header Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 57eb07e85ca1c..35edb9b8a6a44 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -296,7 +296,6 @@ - diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index cd7b2b2e3e176..b367e7695fe64 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -342,9 +342,6 @@ API Headers - - API Headers - API Headers diff --git a/VisualC/tests/testautomation/testautomation.vcxproj b/VisualC/tests/testautomation/testautomation.vcxproj index f64b89be8db2d..260617b4a8723 100644 --- a/VisualC/tests/testautomation/testautomation.vcxproj +++ b/VisualC/tests/testautomation/testautomation.vcxproj @@ -218,7 +218,6 @@ - @@ -229,4 +228,4 @@ - \ No newline at end of file + diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index be5ba5ac43c4f..657b54b2b1c0b 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -437,7 +437,6 @@ F3F7D9352933074E00816151 /* SDL_error.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BC2933074A00816151 /* SDL_error.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9392933074E00816151 /* SDL_opengles2_gl2ext.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BD2933074A00816151 /* SDL_opengles2_gl2ext.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D93D2933074E00816151 /* SDL_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BE2933074A00816151 /* SDL_endian.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3F7D9412933074E00816151 /* SDL_syswm.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BF2933074A00816151 /* SDL_syswm.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9452933074E00816151 /* SDL_opengl_glext.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C02933074A00816151 /* SDL_opengl_glext.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9492933074E00816151 /* SDL_scancode.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C12933074B00816151 /* SDL_scancode.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D94D2933074E00816151 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C22933074B00816151 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -939,7 +938,6 @@ F3F7D8BC2933074A00816151 /* SDL_error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_error.h; path = SDL3/SDL_error.h; sourceTree = ""; }; F3F7D8BD2933074A00816151 /* SDL_opengles2_gl2ext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2_gl2ext.h; path = SDL3/SDL_opengles2_gl2ext.h; sourceTree = ""; }; F3F7D8BE2933074A00816151 /* SDL_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_endian.h; path = SDL3/SDL_endian.h; sourceTree = ""; }; - F3F7D8BF2933074A00816151 /* SDL_syswm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syswm.h; path = SDL3/SDL_syswm.h; sourceTree = ""; }; F3F7D8C02933074A00816151 /* SDL_opengl_glext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengl_glext.h; path = SDL3/SDL_opengl_glext.h; sourceTree = ""; }; F3F7D8C12933074B00816151 /* SDL_scancode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_scancode.h; path = SDL3/SDL_scancode.h; sourceTree = ""; }; F3F7D8C22933074B00816151 /* SDL_sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_sensor.h; path = SDL3/SDL_sensor.h; sourceTree = ""; }; @@ -1091,7 +1089,6 @@ F3F7D8AC2933074900816151 /* SDL_stdinc.h */, F3F7D8BB2933074A00816151 /* SDL_surface.h */, F3F7D8E82933074E00816151 /* SDL_system.h */, - F3F7D8BF2933074A00816151 /* SDL_syswm.h */, F3F7D8CD2933074C00816151 /* SDL_thread.h */, F3F7D8B22933074900816151 /* SDL_timer.h */, F3F7D8AF2933074900816151 /* SDL_touch.h */, @@ -2259,7 +2256,6 @@ A7D8B42823E2514300DCD162 /* SDL_systhread_c.h in Headers */, 5616CA4D252BB2A6005D5928 /* SDL_sysurl.h in Headers */, A7D8AC3F23E2514100DCD162 /* SDL_sysvideo.h in Headers */, - F3F7D9412933074E00816151 /* SDL_syswm.h in Headers */, F3F7D9792933074E00816151 /* SDL_thread.h in Headers */, A7D8B3EC23E2514300DCD162 /* SDL_thread_c.h in Headers */, F3F7D90D2933074E00816151 /* SDL_timer.h in Headers */, diff --git a/docs/README-ios.md b/docs/README-ios.md index 643b342ea6729..6e48af9434713 100644 --- a/docs/README-ios.md +++ b/docs/README-ios.md @@ -125,26 +125,6 @@ SDL for iPhone supports polling the built in accelerometer as a joystick device. The main thing to note when using the accelerometer with SDL is that while the iPhone natively reports accelerometer as floating point values in units of g-force, SDL_GetJoystickAxis() reports joystick values as signed integers. Hence, in order to convert between the two, some clamping and scaling is necessary on the part of the iPhone SDL joystick driver. To convert SDL_GetJoystickAxis() reported values BACK to units of g-force, simply multiply the values by SDL_IPHONE_MAX_GFORCE / 0x7FFF. -Notes -- OpenGL ES -============================================================================== - -Your SDL application for iOS uses OpenGL ES for video by default. - -OpenGL ES for iOS supports several display pixel formats, such as RGBA8 and RGB565, which provide a 32 bit and 16 bit color buffer respectively. By default, the implementation uses RGB565, but you may use RGBA8 by setting each color component to 8 bits in SDL_GL_SetAttribute(). - -If your application doesn't use OpenGL's depth buffer, you may find significant performance improvement by setting SDL_GL_DEPTH_SIZE to 0. - -Finally, if your application completely redraws the screen each frame, you may find significant performance improvement by setting the attribute SDL_GL_RETAINED_BACKING to 0. - -OpenGL ES on iOS doesn't use the traditional system-framebuffer setup provided in other operating systems. Special care must be taken because of this: - -- The drawable Renderbuffer must be bound to the GL_RENDERBUFFER binding point when SDL_GL_SwapWindow() is called. -- The drawable Framebuffer Object must be bound while rendering to the screen and when SDL_GL_SwapWindow() is called. -- If multisample antialiasing (MSAA) is used and glReadPixels is used on the screen, the drawable framebuffer must be resolved to the MSAA resolve framebuffer (via glBlitFramebuffer or glResolveMultisampleFramebufferAPPLE), and the MSAA resolve framebuffer must be bound to the GL_READ_FRAMEBUFFER binding point, before glReadPixels is called. - -The above objects can be obtained via SDL_GetWindowWMInfo() (in SDL_syswm.h). - - Notes -- Keyboard ============================================================================== diff --git a/docs/README-migration.md b/docs/README-migration.md index 60b9209c7baff..3bd20f135b1f8 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1150,6 +1150,8 @@ The following functions have been renamed: ## SDL_system.h +SDL_WindowsMessageHook has changed signatures so the message may be modified and it can block further message processing. + SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. The following functions have been removed: @@ -1159,7 +1161,29 @@ The following functions have been removed: ## SDL_syswm.h -The structures in this file are versioned separately from the rest of SDL, allowing better backwards compatibility and limited forwards compatibility with your application. Instead of calling `SDL_VERSION(&info.version)` before calling SDL_GetWindowWMInfo(), you pass the version in explicitly as SDL_SYSWM_CURRENT_VERSION so SDL knows what fields you expect to be filled out. +This header has been removed. + +The Windows and X11 events are now available via callbacks which you can set with SDL_SetWindowsMessageHook() and SDL_SetX11EventHook(). + +The information previously available in SDL_GetWindowWMInfo() is now available as window properties, e.g. +```c + HWND hwnd = NULL; + SDL_SysWMinfo info; + SDL_VERSION(&info); + if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { + hwnd = info.info.win.window; + } + if (hwnd) { + ... + } +``` +becomes: +```c + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); + if (hwnd) { + ... + } +``` ### SDL_GetWindowWMInfo diff --git a/docs/README-winrt.md b/docs/README-winrt.md index 3530f673e04e2..61922640981a2 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -63,7 +63,7 @@ Here is a rough list of what works, and what doesn't: * using Direct3D 11.x APIs outside of SDL. Non-XAML / Direct3D-only apps can choose to render content directly via Direct3D, using SDL to manage the internal WinRT window, as well as input and audio. (Use - SDL_GetWindowWMInfo() to get the WinRT 'CoreWindow', and pass it into + the window properties to get the WinRT 'CoreWindow', and pass it into IDXGIFactory2::CreateSwapChainForCoreWindow() as appropriate.) * What partially works: diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 427e9416b7a49..dcc9ece04a722 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -101,8 +101,8 @@ typedef enum /* Window events */ /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */ - SDL_EVENT_SYSWM = 0x201, /**< System specific event */ - SDL_EVENT_WINDOW_SHOWN, /**< Window has been shown */ + /* 0x201 was SDL_EVENT_SYSWM, reserve the number for sdl2-compat */ + SDL_EVENT_WINDOW_SHOWN = 0x202, /**< Window has been shown */ SDL_EVENT_WINDOW_HIDDEN, /**< Window has been hidden */ SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn */ SDL_EVENT_WINDOW_MOVED, /**< Window has been moved to data1, data2 */ @@ -573,27 +573,6 @@ typedef struct SDL_UserEvent } SDL_UserEvent; -struct SDL_SysWMmsg; -typedef struct SDL_SysWMmsg SDL_SysWMmsg; - -/** - * A video driver dependent system event (event.syswm.*) - * - * This event is disabled by default, you can enable it with - * SDL_SetEventEnabled() - * - * The `msg` is owned by SDL and should be copied if the application - * wants to hold onto it beyond the scope of handling this event. - * - * \note If you want to use this event, you should include SDL_syswm.h. - */ -typedef struct SDL_SysWMEvent -{ - Uint32 type; /**< ::SDL_EVENT_SYSWM */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */ -} SDL_SysWMEvent; - /** * General event structure */ @@ -623,10 +602,9 @@ typedef union SDL_Event SDL_SensorEvent sensor; /**< Sensor event data */ SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ - SDL_SysWMEvent syswm; /**< System dependent window event data */ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ SDL_DropEvent drop; /**< Drag and drop event data */ - SDL_ClipboardEvent clipboard; /**< Clipboard cancelled event data */ + SDL_ClipboardEvent clipboard; /**< Clipboard event data */ /* This is necessary for ABI compatibility between Visual C++ and GCC. Visual C++ will respect the push pack pragma and use 52 bytes (size of diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index a4933ac77bba0..a2d06b2b18fb0 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -417,7 +417,6 @@ extern "C" { * "0" - Don't log any events (default) * "1" - Log most events (other than the really spammy ones). * "2" - Include mouse and finger motion events. - * "3" - Include SDL_SysWMEvent events. * * This is generally meant to be used to debug SDL itself, but can be useful * for application developers that need better visibility into what is going diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 5e266c1155954..805921292bbba 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -124,7 +124,6 @@ #define SDL_RENDER_DEVICE_RESET SDL_EVENT_RENDER_DEVICE_RESET #define SDL_RENDER_TARGETS_RESET SDL_EVENT_RENDER_TARGETS_RESET #define SDL_SENSORUPDATE SDL_EVENT_SENSOR_UPDATE -#define SDL_SYSWMEVENT SDL_EVENT_SYSWM #define SDL_TEXTEDITING SDL_EVENT_TEXT_EDITING #define SDL_TEXTEDITING_EXT SDL_EVENT_TEXT_EDITING_EXT #define SDL_TEXTINPUT SDL_EVENT_TEXT_INPUT @@ -568,7 +567,6 @@ #define SDL_RENDER_DEVICE_RESET SDL_RENDER_DEVICE_RESET_renamed_SDL_EVENT_RENDER_DEVICE_RESET #define SDL_RENDER_TARGETS_RESET SDL_RENDER_TARGETS_RESET_renamed_SDL_EVENT_RENDER_TARGETS_RESET #define SDL_SENSORUPDATE SDL_SENSORUPDATE_renamed_SDL_EVENT_SENSOR_UPDATE -#define SDL_SYSWMEVENT SDL_SYSWMEVENT_renamed_SDL_EVENT_SYSWM #define SDL_TEXTEDITING SDL_TEXTEDITING_renamed_SDL_EVENT_TEXT_EDITING #define SDL_TEXTEDITING_EXT SDL_TEXTEDITING_EXT_renamed_SDL_EVENT_TEXT_EDITING_EXT #define SDL_TEXTINPUT SDL_TEXTINPUT_renamed_SDL_EVENT_TEXT_INPUT diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index 14a25e00a13f1..a2cd27d8704cd 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -40,14 +40,18 @@ extern "C" { #endif -/* Platform specific functions for Windows */ +/* + * Platform specific functions for Windows + */ #if defined(__WIN32__) || defined(__GDK__) -typedef void (SDLCALL * SDL_WindowsMessageHook)(void *userdata, void *hWnd, unsigned int message, Uint64 wParam, Sint64 lParam); - +typedef struct tagMSG MSG; +typedef SDL_bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); /** * Set a callback for every Windows message, run before TranslateMessage(). * + * The callback may modify the message, and should return SDL_TRUE if the message should continue to be processed, or SDL_FALSE to prevent further processing. + * * \param callback The SDL_WindowsMessageHook function to call. * \param userdata a pointer to pass to every iteration of `callback` * @@ -96,7 +100,27 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, #endif /* defined(__WIN32__) || defined(__WINGDK__) */ -/* Platform specific functions for Linux */ +/* + * Platform specific functions for UNIX + */ + +typedef union _XEvent XEvent; +typedef SDL_bool (SDLCALL *SDL_X11EventHook)(void *userdata, XEvent *xevent); +/** + * Set a callback for every X11 event + * + * The callback may modify the event, and should return SDL_TRUE if the event should continue to be processed, or SDL_FALSE to prevent further processing. + * + * \param callback The SDL_X11EventHook function to call. + * \param userdata a pointer to pass to every iteration of `callback` + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata); + +/* + * Platform specific functions for Linux + */ #ifdef __LINUX__ /** @@ -130,7 +154,9 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, #endif /* __LINUX__ */ -/* Platform specific functions for iOS */ +/* + * Platform specific functions for iOS + */ #ifdef __IOS__ #define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam) @@ -190,7 +216,9 @@ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); #endif /* __IOS__ */ -/* Platform specific functions for Android */ +/* + * Platform specific functions for Android + */ #ifdef __ANDROID__ /** @@ -419,7 +447,9 @@ extern DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); #endif /* __ANDROID__ */ -/* Platform specific functions for WinRT */ +/* + * Platform specific functions for WinRT + */ #ifdef __WINRT__ /** @@ -581,7 +611,9 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void); extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void); #endif -/* Functions used only by GDK */ +/* + * Functions used only by GDK + */ #ifdef __GDK__ typedef struct XTaskQueueObject *XTaskQueueHandle; typedef struct XUser *XUserHandle; diff --git a/include/SDL3/SDL_syswm.h b/include/SDL3/SDL_syswm.h deleted file mode 100644 index cefe98077c9a8..0000000000000 --- a/include/SDL3/SDL_syswm.h +++ /dev/null @@ -1,387 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/** - * \file SDL_syswm.h - * - * Include file for SDL custom system window manager hooks. - */ - -#ifndef SDL_syswm_h_ -#define SDL_syswm_h_ - -#include -#include -#include -#include - -/** - * SDL_syswm.h - * - * Your application has access to a special type of event ::SDL_EVENT_SYSWM, - * which contains window-manager specific information and arrives whenever - * an unhandled window event occurs. This event is ignored by default, but - * you can enable it with SDL_SetEventEnabled(). - */ - -/** - * The available subsystems based on platform - */ -#ifndef SDL_DISABLE_SYSWM_PLATFORMS - -#ifndef SDL_DISABLE_SYSWM_ANDROID -#ifdef __ANDROID__ -#define SDL_ENABLE_SYSWM_ANDROID -#endif -#endif /* !SDL_DISABLE_SYSWM_ANDROID */ - -#ifndef SDL_DISABLE_SYSWM_COCOA -#ifdef __MACOS__ -#define SDL_ENABLE_SYSWM_COCOA -#endif -#endif /* !SDL_DISABLE_SYSWM_COCOA */ - -#ifndef SDL_DISABLE_SYSWM_HAIKU -#ifdef __HAIKU__ -#define SDL_ENABLE_SYSWM_HAIKU -#endif -#endif /* !SDL_DISABLE_SYSWM_HAIKU */ - -#ifndef SDL_DISABLE_SYSWM_KMSDRM -#if defined(__LINUX__) || defined(__FREEBSD__) || defined(__OPENBSD__) -#define SDL_ENABLE_SYSWM_KMSDRM -#endif -#endif /* !SDL_DISABLE_SYSWM_KMSDRM */ - -#ifndef SDL_DISABLE_SYSWM_RISCOS -#ifdef __RISCOS__ -#define SDL_ENABLE_SYSWM_RISCOS -#endif -#endif /* !SDL_DISABLE_SYSWM_RISCOS */ - -#ifndef SDL_DISABLE_SYSWM_UIKIT -#if defined(__IOS__) || defined(__TVOS__) -#define SDL_ENABLE_SYSWM_UIKIT -#endif -#endif /* !SDL_DISABLE_SYSWM_UIKIT */ - -#ifndef SDL_DISABLE_SYSWM_VIVANTE -/* Not enabled by default */ -#endif /* !SDL_DISABLE_SYSWM_VIVANTE */ - -#ifndef SDL_DISABLE_SYSWM_WAYLAND -#if defined(__LINUX__) || defined(__FREEBSD__) -#define SDL_ENABLE_SYSWM_WAYLAND -#endif -#endif /* !SDL_DISABLE_SYSWM_WAYLAND */ - -#ifndef SDL_DISABLE_SYSWM_WINDOWS -#if defined(__WIN32__) || defined(__GDK__) -#define SDL_ENABLE_SYSWM_WINDOWS -#endif -#endif /* !SDL_DISABLE_SYSWM_WINDOWS */ - -#ifndef SDL_DISABLE_SYSWM_WINRT -#ifdef __WINRT__ -#define SDL_ENABLE_SYSWM_WINRT -#endif -#endif /* !SDL_DISABLE_SYSWM_WINRT */ - -#ifndef SDL_DISABLE_SYSWM_X11 -#if defined(__unix__) && !defined(__WIN32__) && !defined(__ANDROID__) && !defined(__QNX__) -#define SDL_ENABLE_SYSWM_X11 -#endif -#endif /* !SDL_DISABLE_SYSWM_X11 */ - -#endif /* !SDL_DISABLE_SYSWM_PLATFORMS */ - -/** - * Forward declaration of types used by subsystems - */ -#ifndef SDL_DISABLE_SYSWM_TYPES - -#if defined(SDL_ENABLE_SYSWM_ANDROID) && !defined(SDL_DISABLE_SYSWM_ANDROID_TYPES) -typedef struct ANativeWindow ANativeWindow; -typedef void *EGLSurface; -#endif /* SDL_ENABLE_SYSWM_ANDROID */ - -#if defined(SDL_ENABLE_SYSWM_COCOA) && !defined(SDL_DISABLE_SYSWM_COCOA_TYPES) -#ifdef __OBJC__ -@class NSWindow; -#else -typedef struct _NSWindow NSWindow; -#endif -#endif /* SDL_ENABLE_SYSWM_COCOA */ - -#if defined(SDL_ENABLE_SYSWM_KMSDRM) && !defined(SDL_DISABLE_SYSWM_KMSDRM_TYPES) -struct gbm_device; -#endif /* SDL_ENABLE_SYSWM_KMSDRM */ - -#if defined(SDL_ENABLE_SYSWM_UIKIT) && !defined(SDL_DISABLE_SYSWM_UIKIT_TYPES) -#ifdef __OBJC__ -#include -#else -typedef struct _UIWindow UIWindow; -typedef struct _UIViewController UIViewController; -#endif -typedef Uint32 GLuint; -#endif /* SDL_ENABLE_SYSWM_UIKIT */ - -#if defined(SDL_ENABLE_SYSWM_VIVANTE) && !defined(SDL_DISABLE_SYSWM_VIVANTE_TYPES) -#include -#endif /* SDL_ENABLE_SYSWM_VIVANTE */ - -#if defined(SDL_ENABLE_SYSWM_WAYLAND) && !defined(SDL_DISABLE_SYSWM_WAYLAND_TYPES) -struct wl_display; -struct wl_egl_window; -struct wl_surface; -struct xdg_popup; -struct xdg_positioner; -struct xdg_surface; -struct xdg_toplevel; -#endif /* SDL_ENABLE_SYSWM_WAYLAND */ - -#if defined(SDL_ENABLE_SYSWM_WINDOWS) && !defined(SDL_DISABLE_SYSWM_WINDOWS_TYPES) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX /* don't define min() and max(). */ -#define NOMINMAX -#endif -#include -#endif /* SDL_ENABLE_SYSWM_WINDOWS */ - -#if defined(SDL_ENABLE_SYSWM_WINRT) && !defined(SDL_DISABLE_SYSWM_WINRT_TYPES) -#include -#endif /* SDL_ENABLE_SYSWM_WINRT */ - -#if defined(SDL_ENABLE_SYSWM_X11) && !defined(SDL_DISABLE_SYSWM_X11_TYPES) -#include -#include -#endif /* SDL_ENABLE_SYSWM_X11 */ - -#endif /* !SDL_DISABLE_SYSWM_TYPES */ - - -#include -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the current version of structures in this file */ -#define SDL_SYSWM_CURRENT_VERSION 1 -#define SDL_SYSWM_INFO_SIZE_V1 (16 * (sizeof (void *) >= 8 ? sizeof (void *) : sizeof(Uint64))) -#define SDL_SYSWM_CURRENT_INFO_SIZE SDL_SYSWM_INFO_SIZE_V1 - -/* This is the tag associated with a Metal view so you can find it */ -#define SDL_METALVIEW_TAG 255 - - -/** - * These are the various supported windowing subsystems - */ -typedef enum -{ - SDL_SYSWM_UNKNOWN, - SDL_SYSWM_ANDROID, - SDL_SYSWM_COCOA, - SDL_SYSWM_HAIKU, - SDL_SYSWM_KMSDRM, - SDL_SYSWM_RISCOS, - SDL_SYSWM_UIKIT, - SDL_SYSWM_VIVANTE, - SDL_SYSWM_WAYLAND, - SDL_SYSWM_WINDOWS, - SDL_SYSWM_WINRT, - SDL_SYSWM_X11 -} SDL_SYSWM_TYPE; - -/** - * The custom event structure. - */ -struct SDL_SysWMmsg -{ - Uint32 version; - Uint32 subsystem; /**< SDL_SYSWM_TYPE */ - - Uint32 padding[(2 * (sizeof (void *) >= 8 ? sizeof (void *) : sizeof(Uint64)) - 2 * sizeof(Uint32)) / sizeof(Uint32)]; - - union - { -#ifdef SDL_ENABLE_SYSWM_WINDOWS - struct { - HWND hwnd; /**< The window for the message */ - UINT msg; /**< The type of message */ - WPARAM wParam; /**< WORD message parameter */ - LPARAM lParam; /**< LONG message parameter */ - } win; -#endif -#ifdef SDL_ENABLE_SYSWM_X11 - struct { - XEvent event; - } x11; -#endif - /* Can't have an empty union */ - int dummy; - } msg; -}; - -/** - * The custom window manager information structure. - * - * When this structure is returned, it holds information about which - * low level system it is using, and will be one of SDL_SYSWM_TYPE. - */ -struct SDL_SysWMinfo -{ - Uint32 version; - Uint32 subsystem; /**< SDL_SYSWM_TYPE */ - - Uint32 padding[(2 * (sizeof (void *) >= 8 ? sizeof (void *) : sizeof(Uint64)) - 2 * sizeof(Uint32)) / sizeof(Uint32)]; - - union - { -#ifdef SDL_ENABLE_SYSWM_WINDOWS - struct - { - HWND window; /**< The window handle */ - HDC hdc; /**< The window device context */ - HINSTANCE hinstance; /**< The instance handle */ - } win; -#endif -#ifdef SDL_ENABLE_SYSWM_WINRT - struct - { - IInspectable * window; /**< The WinRT CoreWindow */ - } winrt; -#endif -#ifdef SDL_ENABLE_SYSWM_X11 - struct - { - Display *display; /**< The X11 display */ - int screen; /**< The X11 screen */ - Window window; /**< The X11 window */ - } x11; -#endif -#ifdef SDL_ENABLE_SYSWM_COCOA - struct - { -#if defined(__OBJC__) && defined(__has_feature) - #if __has_feature(objc_arc) - NSWindow __unsafe_unretained *window; /**< The Cocoa window */ - #else - NSWindow *window; /**< The Cocoa window */ - #endif -#else - NSWindow *window; /**< The Cocoa window */ -#endif - } cocoa; -#endif -#ifdef SDL_ENABLE_SYSWM_UIKIT - struct - { -#if defined(__OBJC__) && defined(__has_feature) - #if __has_feature(objc_arc) - UIWindow __unsafe_unretained *window; /**< The UIKit window */ - #else - UIWindow *window; /**< The UIKit window */ - #endif -#else - UIWindow *window; /**< The UIKit window */ -#endif - GLuint framebuffer; /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */ - GLuint colorbuffer; /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */ - GLuint resolveFramebuffer; /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */ - } uikit; -#endif -#ifdef SDL_ENABLE_SYSWM_WAYLAND - struct - { - struct wl_display *display; /**< Wayland display */ - struct wl_surface *surface; /**< Wayland surface */ - struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */ - struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */ - struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */ - struct xdg_popup *xdg_popup; /**< Wayland xdg popup role */ - struct xdg_positioner *xdg_positioner; /**< Wayland xdg positioner, for popup */ - } wl; -#endif - -#ifdef SDL_ENABLE_SYSWM_ANDROID - struct - { - ANativeWindow *window; - EGLSurface surface; - } android; -#endif - -#ifdef SDL_ENABLE_SYSWM_VIVANTE - struct - { - EGLNativeDisplayType display; - EGLNativeWindowType window; - } vivante; -#endif - -#ifdef SDL_ENABLE_SYSWM_KMSDRM - struct - { - int dev_index; /**< Device index (ex: the X in /dev/dri/cardX) */ - int drm_fd; /**< DRM FD (unavailable on Vulkan windows) */ - struct gbm_device *gbm_dev; /**< GBM device (unavailable on Vulkan windows) */ - } kmsdrm; -#endif - - /* Make sure this union has enough room for 14 pointers */ - void *dummy_ptrs[14]; - Uint64 dummy_ints[14]; - } info; -}; -SDL_COMPILE_TIME_ASSERT(SDL_SysWMinfo_size, sizeof(struct SDL_SysWMinfo) == SDL_SYSWM_CURRENT_INFO_SIZE); - -typedef struct SDL_SysWMinfo SDL_SysWMinfo; - - -/** - * Get driver-specific information about a window. - * - * You must include SDL_syswm.h for the declaration of SDL_SysWMinfo. - * - * \param window the window about which information is being requested - * \param info an SDL_SysWMinfo structure filled in with window information - * \param version the version of info being requested, should be - * SDL_SYSWM_CURRENT_VERSION - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC int SDLCALL SDL_GetWindowWMInfo(SDL_Window *window, SDL_SysWMinfo *info, Uint32 version); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include - -#endif /* SDL_syswm_h_ */ diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 3f79502556f02..567e9437fb4b8 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -934,6 +934,55 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); /** * Get the properties associated with a window. * + * The following properties are provided by SDL: + * + * On Android: + * "SDL.window.android.window" - the ANativeWindow associated with the window + * "SDL.window.android.surface" - the EGLSurface associated with the window + * + * On iOS: + * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window + * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * + * On KMS/DRM: + * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) + * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window + * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window + * + * On macOS: + * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window + * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * + * On Vivante: + * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window + * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window + * "SDL.window.vivante.surface" - the EGLSurface associated with the window + * + * On UWP: + * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window + * + * On Windows: + * "SDL.window.win32.hwnd" - the HWND associated with the window + * "SDL.window.win32.hdc" - the HDC associated with the window + * "SDL.window.win32.instance" - the HINSTANCE associated with the window + * + * On Wayland: + * "SDL.window.wayland.display" - the wl_display associated with the window + * "SDL.window.wayland.surface" - the wl_surface associated with the window + * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window + * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window + * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window + * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode + * + * Note: The xdg_* window objects do not internally persist across window show/hide calls. + * They will be null if the window is hidden and must be queried each time it is shown. + * + * On X11: + * "SDL.window.x11.display" - the X11 Display associated with the window + * "SDL.window.x11.screen" - the screen number associated with the window + * "SDL.window.x11.window" - the X11 Window associated with the window + * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 091751fb3fb0f..b776251f81e42 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -415,62 +415,6 @@ #cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@ #cmakedefine SDL_VIDEO_DRIVER_QNX @SDL_VIDEO_DRIVER_QNX@ -#ifdef SDL_VIDEO_DRIVER_ANDROID -#define SDL_ENABLE_SYSWM_ANDROID -#else -#define SDL_DISABLE_SYSWM_ANDROID -#endif -#ifdef SDL_VIDEO_DRIVER_COCOA -#define SDL_ENABLE_SYSWM_COCOA -#else -#define SDL_DISABLE_SYSWM_COCOA -#endif -#ifdef SDL_VIDEO_DRIVER_HAIKU -#define SDL_ENABLE_SYSWM_HAIKU -#else -#define SDL_DISABLE_SYSWM_HAIKU -#endif -#ifdef SDL_VIDEO_DRIVER_KMSDRM -#define SDL_ENABLE_SYSWM_KMSDRM -#else -#define SDL_DISABLE_SYSWM_KMSDRM -#endif -#ifdef SDL_VIDEO_DRIVER_RISCOS -#define SDL_ENABLE_SYSWM_RISCOS -#else -#define SDL_DISABLE_SYSWM_RISCOS -#endif -#ifdef SDL_VIDEO_DRIVER_UIKIT -#define SDL_ENABLE_SYSWM_UIKIT -#else -#define SDL_DISABLE_SYSWM_UIKIT -#endif -#ifdef SDL_VIDEO_DRIVER_VIVANTE -#define SDL_ENABLE_SYSWM_VIVANTE -#else -#define SDL_DISABLE_SYSWM_VIVANTE -#endif -#ifdef SDL_VIDEO_DRIVER_WAYLAND -#define SDL_ENABLE_SYSWM_WAYLAND -#else -#define SDL_DISABLE_SYSWM_WAYLAND -#endif -#ifdef SDL_VIDEO_DRIVER_WINDOWS -#define SDL_ENABLE_SYSWM_WINDOWS -#else -#define SDL_DISABLE_SYSWM_WINDOWS -#endif -#ifdef SDL_VIDEO_DRIVER_WINRT -#define SDL_ENABLE_SYSWM_WINRT -#else -#define SDL_DISABLE_SYSWM_WINRT -#endif -#ifdef SDL_VIDEO_DRIVER_X11 -#define SDL_ENABLE_SYSWM_X11 -#else -#define SDL_DISABLE_SYSWM_X11 -#endif - #cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@ #cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@ #cmakedefine SDL_VIDEO_RENDER_D3D12 @SDL_VIDEO_RENDER_D3D12@ diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c index 5e1f82834944c..82329b0f0b057 100644 --- a/src/core/SDL_core_unsupported.c +++ b/src/core/SDL_core_unsupported.c @@ -20,6 +20,14 @@ */ #include "SDL_internal.h" +#ifndef SDL_VIDEO_DRIVER_X11 + +DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) +{ +} + +#endif + #ifndef __LINUX__ DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index bbf3f453764aa..0efd7dc5b6a17 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -29,7 +29,6 @@ #ifdef SDL_VIDEO_DRIVER_X11 #include "../../video/x11/SDL_x11video.h" #endif -#include #define FCITX_DBUS_SERVICE "org.freedesktop.portal.Fcitx" @@ -412,7 +411,6 @@ SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) { SDL_Window *focused_win = NULL; - SDL_SysWMinfo info; int x = 0, y = 0; SDL_Rect *cursor = &fcitx_client.cursor_rect; @@ -427,17 +425,18 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) SDL_GetWindowPosition(focused_win, &x, &y); - if (SDL_GetWindowWMInfo(focused_win, &info, SDL_SYSWM_CURRENT_VERSION) == 0) { -#ifdef SDL_ENABLE_SYSWM_X11 - if (info.subsystem == SDL_SYSWM_X11) { - Display *x_disp = info.info.x11.display; - int x_screen = info.info.x11.screen; - Window x_win = info.info.x11.window; - Window unused; +#ifdef SDL_VIDEO_DRIVER_X11 + { + SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); + Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display"); + int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen"); + Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window"); + Window unused; + if (x_disp && x_win) { X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused); } -#endif } +#endif if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) { /* move to bottom left */ diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 237c300fcd91e..5997b046ddfa5 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -32,7 +32,6 @@ #ifdef SDL_VIDEO_DRIVER_X11 #include "../../video/x11/SDL_x11video.h" #endif -#include #include #include @@ -689,7 +688,6 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) { SDL_Window *focused_win; - SDL_SysWMinfo info; int x = 0, y = 0; SDL_DBusContext *dbus; @@ -704,18 +702,19 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) SDL_GetWindowPosition(focused_win, &x, &y); - if (SDL_GetWindowWMInfo(focused_win, &info, SDL_SYSWM_CURRENT_VERSION) == 0) { -#ifdef SDL_ENABLE_SYSWM_X11 - if (info.subsystem == SDL_SYSWM_X11) { - Display *x_disp = info.info.x11.display; - int x_screen = info.info.x11.screen; - Window x_win = info.info.x11.window; - Window unused; - +#ifdef SDL_VIDEO_DRIVER_X11 + { + SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); + Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display"); + int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen"); + Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window"); + Window unused; + + if (x_disp && x_win) { X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused); } -#endif } +#endif x += ibus_cursor_rect.x; y += ibus_cursor_rect.y; diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 23cf60432e301..833a98072d898 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -37,7 +37,6 @@ /* These headers have system specific definitions, so aren't included above */ -#include #include /* This is the version of the dynamic API. This doesn't match the SDL version diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index dc1899f9bea3d..720591affbeb2 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -360,7 +360,6 @@ SDL3_0.0.0 { SDL_GetWindowSizeInPixels; SDL_GetWindowSurface; SDL_GetWindowTitle; - SDL_GetWindowWMInfo; SDL_GetYUVConversionMode; SDL_GetYUVConversionModeForResolution; SDL_HapticClose; @@ -922,6 +921,7 @@ SDL3_0.0.0 { SDL_AllocateEventMemory; SDL_GetDisplayProperties; SDL_SetPropertyWithCleanup; + SDL_SetX11EventHook; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 35fff15baf806..a6c5440ca33d1 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -384,7 +384,6 @@ #define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL #define SDL_GetWindowSurface SDL_GetWindowSurface_REAL #define SDL_GetWindowTitle SDL_GetWindowTitle_REAL -#define SDL_GetWindowWMInfo SDL_GetWindowWMInfo_REAL #define SDL_GetYUVConversionMode SDL_GetYUVConversionMode_REAL #define SDL_GetYUVConversionModeForResolution SDL_GetYUVConversionModeForResolution_REAL #define SDL_HapticClose SDL_HapticClose_REAL @@ -947,3 +946,4 @@ #define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL #define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL +#define SDL_SetX11EventHook SDL_SetX11EventHook_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 9f28f67448287..3348c67a8f44d 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -443,7 +443,6 @@ SDL_DYNAPI_PROC(int,SDL_GetWindowSize,(SDL_Window *a, int *b, int *c),(a,b,c),re SDL_DYNAPI_PROC(int,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetWindowTitle,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowWMInfo,(SDL_Window *a, SDL_SysWMinfo *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionMode,(void),(),return) SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionModeForResolution,(int a, int b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_HapticClose,(SDL_Haptic *a),(a),) @@ -980,3 +979,4 @@ SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 337180dbc7947..f79f46970e3e2 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -33,7 +33,6 @@ #include "../sensor/SDL_sensor_c.h" #endif #include "../video/SDL_sysvideo.h" -#include #undef SDL_PRIs64 #if (defined(__WIN32__) || defined(__GDK__)) && !defined(__CYGWIN__) @@ -194,7 +193,6 @@ static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, co * - 0: (default) no logging * - 1: logging of most events * - 2: as above, plus mouse and finger motion - * - 3: as above, plus SDL_SysWMEvents */ static int SDL_EventLoggingVerbosity = 0; @@ -218,11 +216,6 @@ static void SDL_LogEvent(const SDL_Event *event) return; } - /* window manager events are even more spammy, and don't provide much useful info. */ - if ((SDL_EventLoggingVerbosity < 3) && (event->type == SDL_EVENT_SYSWM)) { - return; - } - /* this is to make (void)SDL_snprintf() calls cleaner. */ #define uint unsigned int @@ -321,11 +314,6 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED); #undef SDL_WINDOWEVENT_CASE - SDL_EVENT_CASE(SDL_EVENT_SYSWM) - /* !!! FIXME: we don't delve further at the moment. */ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u)", (uint)event->syswm.timestamp); - break; - #define PRINT_KEY_EVENT(event) \ (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \ (uint)event->key.timestamp, (uint)event->key.windowID, \ @@ -644,7 +632,6 @@ int SDL_StartEventLoop(void) /* Process most event types */ SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, SDL_FALSE); SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_SYSWM, SDL_FALSE); #if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */ SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_FALSE); SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_FALSE); @@ -1405,27 +1392,6 @@ int SDL_SendAppEvent(SDL_EventType eventType) return posted; } -int SDL_SendSysWMEvent(SDL_SysWMmsg *message) -{ - int posted; - - posted = 0; - if (SDL_EventEnabled(SDL_EVENT_SYSWM)) { - SDL_Event event; - SDL_memset(&event, 0, sizeof(event)); - event.type = SDL_EVENT_SYSWM; - event.common.timestamp = 0; - event.syswm.msg = (SDL_SysWMmsg *)SDL_AllocateEventMemory(sizeof(*message)); - if (!event.syswm.msg) { - return 0; - } - SDL_copyp(event.syswm.msg, message); - posted = (SDL_PushEvent(&event) > 0); - } - /* Update internal event state */ - return posted; -} - int SDL_SendKeymapChangedEvent(void) { return SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED); diff --git a/src/events/SDL_events_c.h b/src/events/SDL_events_c.h index 44c3eb8d110f4..8c6310cd25b27 100644 --- a/src/events/SDL_events_c.h +++ b/src/events/SDL_events_c.h @@ -41,7 +41,6 @@ extern void SDL_StopEventLoop(void); extern void SDL_QuitInterrupt(void); extern int SDL_SendAppEvent(SDL_EventType eventType); -extern int SDL_SendSysWMEvent(SDL_SysWMmsg *message); extern int SDL_SendKeymapChangedEvent(void); extern int SDL_SendLocaleChangedEvent(void); extern int SDL_SendSystemThemeChangedEvent(void); diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index abfe5d5e06d41..9324087eb8bb0 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -28,8 +28,6 @@ #include "../SDL_d3dmath.h" #include "../../video/windows/SDL_windowsvideo.h" -#include - #ifdef SDL_VIDEO_RENDER_D3D #define D3D_DEBUG_INFO #include @@ -1542,7 +1540,6 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) { SDL_Renderer *renderer; D3D_RenderData *data; - SDL_SysWMinfo windowinfo; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; @@ -1552,12 +1549,6 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_DisplayID displayID; const SDL_DisplayMode *fullscreen_mode = NULL; - if (SDL_GetWindowWMInfo(window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 || - windowinfo.subsystem != SDL_SYSWM_WINDOWS) { - SDL_SetError("Couldn't get window handle"); - return NULL; - } - renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (renderer == NULL) { SDL_OutOfMemory(); @@ -1611,7 +1602,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) } SDL_zero(pparams); - pparams.hDeviceWindow = windowinfo.info.win.window; + pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; pparams.BackBufferCount = 1; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index f15344ad204fa..ef11c7de3b074 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -30,8 +30,6 @@ #include "../SDL_sysrender.h" #include "../SDL_d3dmath.h" -#include - #include #include "SDL_shaders_d3d11.h" @@ -827,18 +825,11 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) #endif } else { #if defined(__WIN32__) || defined(__WINGDK__) - SDL_SysWMinfo windowinfo; - - if (SDL_GetWindowWMInfo(renderer->window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 || - windowinfo.subsystem != SDL_SYSWM_WINDOWS) { - SDL_SetError("Couldn't get window handle"); - result = E_FAIL; - goto done; - } + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd"); result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory, (IUnknown *)data->d3dDevice, - windowinfo.info.win.window, + hwnd, &swapChainDesc, NULL, NULL, /* Allow on all displays. */ @@ -848,7 +839,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) goto done; } - IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES); + IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, hwnd, DXGI_MWA_NO_WINDOW_CHANGES); #else SDL_SetError(__FUNCTION__ ", Unable to find something to attach a swap chain to"); goto done; diff --git a/src/render/direct3d11/SDL_render_winrt.cpp b/src/render/direct3d11/SDL_render_winrt.cpp index 0bf3609cf5648..4ecd41908771d 100644 --- a/src/render/direct3d11/SDL_render_winrt.cpp +++ b/src/render/direct3d11/SDL_render_winrt.cpp @@ -39,35 +39,14 @@ using namespace Windows::Graphics::Display; #include -#include - #include "SDL_render_winrt.h" extern "C" void * D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer) { - SDL_Window *sdlWindow = renderer->window; - if (renderer->window == NULL) { - return NULL; - } - - SDL_SysWMinfo sdlWindowInfo; - if (SDL_GetWindowWMInfo(sdlWindow, &sdlWindowInfo, SDL_SYSWM_CURRENT_VERSION) < 0 || - sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) { - SDL_SetError("Couldn't get window handle"); - return NULL; - } - - if (sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) { - return NULL; - } - - if (!sdlWindowInfo.info.winrt.window) { - return NULL; - } - + IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window"); ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL; - if (FAILED(sdlWindowInfo.info.winrt.window->QueryInterface(&coreWindow))) { + if (!window || FAILED(window->QueryInterface(&coreWindow))) { return NULL; } diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 7c0fa525aa021..2fd1f00d10b5d 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -32,8 +32,6 @@ #include "../SDL_sysrender.h" #include "../SDL_d3dmath.h" -#include - #if defined(__XBOXONE__) || defined(__XBOXSERIES__) #include "SDL_render_d3d12_xbox.h" #ifndef D3D12_TEXTURE_DATA_PITCH_ALIGNMENT @@ -1153,7 +1151,6 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h) D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata; IDXGISwapChain1 *swapChain = NULL; HRESULT result = S_OK; - SDL_SysWMinfo windowinfo; /* Create a swap chain using the same adapter as the existing Direct3D device. */ DXGI_SWAP_CHAIN_DESC1 swapChainDesc; @@ -1175,16 +1172,11 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h) swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | /* To support SetMaximumFrameLatency */ DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; /* To support presenting with allow tearing on */ - if (SDL_GetWindowWMInfo(renderer->window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 || - windowinfo.subsystem != SDL_SYSWM_WINDOWS) { - SDL_SetError("Couldn't get window handle"); - result = E_FAIL; - goto done; - } + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd"); result = D3D_CALL(data->dxgiFactory, CreateSwapChainForHwnd, (IUnknown *)data->commandQueue, - windowinfo.info.win.window, + hwnd, &swapChainDesc, NULL, NULL, /* Allow on all displays. */ @@ -1194,7 +1186,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h) goto done; } - D3D_CALL(data->dxgiFactory, MakeWindowAssociation, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES); + D3D_CALL(data->dxgiFactory, MakeWindowAssociation, hwnd, DXGI_MWA_NO_WINDOW_CHANGES); result = D3D_CALL(swapChain, QueryInterface, D3D_GUID(SDL_IID_IDXGISwapChain4), (void **)&data->swapChain); if (FAILED(result)) { diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 3f038f272d3f3..606b17f17dc24 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -35,7 +35,6 @@ #ifdef SDL_VIDEO_DRIVER_UIKIT #import #endif -#include /* Regenerate these with build-metal-shaders.sh */ #ifdef __MACOS__ @@ -160,20 +159,16 @@ @interface METAL_TextureData : NSObject @implementation METAL_TextureData @end -static int IsMetalAvailable(const SDL_SysWMinfo *syswm) +static SDL_bool IsMetalAvailable() { - if (syswm->subsystem != SDL_SYSWM_COCOA && syswm->subsystem != SDL_SYSWM_UIKIT) { - return SDL_SetError("Metal render target only supports Cocoa and UIKit video targets at the moment."); - } - - // this checks a weak symbol. #if (defined(__MACOS__) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101100)) + // this checks a weak symbol. if (MTLCreateSystemDefaultDevice == NULL) { // probably on 10.10 or lower. - return SDL_SetError("Metal framework not available on this system"); + SDL_SetError("Metal framework not available on this system"); + return SDL_FALSE; } #endif - - return 0; + return SDL_TRUE; } static const MTLBlendOperation invalidBlendOperation = (MTLBlendOperation)0xFFFFFFFF; @@ -1630,29 +1625,31 @@ static int METAL_SetVSync(SDL_Renderer *renderer, const int vsync) static SDL_MetalView GetWindowView(SDL_Window *window) { - SDL_SysWMinfo info; - - if (SDL_GetWindowWMInfo(window, &info, SDL_SYSWM_CURRENT_VERSION) == 0) { -#ifdef SDL_ENABLE_SYSWM_COCOA - if (info.subsystem == SDL_SYSWM_COCOA) { - NSView *view = info.info.cocoa.window.contentView; - if (view.subviews.count > 0) { - view = view.subviews[0]; - if (view.tag == SDL_METALVIEW_TAG) { - return (SDL_MetalView)CFBridgingRetain(view); - } - } - } -#endif -#ifdef SDL_ENABLE_SYSWM_UIKIT - if (info.subsystem == SDL_SYSWM_UIKIT) { - UIView *view = info.info.uikit.window.rootViewController.view; - if (view.tag == SDL_METALVIEW_TAG) { +#ifdef SDL_VIDEO_DRIVER_COCOA + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window"); + NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag"); + if (nswindow) { + NSView *view = nswindow.contentView; + if (view.subviews.count > 0) { + view = view.subviews[0]; + if (view.tag == tag) { return (SDL_MetalView)CFBridgingRetain(view); } } + } #endif + +#ifdef SDL_VIDEO_DRIVER_UIKIT + UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window"); + NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag"); + if (uiwindow) { + UIView *view = uiwindow.rootViewController.view; + if (view.tag == tag) { + return (SDL_MetalView)CFBridgingRetain(view); + } } +#endif + return nil; } @@ -1664,7 +1661,6 @@ static SDL_MetalView GetWindowView(SDL_Window *window) id mtldevice = nil; SDL_MetalView view = NULL; CAMetalLayer *layer = nil; - SDL_SysWMinfo syswm; NSError *err = nil; dispatch_data_t mtllibdata; char *constantdata; @@ -1740,11 +1736,7 @@ static SDL_MetalView GetWindowView(SDL_Window *window) 1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */ }; - if (SDL_GetWindowWMInfo(window, &syswm, SDL_SYSWM_CURRENT_VERSION) < 0) { - return NULL; - } - - if (IsMetalAvailable(&syswm) == -1) { + if (!IsMetalAvailable()) { return NULL; } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 3db2d85b1fedf..fe3e5fd52a4de 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -151,9 +151,6 @@ struct SDL_VideoDisplay SDL_DisplayData *driverdata; }; -/* Forward declaration */ -struct SDL_SysWMinfo; - /* Video device flags */ typedef enum { @@ -267,9 +264,6 @@ struct SDL_VideoDevice */ SDL_ShapeDriver shape_driver; - /* Get some platform dependent window information */ - int (*GetWindowWMInfo)(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); - /* * * */ /* * OpenGL support diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index a4f771b74c314..bb983b902a01d 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -32,8 +32,6 @@ #include "../events/SDL_events_c.h" #include "../timer/SDL_timer_c.h" -#include - #ifdef SDL_VIDEO_OPENGL #include #endif /* SDL_VIDEO_OPENGL */ @@ -4671,33 +4669,6 @@ void SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask) } #endif -int SDL_GetWindowWMInfo(SDL_Window *window, struct SDL_SysWMinfo *info, Uint32 version) -{ - CHECK_WINDOW_MAGIC(window, -1); - - if (info == NULL) { - return SDL_InvalidParamError("info"); - } - - /* Set the version in the structure to the minimum of our version and the application expected version */ - version = SDL_min(version, SDL_SYSWM_CURRENT_VERSION); - - if (version == 1) { - SDL_memset(info, 0, SDL_SYSWM_INFO_SIZE_V1); - } else { - return SDL_SetError("Unknown info version"); - } - - info->subsystem = SDL_SYSWM_UNKNOWN; - info->version = version; - - if (_this->GetWindowWMInfo) { - return (_this->GetWindowWMInfo(_this, window, info)); - } else { - return 0; - } -} - void SDL_StartTextInput(void) { SDL_Window *window; @@ -4827,20 +4798,6 @@ int SDL_GetMessageBoxCount(void) #include "vita/SDL_vitamessagebox.h" #endif -#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_WINRT) || defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT) || defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_HAIKU) || defined(SDL_VIDEO_DRIVER_RISCOS) -static SDL_bool SDL_IsMessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype) -{ - SDL_SysWMinfo info; - SDL_Window *window = messageboxdata->window; - - if (window == NULL || SDL_GetWindowWMInfo(window, &info, SDL_SYSWM_CURRENT_VERSION) < 0) { - return SDL_TRUE; - } else { - return info.subsystem == (Uint32)drivertype; - } -} -#endif - int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { int dummybutton; @@ -4894,56 +4851,48 @@ int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) #endif #if defined(SDL_VIDEO_DRIVER_WINDOWS) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINDOWS) && WIN_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_WINRT if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINRT) && WINRT_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_COCOA if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_COCOA) && Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_UIKIT if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_UIKIT) && UIKit_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_WAYLAND if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) && Wayland_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_X11 if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_X11) && X11_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_HAIKU if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_HAIKU) && HAIKU_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } #endif #ifdef SDL_VIDEO_DRIVER_RISCOS if (retval == -1 && - SDL_IsMessageboxValidForDriver(messageboxdata, SDL_SYSWM_RISCOS) && RISCOS_ShowMessageBox(messageboxdata, buttonid) == 0) { retval = 0; } diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index ede5b1c9631c0..96cc2d7edb869 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -117,7 +117,6 @@ static SDL_VideoDevice *Android_CreateDevice(void) device->MinimizeWindow = Android_MinimizeWindow; device->SetWindowResizable = Android_SetWindowResizable; device->DestroyWindow = Android_DestroyWindow; - device->GetWindowWMInfo = Android_GetWindowWMInfo; device->free = Android_DeleteDevice; diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c index 85f044f48bdfc..1d1577cfff09f 100644 --- a/src/video/android/SDL_androidvulkan.c +++ b/src/video/android/SDL_androidvulkan.c @@ -35,7 +35,6 @@ #include "SDL_androidvulkan.h" -#include int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) { diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 491765529f36c..1ef9cd518269d 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -31,7 +31,6 @@ #include "SDL_androidvideo.h" #include "SDL_androidwindow.h" -#include /* Currently only one window */ SDL_Window *Android_Window = NULL; @@ -68,12 +67,12 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } data->native_window = Android_JNI_GetNativeWindow(); - if (!data->native_window) { SDL_free(data); retval = SDL_SetError("Could not fetch native window"); goto endfunction; } + SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.android.window", data->native_window); /* Do not create EGLSurface for Vulkan window since it will then make the window incompatible with vkCreateAndroidSurfaceKHR */ @@ -88,6 +87,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) goto endfunction; } } + SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.android.surface", data->egl_surface); #endif window->driverdata = data; @@ -194,18 +194,4 @@ void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_UnlockMutex(Android_ActivityMutex); } -int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - SDL_WindowData *data = window->driverdata; - - info->subsystem = SDL_SYSWM_ANDROID; - info->info.android.window = data->native_window; - -#ifdef SDL_VIDEO_OPENGL_EGL - info->info.android.surface = data->egl_surface; -#endif - - return 0; -} - #endif /* SDL_VIDEO_DRIVER_ANDROID */ diff --git a/src/video/android/SDL_androidwindow.h b/src/video/android/SDL_androidwindow.h index 439156119d030..ea81d3bc802d9 100644 --- a/src/video/android/SDL_androidwindow.h +++ b/src/video/android/SDL_androidwindow.h @@ -33,7 +33,6 @@ extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); extern void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); extern SDL_Window *Android_Window; struct SDL_WindowData diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m index 46d11251e8c0b..08a5c0d472872 100644 --- a/src/video/cocoa/SDL_cocoametalview.m +++ b/src/video/cocoa/SDL_cocoametalview.m @@ -30,8 +30,6 @@ #if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL)) -#include - static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event) { /* Update the drawable size when SDL receives a size changed event for diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 3b6092b00cb29..bd2fdf8148bb8 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -115,7 +115,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab; device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab; device->DestroyWindow = Cocoa_DestroyWindow; - device->GetWindowWMInfo = Cocoa_GetWindowWMInfo; device->SetWindowHitTest = Cocoa_SetWindowHitTest; device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop; device->FlashWindow = Cocoa_FlashWindow; diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index d5d3cb88da69f..a018db5a82805 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -33,8 +33,6 @@ #include "SDL_cocoametalview.h" #include "SDL_cocoavulkan.h" -#include - #include const char *defaultPaths[] = { diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 1408784b28e1d..8e4158cf6724a 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -29,6 +29,8 @@ #include "../SDL_egl_c.h" #endif +#define SDL_METALVIEW_TAG 255 + @class SDL_CocoaWindowData; typedef enum @@ -165,7 +167,6 @@ extern SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Windo extern void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); extern void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int Cocoa_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept); extern int Cocoa_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 970e8e1f17cdd..c7e004b220217 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -41,7 +41,6 @@ #include "SDL_cocoaopengl.h" #include "SDL_cocoaopengles.h" -#include /* #define DEBUG_COCOAWINDOW */ @@ -1863,6 +1862,10 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow */ [nswindow setOneShot:NO]; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.cocoa.window", (__bridge void *)data.nswindow); + SDL_SetProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG); + /* All done! */ window->driverdata = (SDL_WindowData *)CFBridgingRetain(data); return 0; @@ -2580,17 +2583,6 @@ void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -int Cocoa_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - @autoreleasepool { - NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; - - info->subsystem = SDL_SYSWM_COCOA; - info->info.cocoa.window = nswindow; - return 0; - } -} - SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window) { @autoreleasepool { diff --git a/src/video/haiku/SDL_BWin.h b/src/video/haiku/SDL_BWin.h index e053f483c3b72..4cd1582cd9b7c 100644 --- a/src/video/haiku/SDL_BWin.h +++ b/src/video/haiku/SDL_BWin.h @@ -29,8 +29,6 @@ extern "C" { #include "SDL_internal.h" #include "SDL_bframebuffer.h" -#include - #ifdef __cplusplus } #endif diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 14e3ef2fd6ed8..86b8037d531b0 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -91,7 +91,6 @@ static SDL_VideoDevice * HAIKU_CreateDevice(void) device->SetWindowMouseGrab = HAIKU_SetWindowMouseGrab; device->SetWindowMinimumSize = HAIKU_SetWindowMinimumSize; device->DestroyWindow = HAIKU_DestroyWindow; - device->GetWindowWMInfo = HAIKU_GetWindowWMInfo; device->CreateWindowFramebuffer = HAIKU_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = HAIKU_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = HAIKU_DestroyWindowFramebuffer; diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index 2d309e6aa07e1..f69bec1f67e03 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -26,8 +26,6 @@ #include "SDL_BWin.h" #include -#include - /* Define a path to window's BWIN data */ #ifdef __cplusplus extern "C" { @@ -211,13 +209,6 @@ void HAIKU_DestroyWindow(SDL_VideoDevice *_this, SDL_Window * window) { window->driverdata = NULL; } -int HAIKU_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info) -{ - info->subsystem = SDL_SYSWM_HAIKU; - return 0; -} - - #ifdef __cplusplus } #endif diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index 0597acbcedd20..400fa9467a5a4 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -41,6 +41,5 @@ extern void HAIKU_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, extern void HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void HAIKU_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int HAIKU_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); #endif diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 5312a584e93d5..15b943b724c96 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -35,8 +35,6 @@ #include "../../core/openbsd/SDL_wscons.h" #endif -#include - /* KMS/DRM declarations */ #include "SDL_kmsdrmdyn.h" #include "SDL_kmsdrmevents.h" @@ -295,7 +293,6 @@ static SDL_VideoDevice *KMSDRM_CreateDevice(void) device->MinimizeWindow = KMSDRM_MinimizeWindow; device->RestoreWindow = KMSDRM_RestoreWindow; device->DestroyWindow = KMSDRM_DestroyWindow; - device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo; device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary; device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress; @@ -1437,6 +1434,11 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) windata->viddata = viddata; window->driverdata = windata; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.kmsdrm.dev_index", (void *)(intptr_t)viddata->devindex); + SDL_SetProperty(props, "SDL.window.kmsdrm.drm_fd", (void *)(intptr_t)viddata->drm_fd); + SDL_SetProperty(props, "SDL.window.kmsdrm.gbm_dev", viddata->gbm_dev); + if (!is_vulkan && !vulkan_mode) { /* NON-Vulkan block. */ /* Maybe you didn't ask for an OPENGL window, but that's what you will get. @@ -1595,19 +1597,4 @@ void KMSDRM_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { } -/*****************************************************************************/ -/* SDL Window Manager function */ -/*****************************************************************************/ -int KMSDRM_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info) -{ - SDL_VideoData *viddata = _this->driverdata; - - info->subsystem = SDL_SYSWM_KMSDRM; - info->info.kmsdrm.dev_index = viddata->devindex; - info->info.kmsdrm.drm_fd = viddata->drm_fd; - info->info.kmsdrm.gbm_dev = viddata->gbm_dev; - - return 0; -} - #endif /* SDL_VIDEO_DRIVER_KMSDRM */ diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index 24e03fb9b0cc1..d488fc84aed89 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -135,9 +135,6 @@ void KMSDRM_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -/* Window manager function */ -int KMSDRM_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); - /* OpenGL/OpenGL ES functions */ int KMSDRM_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); SDL_FunctionPointer KMSDRM_GLES_GetProcAddress(SDL_VideoDevice *_this, const char *proc); diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index 20b6516e35410..038bd2db92dcb 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -34,8 +34,6 @@ #include "SDL_kmsdrmdyn.h" #include "SDL_kmsdrmvulkan.h" -#include - #include #ifdef __OpenBSD__ diff --git a/src/video/ngage/SDL_ngagewindow.h b/src/video/ngage/SDL_ngagewindow.h index 1418ab7c3a714..811142dd7e632 100644 --- a/src/video/ngage/SDL_ngagewindow.h +++ b/src/video/ngage/SDL_ngagewindow.h @@ -24,8 +24,6 @@ #include "../SDL_sysvideo.h" -#include - #include "SDL_ngagevideo.h" typedef struct @@ -34,10 +32,7 @@ typedef struct } NGAGE_Window; -extern int -NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); - -extern void -NGAGE_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern void NGAGE_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_ngagewindow */ diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 7b47fa38b4d0b..5cf0d7288d55d 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -28,8 +28,6 @@ #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_keyboard_c.h" -#include - /* PSP declarations */ #include "SDL_pspvideo.h" #include "SDL_pspevents_c.h" diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 40519a9236457..3d5d0888b4383 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -35,8 +35,6 @@ #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_keyboard_c.h" -#include - #ifdef SDL_INPUT_LINUXEV #include "../../core/linux/SDL_evdev.h" #endif diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c index dd57ce839e573..a2df367f994df 100644 --- a/src/video/riscos/SDL_riscosvideo.c +++ b/src/video/riscos/SDL_riscosvideo.c @@ -79,7 +79,6 @@ static SDL_VideoDevice *RISCOS_CreateDevice(void) device->CreateSDLWindow = RISCOS_CreateWindow; device->DestroyWindow = RISCOS_DestroyWindow; - device->GetWindowWMInfo = RISCOS_GetWindowWMInfo; device->CreateWindowFramebuffer = RISCOS_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = RISCOS_UpdateWindowFramebuffer; diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c index 80a0e94f7f43e..b0a3a207a50e3 100644 --- a/src/video/riscos/SDL_riscoswindow.c +++ b/src/video/riscos/SDL_riscoswindow.c @@ -25,8 +25,6 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_mouse_c.h" -#include - #include "SDL_riscosvideo.h" #include "SDL_riscoswindow.h" @@ -61,10 +59,4 @@ void RISCOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) window->driverdata = NULL; } -int RISCOS_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info) -{ - info->subsystem = SDL_SYSWM_RISCOS; - return 0; -} - #endif /* SDL_VIDEO_DRIVER_RISCOS */ diff --git a/src/video/riscos/SDL_riscoswindow.h b/src/video/riscos/SDL_riscoswindow.h index e05466481a3be..6899a3d2a8016 100644 --- a/src/video/riscos/SDL_riscoswindow.h +++ b/src/video/riscos/SDL_riscoswindow.h @@ -34,6 +34,5 @@ struct SDL_WindowData extern int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void RISCOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int RISCOS_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); #endif /* SDL_riscoswindow_h_ */ diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index c5317ebd900c0..accda70361c36 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -35,8 +35,6 @@ #import "SDL_uikitwindow.h" #import "SDL_uikitmetalview.h" -#include - @implementation SDL_uikitmetalview /* Returns a Metal-compatible layer. */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 0e1919bde3ebd..0c37b33421f42 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -94,7 +94,6 @@ static void UIKit_DeleteDevice(SDL_VideoDevice *device) device->SetWindowFullscreen = UIKit_SetWindowFullscreen; device->SetWindowMouseGrab = UIKit_SetWindowMouseGrab; device->DestroyWindow = UIKit_DestroyWindow; - device->GetWindowWMInfo = UIKit_GetWindowWMInfo; device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds; device->GetWindowSizeInPixels = UIKit_GetWindowSizeInPixels; diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m index b6191ae0b3c08..a8816a4eb62fe 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -34,8 +34,6 @@ #include "SDL_uikitvulkan.h" #include "SDL_uikitmetalview.h" -#include - #include const char *defaultPaths[] = { diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index ba89566293a42..64ba38c13d2ed 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -37,10 +37,11 @@ extern void UIKit_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, extern void UIKit_UpdatePointerLock(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h); -extern int UIKit_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window *window); +#define SDL_METALVIEW_TAG 255 + @class UIWindow; @interface SDL_UIKitWindowData : NSObject diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index ed8c6dcd1722c..407e6edf4d518 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -34,8 +34,6 @@ #include "SDL_uikitview.h" #include "SDL_uikitopenglview.h" -#include - #include @implementation SDL_UIKitWindowData @@ -86,13 +84,13 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window); SDL_UIKitDisplayData *displaydata = (__bridge SDL_UIKitDisplayData *)display->driverdata; SDL_uikitview *view; - + #if TARGET_OS_XR CGRect frame = UIKit_ComputeViewFrame(window); #else CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); #endif - + int width = (int)frame.size.width; int height = (int)frame.size.height; @@ -155,6 +153,10 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow * hierarchy. */ [view setSDLWindow:window]; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.uikit.window", (__bridge void *)data.uiwindow); + SDL_SetProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG); + return 0; } @@ -385,26 +387,6 @@ void UIKit_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int } } -int UIKit_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - @autoreleasepool { - SDL_UIKitWindowData *data = (__bridge SDL_UIKitWindowData *)window->driverdata; - - info->subsystem = SDL_SYSWM_UIKIT; - info->info.uikit.window = data.uiwindow; - -#if defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2) - if ([data.viewcontroller.view isKindOfClass:[SDL_uikitopenglview class]]) { - SDL_uikitopenglview *glview = (SDL_uikitopenglview *)data.viewcontroller.view; - info->info.uikit.framebuffer = glview.drawableFramebuffer; - info->info.uikit.colorbuffer = glview.drawableRenderbuffer; - info->info.uikit.resolveFramebuffer = glview.msaaResolveFramebuffer; - } -#endif - return 0; - } -} - #if !TARGET_OS_TV NSUInteger UIKit_GetSupportedOrientations(SDL_Window *window) diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 97a0a254e8ed1..3b59a3662a7d5 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -28,8 +28,6 @@ #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_keyboard_c.h" -#include - /* VITA declarations */ #include #include "SDL_vitavideo.h" diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index 06c69dd348514..69eef0a349966 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -26,8 +26,6 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_events_c.h" -#include - #ifdef SDL_INPUT_LINUXEV #include "../../core/linux/SDL_evdev.h" #endif @@ -81,7 +79,6 @@ static SDL_VideoDevice *VIVANTE_Create() device->ShowWindow = VIVANTE_ShowWindow; device->HideWindow = VIVANTE_HideWindow; device->DestroyWindow = VIVANTE_DestroyWindow; - device->GetWindowWMInfo = VIVANTE_GetWindowWMInfo; #ifdef SDL_VIDEO_OPENGL_EGL device->GL_LoadLibrary = VIVANTE_GLES_LoadLibrary; @@ -258,6 +255,9 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Setup driver data for this window */ window->driverdata = data; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.vivante.display", displaydata->native_display); + #ifdef SDL_VIDEO_DRIVER_VIVANTE_VDK data->native_window = vdkCreateWindow(displaydata->native_display, window->x, window->y, window->w, window->h); #else @@ -266,6 +266,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) if (!data->native_window) { return SDL_SetError("VIVANTE: Can't create native window"); } + SDL_SetProperty(props, "SDL.window.vivante.window", data->native_window); #ifdef SDL_VIDEO_OPENGL_EGL if (window->flags & SDL_WINDOW_OPENGL) { @@ -276,6 +277,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } else { data->egl_surface = EGL_NO_SURFACE; } + SDL_SetProperty(props, "SDL.window.vivante.surface", data->egl_surface); #endif /* Window has been successfully created */ @@ -347,20 +349,6 @@ void VIVANTE_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_SetKeyboardFocus(NULL); } -/*****************************************************************************/ -/* SDL Window Manager function */ -/*****************************************************************************/ -int VIVANTE_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info) -{ - SDL_WindowData *data = window->driverdata; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverData(SDL_GetPrimaryDisplay()); - - info->subsystem = SDL_SYSWM_VIVANTE; - info->info.vivante.display = displaydata->native_display; - info->info.vivante.window = data->native_window; - return 0; -} - /*****************************************************************************/ /* SDL event functions */ /*****************************************************************************/ diff --git a/src/video/vivante/SDL_vivantevideo.h b/src/video/vivante/SDL_vivantevideo.h index 290851fc8b43e..ca9a62ed6ca57 100644 --- a/src/video/vivante/SDL_vivantevideo.h +++ b/src/video/vivante/SDL_vivantevideo.h @@ -80,9 +80,6 @@ void VIVANTE_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); void VIVANTE_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); void VIVANTE_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -/* Window manager function */ -int VIVANTE_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); - /* Event functions */ void VIVANTE_PumpEvents(SDL_VideoDevice *_this); diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c index 9244bf0b256bf..a8fcb0ff65895 100644 --- a/src/video/vivante/SDL_vivantevulkan.c +++ b/src/video/vivante/SDL_vivantevulkan.c @@ -33,7 +33,6 @@ #include "SDL_vivantevideo.h" #include "SDL_vivantevulkan.h" -#include int VIVANTE_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) { diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index d4a30bdf05465..96d7f390fd393 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -174,7 +174,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) device->VideoInit = Wayland_VideoInit; device->VideoQuit = Wayland_VideoQuit; device->GetDisplayBounds = Wayland_GetDisplayBounds; - device->GetWindowWMInfo = Wayland_GetWindowWMInfo; device->SuspendScreenSaver = Wayland_SuspendScreenSaver; device->PumpEvents = Wayland_PumpEvents; diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 99a9cd13e40fc..75cef415f1dd4 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -36,8 +36,6 @@ #include "../SDL_vulkan_internal.h" #include "SDL_waylandvulkan.h" -#include - #ifdef __OpenBSD__ #define DEFAULT_VULKAN "libvulkan.so" #else diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index f0927f08cff18..f65c3cfe186fd 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1301,37 +1301,6 @@ static void SetKeyboardFocus(SDL_Window *window) SDL_SetKeyboardFocus(window); } -int Wayland_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - SDL_VideoData *viddata = _this->driverdata; - SDL_WindowData *data = window->driverdata; - - info->subsystem = SDL_SYSWM_WAYLAND; - info->info.wl.display = data->waylandData->display; - info->info.wl.surface = data->surface; - info->info.wl.egl_window = data->egl_window; - -#ifdef HAVE_LIBDECOR_H - if (data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (data->shell_surface.libdecor.frame != NULL) { - info->info.wl.xdg_surface = libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame); - info->info.wl.xdg_toplevel = libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame); - } - } else -#endif - if (viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) { - SDL_bool popup = (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP); - info->info.wl.xdg_surface = data->shell_surface.xdg.surface; - info->info.wl.xdg_toplevel = popup ? NULL : data->shell_surface.xdg.roleobj.toplevel; - if (popup) { - info->info.wl.xdg_popup = data->shell_surface.xdg.roleobj.popup.popup; - info->info.wl.xdg_positioner = data->shell_surface.xdg.roleobj.popup.positioner; - } - } - - return 0; -} - int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled) { return 0; /* just succeed, the real work is done elsewhere. */ @@ -1380,6 +1349,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *c = _this->driverdata; SDL_WindowData *data = window->driverdata; + SDL_PropertiesID props = SDL_GetWindowProperties(window); /* If this is a child window, the parent *must* be in the final shown state, * meaning that it has received a configure event, followed by a frame callback. @@ -1427,13 +1397,17 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } else { libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id); libdecor_frame_map(data->shell_surface.libdecor.frame); + + SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame)); + SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame)); } } else #endif - if ((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) && c->shell.xdg) { + if ((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) && c->shell.xdg) { data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface); xdg_surface_set_user_data(data->shell_surface.xdg.surface, data); xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data); + SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.xdg_surface", data->shell_surface.xdg.surface); if (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { SDL_Window *parent = window->parent; @@ -1485,10 +1459,14 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) SetKeyboardFocus(window); } } + + SDL_SetProperty(props, "SDL.window.wayland.xdg_popup", data->shell_surface.xdg.roleobj.popup.popup); + SDL_SetProperty(props, "SDL.window.wayland.xdg_positioner", data->shell_surface.xdg.roleobj.popup.positioner); } else { data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface); xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id); xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data); + SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", data->shell_surface.xdg.roleobj.toplevel); } } @@ -1624,12 +1602,17 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup) xdg_positioner_destroy(popupdata->shell_surface.xdg.roleobj.popup.positioner); popupdata->shell_surface.xdg.roleobj.popup.popup = NULL; popupdata->shell_surface.xdg.roleobj.popup.positioner = NULL; + + SDL_PropertiesID props = SDL_GetWindowProperties(popup); + SDL_SetProperty(props, "SDL.window.wayland.xdg_popup", NULL); + SDL_SetProperty(props, "SDL.window.wayland.xdg_positioner", NULL); } void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *data = _this->driverdata; SDL_WindowData *wind = window->driverdata; + SDL_PropertiesID props = SDL_GetWindowProperties(window); wind->surface_status = WAYLAND_SURFACE_STATUS_HIDDEN; @@ -1649,19 +1632,24 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) if (wind->shell_surface.libdecor.frame) { libdecor_frame_unref(wind->shell_surface.libdecor.frame); wind->shell_surface.libdecor.frame = NULL; + + SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", NULL); + SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", NULL); } } else #endif - if (data->shell.xdg) { + if (data->shell.xdg) { if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { Wayland_ReleasePopup(_this, window); } else if (wind->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel); wind->shell_surface.xdg.roleobj.toplevel = NULL; + SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", NULL); } if (wind->shell_surface.xdg.surface) { xdg_surface_destroy(wind->shell_surface.xdg.surface); wind->shell_surface.xdg.surface = NULL; + SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", NULL); } } @@ -2109,6 +2097,11 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.wayland.display", data->waylandData->display); + SDL_SetProperty(props, "SDL.window.wayland.surface", data->surface); + SDL_SetProperty(props, "SDL.window.wayland.egl_window", data->egl_window); + return 0; } diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index a7d9ba4e9e679..d2105706d7626 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -27,8 +27,6 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_touch_c.h" -#include - #include "SDL_waylandvideo.h" struct SDL_WaylandInput; @@ -151,7 +149,6 @@ extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y); extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); extern int Wayland_SuspendScreenSaver(SDL_VideoDevice *_this); -extern int Wayland_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info); extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern int Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 41d94182225f5..57abda4fb1bce 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -29,8 +29,6 @@ #include "../../events/SDL_touch_c.h" #include "../../events/scancodes_windows.h" -#include - /* Dropfile support */ #include @@ -715,19 +713,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_WindowData *data; LRESULT returnCode = -1; - /* Send a SDL_EVENT_SYSWM if the application wants them */ - if (SDL_EventEnabled(SDL_EVENT_SYSWM)) { - SDL_SysWMmsg wmmsg; - - wmmsg.version = SDL_SYSWM_CURRENT_VERSION; - wmmsg.subsystem = SDL_SYSWM_WINDOWS; - wmmsg.msg.win.hwnd = hwnd; - wmmsg.msg.win.msg = msg; - wmmsg.msg.win.wParam = wParam; - wmmsg.msg.win.lParam = lParam; - SDL_SendSysWMEvent(&wmmsg); - } - /* Get the window data for the window */ data = WIN_GetWindowDataFromHWND(hwnd); #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) @@ -1809,7 +1794,9 @@ int WIN_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) return 0; } if (g_WindowsMessageHook) { - g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam); + if (!g_WindowsMessageHook(g_WindowsMessageHookData, &msg)) { + return 1; + } } /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */ TranslateMessage(&msg); @@ -1845,7 +1832,9 @@ void WIN_PumpEvents(SDL_VideoDevice *_this) while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (g_WindowsMessageHook) { - g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam); + if (!g_WindowsMessageHook(g_WindowsMessageHookData, &msg)) { + continue; + } } #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index b0d7122b50668..0bd8fd5b663ef 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -201,7 +201,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) device->SetWindowKeyboardGrab = WIN_SetWindowKeyboardGrab; #endif device->DestroyWindow = WIN_DestroyWindow; - device->GetWindowWMInfo = WIN_GetWindowWMInfo; #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer; diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c index e2e2a39a60c60..f52892d0f0a2a 100644 --- a/src/video/windows/SDL_windowsvulkan.c +++ b/src/video/windows/SDL_windowsvulkan.c @@ -35,8 +35,6 @@ #include "SDL_windowsvulkan.h" -#include - int WIN_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) { VkExtensionProperties *extensions = NULL; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 159a7abd8ca96..95927b74dc785 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -38,8 +38,6 @@ /* Dropfile support */ #include -#include - /* Dark mode support */ #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE #define DWMWA_USE_IMMERSIVE_DARK_MODE 20 @@ -440,6 +438,11 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd data->initializing = SDL_FALSE; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.win32.hwnd", data->hwnd); + SDL_SetProperty(props, "SDL.window.win32.hdc", data->hdc); + SDL_SetProperty(props, "SDL.window.win32.instance", data->hinstance); + /* All done! */ return 0; } @@ -1250,18 +1253,6 @@ void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) CleanupWindowData(_this, window); } -int WIN_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - const SDL_WindowData *data = (const SDL_WindowData *)window->driverdata; - - info->subsystem = SDL_SYSWM_WINDOWS; - info->info.win.window = data->hwnd; - info->info.win.hdc = data->hdc; - info->info.win.hinstance = data->hinstance; - - return 0; -} - /* * Creates a HelperWindow used for DirectInput. */ diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 527fee78d17fd..5b2c0260c0ea0 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -100,7 +100,6 @@ extern void WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); extern void WIN_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int WIN_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); extern void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window); extern void WIN_UpdateClipCursor(SDL_Window *window); extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index b98f67526f132..51e10ab31712c 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -67,8 +67,6 @@ extern "C" { #include "SDL_winrtmouse_c.h" #include "SDL_winrtvideo_cpp.h" -#include - /* Initialization/Query functions */ static int WINRT_VideoInit(SDL_VideoDevice *_this); static int WINRT_InitModes(SDL_VideoDevice *_this); @@ -80,7 +78,6 @@ static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); static void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); static void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); static void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -static int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info); /* Misc functions */ static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this); @@ -133,7 +130,6 @@ static SDL_VideoDevice *WINRT_CreateDevice(void) device->DestroyWindow = WINRT_DestroyWindow; device->SetDisplayMode = WINRT_SetDisplayMode; device->PumpEvents = WINRT_PumpEvents; - device->GetWindowWMInfo = WINRT_GetWindowWMInfo; device->SuspendScreenSaver = WINRT_SuspendScreenSaver; #if NTDDI_VERSION >= NTDDI_WIN10 @@ -612,6 +608,7 @@ int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) data->appView = ApplicationView::GetForCurrentView(); #endif } + SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.winrt.window", reinterpret_cast(data->coreWindow.Get())); /* Make note of the requested window flags, before they start getting changed. */ const Uint32 requestedFlags = window->flags; @@ -779,15 +776,6 @@ void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - SDL_WindowData *data = window->driverdata; - - info->subsystem = SDL_SYSWM_WINRT; - info->info.winrt.window = reinterpret_cast(data->coreWindow.Get()); - return 0; -} - static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this) { /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 2c8ed6b5900e0..1731dc747b882 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -40,8 +40,6 @@ #include "../../core/linux/SDL_system_theme.h" #include "../../SDL_utils_c.h" -#include - #include /*#define DEBUG_XEVENTS*/ @@ -324,27 +322,25 @@ static char *X11_URIToLocal(char *uri) return file; } +/* An X11 event hook */ +static SDL_X11EventHook g_X11EventHook = NULL; +static void *g_X11EventHookData = NULL; + +void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) +{ + g_X11EventHook = callback; + g_X11EventHookData = userdata; +} + #ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev) { /* event is a union, so cookie == &event, but this is type safe. */ XGenericEventCookie *cookie = &xev->xcookie; if (X11_XGetEventData(videodata->display, cookie)) { - X11_HandleXinput2Event(videodata, cookie); - - /* Send a SDL_EVENT_SYSWM if the application wants them. - * Since event data is only available until XFreeEventData is called, - * the *only* way for an application to access it is to register an event filter/watcher - * and do all the processing on the SDL_EVENT_SYSWM inside the callback. */ - if (SDL_EventEnabled(SDL_EVENT_SYSWM)) { - SDL_SysWMmsg wmmsg; - - wmmsg.version = SDL_SYSWM_CURRENT_VERSION; - wmmsg.subsystem = SDL_SYSWM_X11; - wmmsg.msg.x11.event = *xev; - SDL_SendSysWMEvent(&wmmsg); + if (!g_X11EventHook || g_X11EventHook(g_X11EventHookData, xev)) { + X11_HandleXinput2Event(videodata, cookie); } - X11_XFreeEventData(videodata->display, cookie); } } @@ -870,22 +866,19 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } #endif + /* Calling the event hook for generic events happens in X11_HandleGenericEvent(), where the event data is available */ + if (g_X11EventHook) { + if (!g_X11EventHook(g_X11EventHookData, xevent)) { + return; + } + } + #ifdef SDL_VIDEO_DRIVER_X11_XRANDR if (videodata->xrandr_event_base && (xevent->type == (videodata->xrandr_event_base + RRNotify))) { X11_HandleXRandREvent(_this, xevent); } #endif - /* Send a SDL_EVENT_SYSWM if the application wants them */ - if (SDL_EventEnabled(SDL_EVENT_SYSWM)) { - SDL_SysWMmsg wmmsg; - - wmmsg.version = SDL_SYSWM_CURRENT_VERSION; - wmmsg.subsystem = SDL_SYSWM_X11; - wmmsg.msg.x11.event = *xevent; - SDL_SendSysWMEvent(&wmmsg); - } - #if 0 printf("type = %d display = %d window = %d\n", xevent->type, xevent->xany.display, xevent->xany.window); diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index ac1340c79322c..1e164e84cccd7 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -207,7 +207,6 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer; - device->GetWindowWMInfo = X11_GetWindowWMInfo; device->SetWindowHitTest = X11_SetWindowHitTest; device->AcceptDragAndDrop = X11_AcceptDragAndDrop; device->FlashWindow = X11_FlashWindow; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index a1c5bb82198ad..1820b54c2ca7f 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -39,8 +39,6 @@ #include "SDL_x11opengles.h" #endif -#include - #define _NET_WM_STATE_REMOVE 0l #define _NET_WM_STATE_ADD 1l @@ -300,6 +298,7 @@ Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwin static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, BOOL created) { SDL_VideoData *videodata = _this->driverdata; + SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); SDL_WindowData *data; int numwindows = videodata->numwindows; int windowlistlength = videodata->windowlistlength; @@ -382,6 +381,13 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, /* All done! */ window->driverdata = data; + + SDL_PropertiesID props = SDL_GetWindowProperties(window); + int screen = (displaydata ? displaydata->screen : 0); + SDL_SetProperty(props, "SDL.window.x11.display", data->videodata->display); + SDL_SetProperty(props, "SDL.window.x11.screen", (void *)(intptr_t)screen); + SDL_SetProperty(props, "SDL.window.x11.window", (void *)(uintptr_t)data->xwindow); + return 0; } @@ -1848,23 +1854,6 @@ void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) window->driverdata = NULL; } -int X11_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info) -{ - SDL_WindowData *data = window->driverdata; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - - if (data == NULL) { - /* This sometimes happens in SDL_IBus_UpdateTextRect() while creating the window */ - return SDL_SetError("Window not initialized"); - } - - info->subsystem = SDL_SYSWM_X11; - info->info.x11.display = data->videodata->display; - info->info.x11.screen = displaydata->screen; - info->info.x11.window = data->xwindow; - return 0; -} - int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled) { return 0; /* just succeed, the real work is done elsewhere. */ diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index b9d6ab0d0ee32..03b8b8cdee452 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -111,7 +111,6 @@ extern void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, extern void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int X11_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info); extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void X11_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept); extern int X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); diff --git a/test/testautomation.c b/test/testautomation.c index 7cdd6be9337a9..f2bb2e8ebcdf3 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -42,7 +42,6 @@ static SDLTest_TestSuiteReference *testSuites[] = { &sdltestTestSuite, &stdlibTestSuite, &surfaceTestSuite, - &syswmTestSuite, &timerTestSuite, &videoTestSuite, &subsystemsTestSuite, /* run last, not interfere with other test enviroment */ diff --git a/test/testautomation_suites.h b/test/testautomation_suites.h index 9a562620a2d0e..143ec15369a4a 100644 --- a/test/testautomation_suites.h +++ b/test/testautomation_suites.h @@ -30,7 +30,6 @@ extern SDLTest_TestSuiteReference sdltestTestSuite; extern SDLTest_TestSuiteReference stdlibTestSuite; extern SDLTest_TestSuiteReference subsystemsTestSuite; extern SDLTest_TestSuiteReference surfaceTestSuite; -extern SDLTest_TestSuiteReference syswmTestSuite; extern SDLTest_TestSuiteReference timerTestSuite; extern SDLTest_TestSuiteReference videoTestSuite; diff --git a/test/testautomation_syswm.c b/test/testautomation_syswm.c deleted file mode 100644 index e05f114915823..0000000000000 --- a/test/testautomation_syswm.c +++ /dev/null @@ -1,60 +0,0 @@ -/** - * SysWM test suite - */ - -/* Avoid inclusion of e.g. X11 headers when these are not installed */ -#include - -#include -#include -#include -#include "testautomation_suites.h" - -/* Test case functions */ - -/** - * Call to SDL_GetWindowWMInfo - */ -static int syswm_getWindowWMInfo(void *arg) -{ - int result; - SDL_Window *window; - SDL_SysWMinfo info; - - window = SDL_CreateWindow("", 0, 0, SDL_WINDOW_HIDDEN); - SDLTest_AssertPass("Call to SDL_CreateWindow()"); - SDLTest_AssertCheck(window != NULL, "Check that value returned from SDL_CreateWindow is not NULL"); - if (window == NULL) { - return TEST_ABORTED; - } - - /* Make call */ - result = SDL_GetWindowWMInfo(window, &info, SDL_SYSWM_CURRENT_VERSION); - SDLTest_AssertPass("Call to SDL_GetWindowWMInfo()"); - SDLTest_Log((result == 0) ? "Got window information" : "Couldn't get window information"); - - SDL_DestroyWindow(window); - SDLTest_AssertPass("Call to SDL_DestroyWindow()"); - - return TEST_COMPLETED; -} - -/* ================= Test References ================== */ - -/* SysWM test cases */ -static const SDLTest_TestCaseReference syswmTest1 = { - (SDLTest_TestCaseFp)syswm_getWindowWMInfo, "syswm_getWindowWMInfo", "Call to SDL_GetWindowWMInfo", TEST_ENABLED -}; - -/* Sequence of SysWM test cases */ -static const SDLTest_TestCaseReference *syswmTests[] = { - &syswmTest1, NULL -}; - -/* SysWM test suite (global) */ -SDLTest_TestSuiteReference syswmTestSuite = { - "SysWM", - NULL, - syswmTests, - NULL -}; From 4e8d1ec98373444e872d47668cdbfa072a5fe501 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 7 Nov 2023 15:32:40 -0800 Subject: [PATCH 291/725] Fixed crash trying to create a metal view with the dummy driver --- src/video/SDL_video.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index bb983b902a01d..aa1fee7298c6c 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -5138,6 +5138,11 @@ SDL_MetalView SDL_Metal_CreateView(SDL_Window *window) { CHECK_WINDOW_MAGIC(window, NULL); + if (!_this->Metal_CreateView) { + SDL_Unsupported(); + return NULL; + } + if (!(window->flags & SDL_WINDOW_METAL)) { /* No problem, we can convert to Metal */ if (window->flags & SDL_WINDOW_OPENGL) { From 6c91b28e71e46d509431178fb52a7715385d54af Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 11:27:00 -0800 Subject: [PATCH 292/725] Added the "SDL.renderer.d3d12.command_queue" property Fixes https://github.com/libsdl-org/SDL/issues/8491 --- include/SDL3/SDL_render.h | 1 + src/render/direct3d12/SDL_render_d3d12.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 9fde47f2c6b3b..5b745b54eac1a 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -313,6 +313,7 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer + * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 2fd1f00d10b5d..8e89185a0103f 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -323,6 +323,10 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer) D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata; SDL_Texture *texture = NULL; + SDL_PropertiesID props = SDL_GetRendererProperties(renderer); + SDL_SetProperty(props, "SDL.renderer.d3d12.device", NULL); + SDL_SetProperty(props, "SDL.renderer.d3d12.command_queue", NULL); + /* Release all textures */ for (texture = renderer->textures; texture; texture = texture->next) { D3D12_DestroyTexture(renderer, texture); @@ -1068,7 +1072,9 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) } data->srvPoolHead = &data->srvPoolNodes[0]; - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d12.device", data->d3dDevice); + SDL_PropertiesID props = SDL_GetRendererProperties(renderer); + SDL_SetProperty(props, "SDL.renderer.d3d12.device", data->d3dDevice); + SDL_SetProperty(props, "SDL.renderer.d3d12.command_queue", data->commandQueue); done: SAFE_RELEASE(d3dDevice); From 151cdfa99fd154885595d53a7a6c1b89514a8f6b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 11:45:55 -0800 Subject: [PATCH 293/725] Added the "SDL.window.wayland.registry" property Fixes https://github.com/libsdl-org/SDL/issues/8393 --- include/SDL3/SDL_video.h | 1 + src/video/wayland/SDL_waylandwindow.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 567e9437fb4b8..8c89fae443a25 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -967,6 +967,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * "SDL.window.win32.instance" - the HINSTANCE associated with the window * * On Wayland: + * "SDL.window.wayland.registry" - the wl_registry associated with the window * "SDL.window.wayland.display" - the wl_display associated with the window * "SDL.window.wayland.surface" - the wl_surface associated with the window * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index f65c3cfe186fd..7e00c63a3886e 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2098,6 +2098,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_SetProperty(props, "SDL.window.wayland.registry", c->registry); SDL_SetProperty(props, "SDL.window.wayland.display", data->waylandData->display); SDL_SetProperty(props, "SDL.window.wayland.surface", data->surface); SDL_SetProperty(props, "SDL.window.wayland.egl_window", data->egl_window); From 979214363fca0a7a07887ae2ae705c16085c8f6c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 11:55:04 -0800 Subject: [PATCH 294/725] Added SDL_GetGlobalProperties() We'll undoubtedly want to have global properties available --- include/SDL3/SDL_properties.h | 13 +++++++++++++ src/SDL_properties.c | 21 +++++++++++++++++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + 5 files changed, 37 insertions(+) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 9a6ebf3152c15..588bdfc4ca497 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -39,6 +39,19 @@ extern "C" { */ typedef Uint32 SDL_PropertiesID; +/** + * Get the global SDL properties + * + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); + /** * Create a set of properties * diff --git a/src/SDL_properties.c b/src/SDL_properties.c index d0b9c60f17d7e..49ae6866cdcc1 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -39,6 +39,7 @@ typedef struct static SDL_HashTable *SDL_properties; static SDL_RWLock *SDL_properties_lock; static SDL_PropertiesID SDL_last_properties_id; +static SDL_PropertiesID SDL_global_properties; static void SDL_FreeProperty(const void *key, const void *value, void *data) @@ -81,11 +82,23 @@ int SDL_InitProperties(void) return -1; } } + + /* Create the global properties here to avoid race conditions later */ + if (!SDL_global_properties) { + SDL_global_properties = SDL_CreateProperties(); + if (!SDL_global_properties) { + return -1; + } + } return 0; } void SDL_QuitProperties(void) { + if (SDL_global_properties) { + SDL_DestroyProperties(SDL_global_properties); + SDL_global_properties = 0; + } if (SDL_properties) { SDL_DestroyHashTable(SDL_properties); SDL_properties = NULL; @@ -96,6 +109,14 @@ void SDL_QuitProperties(void) } } +SDL_PropertiesID SDL_GetGlobalProperties(void) +{ + if (!SDL_properties && SDL_InitProperties() < 0) { + return 0; + } + return SDL_global_properties; +} + SDL_PropertiesID SDL_CreateProperties(void) { SDL_PropertiesID props = 0; diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 720591affbeb2..e6fd996c64299 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -922,6 +922,7 @@ SDL3_0.0.0 { SDL_GetDisplayProperties; SDL_SetPropertyWithCleanup; SDL_SetX11EventHook; + SDL_GetGlobalProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index a6c5440ca33d1..97d05e88ba0b8 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -947,3 +947,4 @@ #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL #define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL #define SDL_SetX11EventHook SDL_SetX11EventHook_REAL +#define SDL_GetGlobalProperties SDL_GetGlobalProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 3348c67a8f44d..64022522244f3 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -980,3 +980,4 @@ SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGlobalProperties,(void),(),return) From 407a3cb4e06e4524bbfa33db71cd1820e936982b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 12:38:04 -0800 Subject: [PATCH 295/725] Fixed infinite recursion initializing properties --- src/SDL.c | 1 + src/SDL_properties.c | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/SDL.c b/src/SDL.c index 46d668820d723..2959db8749154 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -185,6 +185,7 @@ int SDL_InitSubSystem(Uint32 flags) SDL_InitLog(); SDL_InitProperties(); + SDL_GetGlobalProperties(); /* Clear the error message */ SDL_ClearError(); diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 49ae6866cdcc1..31da31d320433 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -82,14 +82,6 @@ int SDL_InitProperties(void) return -1; } } - - /* Create the global properties here to avoid race conditions later */ - if (!SDL_global_properties) { - SDL_global_properties = SDL_CreateProperties(); - if (!SDL_global_properties) { - return -1; - } - } return 0; } @@ -111,8 +103,8 @@ void SDL_QuitProperties(void) SDL_PropertiesID SDL_GetGlobalProperties(void) { - if (!SDL_properties && SDL_InitProperties() < 0) { - return 0; + if (!SDL_global_properties) { + SDL_global_properties = SDL_CreateProperties(); } return SDL_global_properties; } From 1934417b4d6db0117a8438e099ea63d8f7cf3d74 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 12:38:54 -0800 Subject: [PATCH 296/725] Show the existing mapping when a controller is connected --- test/testcontroller.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testcontroller.c b/test/testcontroller.c index dd4b9819d95f0..4fd5627ab0962 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -981,6 +981,14 @@ static void HandleGamepadAdded(SDL_JoystickID id, SDL_bool verbose) SDL_SetGamepadSensorEnabled(gamepad, sensor, SDL_TRUE); } } + + if (verbose) { + char *mapping = SDL_GetGamepadMapping(gamepad); + if (mapping) { + SDL_Log("Mapping: %s\n", mapping); + SDL_free(mapping); + } + } } else { SDL_Log("Couldn't open gamepad: %s", SDL_GetError()); } From 02f356439d1fedf0b4e5f96cd23c2d570e2f7be2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 13:11:21 -0800 Subject: [PATCH 297/725] Allow the application to draw while Windows is in a modal move/resize loop If you're using the application main callbacks, your SDL_AppIterate() function will be called while Windows is moving and resizing your window. If not, then SDL will send an SDL_EVENT_WINDOW_EXPOSED event for your window and you can use an event watcher to redraw your window directly from the callback. Fixes https://github.com/libsdl-org/SDL/issues/1059 Closes https://github.com/libsdl-org/SDL/pull/4836 --- src/main/SDL_main_callbacks.c | 24 ++++++++++++++----- src/main/SDL_main_callbacks.h | 5 ++-- src/main/generic/SDL_sysmain_callbacks.c | 2 +- src/video/windows/SDL_windowsevents.c | 30 ++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 0c091323f03ee..0e7fb8d2895f3 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -80,6 +80,14 @@ static int SDLCALL SDL_MainCallbackEventWatcher(void *userdata, SDL_Event *event return 0; } +SDL_bool SDL_HasMainCallbacks() +{ + if (SDL_main_iteration_callback) { + return SDL_TRUE; + } + return SDL_FALSE; +} + int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit) { SDL_main_iteration_callback = appiter; @@ -104,16 +112,20 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ return SDL_AtomicGet(&apprc); } -int SDL_IterateMainCallbacks(void) +int SDL_IterateMainCallbacks(SDL_bool pump_events) { - SDL_PumpEvents(); + if (pump_events) { + SDL_PumpEvents(); + } SDL_DispatchMainCallbackEvents(); - int rc = SDL_main_iteration_callback(); - if (!SDL_AtomicCAS(&apprc, 0, rc)) { - rc = SDL_AtomicGet(&apprc); // something else already set a quit result, keep that. + int rc = SDL_AtomicGet(&apprc); + if (rc == 0) { + rc = SDL_main_iteration_callback(); + if (!SDL_AtomicCAS(&apprc, 0, rc)) { + rc = SDL_AtomicGet(&apprc); // something else already set a quit result, keep that. + } } - return rc; } diff --git a/src/main/SDL_main_callbacks.h b/src/main/SDL_main_callbacks.h index 9df171a99c13b..229fec7766a02 100644 --- a/src/main/SDL_main_callbacks.h +++ b/src/main/SDL_main_callbacks.h @@ -22,8 +22,9 @@ #ifndef SDL_main_callbacks_h_ #define SDL_main_callbacks_h_ -int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit); -int SDL_IterateMainCallbacks(void); +SDL_bool SDL_HasMainCallbacks(); +int SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit); +int SDL_IterateMainCallbacks(SDL_bool pump_events); void SDL_QuitMainCallbacks(void); #endif // SDL_main_callbacks_h_ diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index 1fcb7d767f8f3..fa18e80002c5a 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -45,7 +45,7 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, Uint64 next_iteration = callback_rate_increment ? (SDL_GetTicksNS() + callback_rate_increment) : 0; - while ((rc = SDL_IterateMainCallbacks()) == 0) { + while ((rc = SDL_IterateMainCallbacks(SDL_TRUE)) == 0) { // !!! FIXME: this can be made more complicated if we decide to // !!! FIXME: optionally hand off callback responsibility to the // !!! FIXME: video subsystem (for example, if Wayland has a diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 57abda4fb1bce..cc6b1f63b0ee4 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -28,6 +28,7 @@ #include "../../events/SDL_events_c.h" #include "../../events/SDL_touch_c.h" #include "../../events/scancodes_windows.h" +#include "../../main/SDL_main_callbacks.h" /* Dropfile support */ #include @@ -106,6 +107,10 @@ #define IS_SURROGATE_PAIR(h, l) (IS_HIGH_SURROGATE(h) && IS_LOW_SURROGATE(l)) #endif +#ifndef USER_TIMER_MINIMUM +#define USER_TIMER_MINIMUM 0x0000000A +#endif + /* Used to compare Windows message timestamps */ #define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) @@ -1283,6 +1288,31 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } } break; + case WM_ENTERSIZEMOVE: + case WM_ENTERMENULOOP: + { + SetTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks, USER_TIMER_MINIMUM, NULL); + } break; + + case WM_TIMER: + { + if (wParam == (UINT_PTR)SDL_IterateMainCallbacks) { + if (SDL_HasMainCallbacks()) { + SDL_IterateMainCallbacks(SDL_FALSE); + } else { + // Send an expose event so the application can redraw + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); + } + return 0; + } + } break; + + case WM_EXITSIZEMOVE: + case WM_EXITMENULOOP: + { + KillTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks); + } break; + case WM_SIZE: { switch (wParam) { From b5347c33647e55183393c47d3b524a4b0a267060 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 14:14:41 -0800 Subject: [PATCH 298/725] Fixed emscripten and iOS builds --- src/main/emscripten/SDL_sysmain_callbacks.c | 2 +- src/main/ios/SDL_sysmain_callbacks.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/emscripten/SDL_sysmain_callbacks.c b/src/main/emscripten/SDL_sysmain_callbacks.c index fc6f53e6c7d3f..151ccf49a2cad 100644 --- a/src/main/emscripten/SDL_sysmain_callbacks.c +++ b/src/main/emscripten/SDL_sysmain_callbacks.c @@ -26,7 +26,7 @@ static void EmscriptenInternalMainloop(void) { - const int rc = SDL_IterateMainCallbacks(); + const int rc = SDL_IterateMainCallbacks(SDL_TRUE); if (rc != 0) { SDL_QuitMainCallbacks(); emscripten_cancel_main_loop(); // kill" the mainloop, so it stops calling back into it. diff --git a/src/main/ios/SDL_sysmain_callbacks.m b/src/main/ios/SDL_sysmain_callbacks.m index 63722630f04e0..8cffd9c11795b 100644 --- a/src/main/ios/SDL_sysmain_callbacks.m +++ b/src/main/ios/SDL_sysmain_callbacks.m @@ -47,7 +47,7 @@ - (instancetype)init:(SDL_AppIterate_func)_appiter quitfunc:(SDL_AppQuit_func)_a - (void)appIteration:(CADisplayLink *)sender { - const int rc = SDL_IterateMainCallbacks(); + const int rc = SDL_IterateMainCallbacks(SDL_TRUE); if (rc != 0) { [self.displayLink invalidate]; self.displayLink = nil; From bea34c53804ada8d90c94aba27262635513452d3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 14:26:07 -0800 Subject: [PATCH 299/725] Fixed a memory leak at window creation. Windows updates the desktop display mode once at video init (in WIN_InitModes()) and once when creating a window (in WIN_RefreshDisplays()) Fixes https://github.com/libsdl-org/SDL/issues/7982 Fixes https://github.com/libsdl-org/SDL/issues/8189 --- src/video/SDL_video.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index aa1fee7298c6c..df0ad23511371 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1164,6 +1164,9 @@ const SDL_DisplayMode *SDL_GetClosestFullscreenDisplayMode(SDL_DisplayID display void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode) { + if (display->desktop_mode.driverdata) { + SDL_free(display->desktop_mode.driverdata); + } SDL_memcpy(&display->desktop_mode, mode, sizeof(*mode)); display->desktop_mode.displayID = display->id; SDL_FinalizeDisplayMode(&display->desktop_mode); From 2e3f574f8f9488bac92d11ba6de1e9d51c80666f Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 00:20:34 +0100 Subject: [PATCH 300/725] cmake: don't add the C runtime library to the .obj file (when using MSVC) Using /Zl, the obj files will no longer add a link requirement to the C runtime libraries. Meanwhile, also add /NODEFAULTLIB for non-UWP MSVC toolchains. Because /Zl is a compile option, it can also be used when building a static SDL3 library, and SDL3_test. --- CMakeLists.txt | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1beb5f84af66..4e93a84ace54f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1932,8 +1932,8 @@ elseif(WINDOWS) vccorlib$<$:d>.lib msvcrt$<$:d>.lib LINK_OPTIONS - -nodefaultlib:vccorlib$<$:d> - -nodefaultlib:msvcrt$<$:d> + /nodefaultlib:vccorlib$<$:d> + /nodefaultlib:msvcrt$<$:d> ) endif() @@ -2988,6 +2988,24 @@ if(PS2) sdl_compile_options(PRIVATE "-Wno-error=declaration-after-statement") endif() +if(NOT SDL_LIBC) + if(MSVC) + set(saved_CMAKE_TRY_COMPILE_TARGET_TYPE "${CMAKE_TRY_COMPILE_TARGET_TYPE}") + cmake_push_check_state(RESET) + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + check_c_compiler_flag("/Zl" COMPILER_SUPPORTS_Zl) + cmake_pop_check_state() + set(CMAKE_TRY_COMPILE_TARGET_TYPE "${saved_CMAKE_TRY_COMPILE_TARGET_TYPE}") + if(COMPILER_SUPPORTS_Zl) + # /Zl omits the default C runtime library name from the .obj file. + sdl_compile_options(PRIVATE "$<$,$>:/Zl>") + if(TARGET SDL3_test) + target_compile_options(SDL3_test PRIVATE "/Zl") + endif() + endif() + endif() +endif() + if(APPLE) get_property(sources TARGET SDL3-collector PROPERTY INTERFACE_SOURCES) foreach(SOURCE_FILE IN LISTS sources) @@ -3058,9 +3076,15 @@ if(SDL_SHARED) ) endif() if(NOT SDL_LIBC) - if(MSVC AND SDL_CPU_X86) - # FIXME: should be added for all architectures (missing symbols for ARM) - target_link_libraries(SDL3-shared PRIVATE "-nodefaultlib:MSVCRT") + if(MSVC AND (NOT MSVC_CLANG AND NOT WINDOWS_STORE)) + # Don't try to link with the default set of libraries. + # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB. + target_link_options(SDL3-shared PRIVATE "/NODEFAULTLIB") + if(SDL_CPU_ARM32) + # linking to msvcrt.lib avoid unresolved external symbols + # (__rt_sdiv, __rt_udiv, __rt_sdiv64, _rt_udiv64, __dtou64, __u64tod, __i64tos) + target_link_libraries(SDL3-shared PRIVATE msvcrt.lib) + endif() endif() if(HAS_Q_NO_USE_LIBIRC) target_compile_options(SDL3-shared PRIVATE /Q_no-use-libirc) @@ -3095,14 +3119,6 @@ if(SDL_SHARED) ) endif() endif() - # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB. - if(MSVC AND NOT SDL_LIBC AND NOT MSVC_CLANG AND NOT SDL_CPU_ARM32) - # Don't try to link with the default set of libraries. - if(NOT WINDOWS_STORE) - # FIXME: is this needed? "-nodefaultlib:MSVCRT" ia already added when SDL_LIBC is false - target_link_options(SDL3-shared PRIVATE "/NODEFAULTLIB") - endif() - endif() target_link_libraries(SDL3-shared PRIVATE ${SDL_CMAKE_DEPENDS}) target_include_directories(SDL3-shared PRIVATE From a6541166bcf9da779b6cdb587d47976d5c1d4ea9 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 00:24:10 +0100 Subject: [PATCH 301/725] cmake: also install pdb files of static libraries --- CMakeLists.txt | 8 +++++++- cmake/macros.cmake | 14 ++++++++++++++ test/CMakeLists.txt | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e93a84ace54f..ca03351edb19c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3310,7 +3310,7 @@ if(NOT SDL_DISABLE_INSTALL) RESOURCE DESTINATION "${SDL_SDL_INSTALL_RESOURCEDIR}" ) if(MSVC) - install(FILES $ DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL) + SDL_install_pdb(SDL3-shared "${CMAKE_INSTALL_BINDIR}") endif() endif() @@ -3320,6 +3320,9 @@ if(NOT SDL_DISABLE_INSTALL) FRAMEWORK DESTINATION "." RESOURCE DESTINATION "${SDL_SDLstatic_INSTALL_RESOURCEDIR}" ) + if(MSVC) + SDL_install_pdb(SDL3-static "${CMAKE_INSTALL_LIBDIR}") + endif() endif() if(SDL_TEST_LIBRARY) @@ -3328,6 +3331,9 @@ if(NOT SDL_DISABLE_INSTALL) FRAMEWORK DESTINATION "." RESOURCE DESTINATION "${SDL_SDLtest_INSTALL_RESOURCEDIR}" ) + if(MSVC) + SDL_install_pdb(SDL3_test "${CMAKE_INSTALL_LIBDIR}") + endif() endif() ##### Install CMake Targets ##### diff --git a/cmake/macros.cmake b/cmake/macros.cmake index f91946425d2fe..edc30fcfbb794 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -201,3 +201,17 @@ function(SDL_PrintSummary) message(STATUS "") endif() endfunction() + +function(SDL_install_pdb TARGET DIRECTORY) + get_property(type TARGET ${TARGET} PROPERTY TYPE) + if(type MATCHES "^(SHARED_LIBRARY|EXECUTABLE)$") + install(FILES $ DESTINATION "${DIRECTORY}" OPTIONAL) + elseif(type STREQUAL "STATIC_LIBRARY") + # FIXME: Use $.pdb\")") + else() + install(CODE "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DIRECTORY}\" TYPE FILE OPTIONAL FILES \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir/$.pdb\")") + endif() + endif() +endfunction() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ee4251a478f21..8d7ff59047305 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -571,7 +571,7 @@ if(SDL_INSTALL_TESTS) endif() if(MSVC) foreach(test IN LISTS SDL_TEST_EXECUTABLES) - install(FILES $ DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3" OPTIONAL) + SDL_install_pdb(${test} "${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3") endforeach() endif() install( From 391a3d23d02fea5aeda15a9c6e39bb2882a1fb0a Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 03:28:20 +0100 Subject: [PATCH 302/725] cmake: the compile-time pdb does not have a suffix, if set --- cmake/macros.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/macros.cmake b/cmake/macros.cmake index edc30fcfbb794..c04c760a7bec5 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -209,9 +209,9 @@ function(SDL_install_pdb TARGET DIRECTORY) elseif(type STREQUAL "STATIC_LIBRARY") # FIXME: Use $.pdb\")") + install(CODE "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DIRECTORY}\" TYPE FILE OPTIONAL FILES \"${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/${TARGET}.pdb\")") else() - install(CODE "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DIRECTORY}\" TYPE FILE OPTIONAL FILES \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir/$.pdb\")") + install(CODE "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DIRECTORY}\" TYPE FILE OPTIONAL FILES \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET}.dir/${TARGET}.pdb\")") endif() endif() endfunction() From f4b61fff308443727c52ae098923b9e934660609 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 10:33:40 -0800 Subject: [PATCH 303/725] Implemented VT switching for KMSDRM on Linux Fixes https://github.com/libsdl-org/SDL/issues/3844 --- src/core/freebsd/SDL_evdev_kbd_freebsd.c | 16 +- src/core/linux/SDL_evdev.c | 10 ++ src/core/linux/SDL_evdev.h | 2 + src/core/linux/SDL_evdev_kbd.c | 211 ++++++++++++++++++++--- src/core/linux/SDL_evdev_kbd.h | 2 + src/video/kmsdrm/SDL_kmsdrmopengles.c | 9 +- src/video/kmsdrm/SDL_kmsdrmsym.h | 1 + src/video/kmsdrm/SDL_kmsdrmvideo.c | 32 ++++ 8 files changed, 252 insertions(+), 31 deletions(-) diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c index 19a7a7114811e..e9129feeb8c4a 100644 --- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -320,6 +320,18 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) SDL_free(kbd); } +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +{ +} + +void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data) +{ +} + +void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) +{ +} + /* * Helper Functions. */ @@ -467,10 +479,6 @@ static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ } } -void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) -{ -} - void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down) { keymap_t key_map; diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index 4532857938319..9ca3bdfaf7b7a 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -288,6 +288,14 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl } #endif /* SDL_USE_LIBUDEV */ +void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data, + void (*acquire_callback)(void*), void *acquire_callback_data) +{ + SDL_EVDEV_kbd_set_vt_switch_callbacks(_this->kbd, + release_callback, release_callback_data, + acquire_callback, acquire_callback_data); +} + int SDL_EVDEV_GetDeviceCount(int device_class) { SDL_evdevlist_item *item; @@ -319,6 +327,8 @@ void SDL_EVDEV_Poll(void) SDL_UDEV_Poll(); #endif + SDL_EVDEV_kbd_update(_this->kbd); + mouse = SDL_GetMouse(); for (item = _this->first; item != NULL; item = item->next) { diff --git a/src/core/linux/SDL_evdev.h b/src/core/linux/SDL_evdev.h index b0c6c7ef0e491..c9ac38edd2a33 100644 --- a/src/core/linux/SDL_evdev.h +++ b/src/core/linux/SDL_evdev.h @@ -30,6 +30,8 @@ struct input_event; extern int SDL_EVDEV_Init(void); extern void SDL_EVDEV_Quit(void); +extern void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data, + void (*acquire_callback)(void*), void *acquire_callback_data); extern int SDL_EVDEV_GetDeviceCount(int device_class); extern void SDL_EVDEV_Poll(void); extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event); diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index fb3036cd4447a..2085b07e790fa 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -99,6 +99,10 @@ struct SDL_EVDEV_keyboard_state char shift_state; char text[128]; unsigned int text_len; + void (*vt_release_callback)(void *); + void *vt_release_callback_data; + void (*vt_acquire_callback)(void *); + void *vt_acquire_callback_data; }; #ifdef DUMP_ACCENTS @@ -296,6 +300,128 @@ static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd) } } +enum { + VT_SIGNAL_NONE, + VT_SIGNAL_RELEASE, + VT_SIGNAL_ACQUIRE, +}; +static int vt_release_signal; +static int vt_acquire_signal; +static SDL_AtomicInt vt_signal_pending; + +typedef void (*signal_handler)(int signum); + +static void kbd_vt_release_signal_action(int signum) +{ +printf("kbd_vt_release_signal_action\n"); + SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_RELEASE); +} + +static void kbd_vt_acquire_signal_action(int signum) +{ +printf("kbd_vt_acquire_signal_action\n"); + SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_ACQUIRE); +} + +static SDL_bool setup_vt_signal(int signum, signal_handler handler) +{ + struct sigaction *old_action_p; + struct sigaction new_action; + old_action_p = &(old_sigaction[signum]); + SDL_zero(new_action); + new_action.sa_handler = handler; + new_action.sa_flags = SA_RESTART; + if (sigaction(signum, &new_action, old_action_p) < 0) { + return SDL_FALSE; + } + if (old_action_p->sa_handler != SIG_DFL) { + /* This signal is already in use */ + sigaction(signum, old_action_p, NULL); + return SDL_FALSE; + } + return SDL_TRUE; +} + +static int find_free_signal(signal_handler handler) +{ +#ifdef SIGRTMIN + int i; + + for (i = SIGRTMIN + 2; i <= SIGRTMAX; ++i) { + if (setup_vt_signal(i, handler)) { + return i; + } + } +#endif + if (setup_vt_signal(SIGUSR1, handler)) { + return SIGUSR1; + } + if (setup_vt_signal(SIGUSR2, handler)) { + return SIGUSR2; + } + return 0; +} + +static void kbd_vt_quit(int console_fd) +{ + struct vt_mode mode; + + if (vt_release_signal) { + sigaction(vt_release_signal, &old_sigaction[vt_release_signal], NULL); + vt_release_signal = 0; + } + if (vt_acquire_signal) { + sigaction(vt_acquire_signal, &old_sigaction[vt_acquire_signal], NULL); + vt_acquire_signal = 0; + } + + SDL_zero(mode); + mode.mode = VT_AUTO; + ioctl(console_fd, VT_SETMODE, &mode); +} + +static int kbd_vt_init(int console_fd) +{ + struct vt_mode mode; + + vt_release_signal = find_free_signal(kbd_vt_release_signal_action); + vt_acquire_signal = find_free_signal(kbd_vt_acquire_signal_action); + if (!vt_release_signal || !vt_acquire_signal ) { + kbd_vt_quit(console_fd); + return -1; + } + + SDL_zero(mode); + mode.mode = VT_PROCESS; + mode.relsig = vt_release_signal; + mode.acqsig = vt_acquire_signal; + mode.frsig = SIGIO; + if (ioctl(console_fd, VT_SETMODE, &mode) < 0) { + kbd_vt_quit(console_fd); + return -1; + } + return 0; +} + +static void kbd_vt_update(SDL_EVDEV_keyboard_state *state) +{ + int signal_pending = SDL_AtomicGet(&vt_signal_pending); + if (signal_pending != VT_SIGNAL_NONE) { + if (signal_pending == VT_SIGNAL_RELEASE) { + if (state->vt_release_callback) { + state->vt_release_callback(state->vt_release_callback_data); + } + ioctl(state->console_fd, VT_RELDISP, 1); + } else { + if (state->vt_acquire_callback) { + state->vt_acquire_callback(state->vt_acquire_callback_data); + } + ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ); + } + SDL_AtomicCAS(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); + } +} + SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) { SDL_EVDEV_keyboard_state *kbd; @@ -333,33 +459,9 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE); } - return kbd; -} + kbd_vt_init(kbd->console_fd); -void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) -{ - if (state == NULL) { - return; - } - - SDL_EVDEV_kbd_set_muted(state, SDL_FALSE); - - if (state->console_fd >= 0) { - close(state->console_fd); - state->console_fd = -1; - } - - if (state->key_maps && state->key_maps != default_key_maps) { - int i; - for (i = 0; i < MAX_NR_KEYMAPS; ++i) { - if (state->key_maps[i]) { - SDL_free(state->key_maps[i]); - } - } - SDL_free(state->key_maps); - } - - SDL_free(state); + return kbd; } void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) @@ -396,6 +498,55 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) state->muted = muted; } +void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data) +{ + if (state == NULL) { + return; + } + + state->vt_release_callback = release_callback; + state->vt_release_callback_data = release_callback_data; + state->vt_acquire_callback = acquire_callback; + state->vt_acquire_callback_data = acquire_callback_data; +} + +void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) +{ + if (!state) { + return; + } + + kbd_vt_update(state); +} + +void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) +{ + if (state == NULL) { + return; + } + + SDL_EVDEV_kbd_set_muted(state, SDL_FALSE); + + kbd_vt_quit(state->console_fd); + + if (state->console_fd >= 0) { + close(state->console_fd); + state->console_fd = -1; + } + + if (state->key_maps && state->key_maps != default_key_maps) { + int i; + for (i = 0; i < MAX_NR_KEYMAPS; ++i) { + if (state->key_maps[i]) { + SDL_free(state->key_maps[i]); + } + } + SDL_free(state->key_maps); + } + + SDL_free(state); +} + /* * Helper Functions. */ @@ -830,6 +981,14 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) { } +void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data) +{ +} + +void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) +{ +} + void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down) { } diff --git a/src/core/linux/SDL_evdev_kbd.h b/src/core/linux/SDL_evdev_kbd.h index e00ca0b1445a6..73cff0bc3a75e 100644 --- a/src/core/linux/SDL_evdev_kbd.h +++ b/src/core/linux/SDL_evdev_kbd.h @@ -27,6 +27,8 @@ typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state; extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void); extern void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted); +extern void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data); +extern void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state); extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down); extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state); diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c index 2de35e0e86ba6..1df556e23a98d 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -96,6 +96,13 @@ int KMSDRM_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) even if you do async flips. */ uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT; + /* Skip the swap if we've switched away to another VT */ + if (windata->egl_surface == EGL_NO_SURFACE) { + /* Wait a bit, throttling to ~100 FPS */ + SDL_Delay(10); + return 0; + } + /* Recreate the GBM / EGL surfaces if the display mode has changed */ if (windata->egl_surface_dirty) { KMSDRM_CreateSurfaces(_this, window); @@ -116,7 +123,7 @@ int KMSDRM_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) windata->bo = windata->next_bo; - /* Mark a buffer to becume the next front buffer. + /* Mark a buffer to become the next front buffer. This won't happen until pagelip completes. */ if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface))) { diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index e378fdfb07d64..d8f31ca9433c1 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -42,6 +42,7 @@ SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr)) SDL_KMSDRM_SYM(int,drmGetCap,(int fd, uint64_t capability, uint64_t *value)) SDL_KMSDRM_SYM(int,drmSetMaster,(int fd)) +SDL_KMSDRM_SYM(int,drmDropMaster,(int fd)) SDL_KMSDRM_SYM(int,drmAuthMagic,(int fd, drm_magic_t magic)) SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd)) SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth, diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 15b943b724c96..643a469d86d7c 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1223,6 +1223,36 @@ int KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window) return ret; } +static void KMSDRM_ReleaseVT(void *userdata) +{ + SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; + SDL_VideoData *viddata = _this->driverdata; + int i; + + for (i = 0; i < viddata->num_windows; i++) { + SDL_Window *window = viddata->windows[i]; + if (!(window->flags & SDL_WINDOW_VULKAN)) { + KMSDRM_DestroySurfaces(_this, window); + } + } + KMSDRM_drmDropMaster(viddata->drm_fd); +} + +static void KMSDRM_AcquireVT(void *userdata) +{ + SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; + SDL_VideoData *viddata = _this->driverdata; + int i; + + KMSDRM_drmSetMaster(viddata->drm_fd); + for (i = 0; i < viddata->num_windows; i++) { + SDL_Window *window = viddata->windows[i]; + if (!(window->flags & SDL_WINDOW_VULKAN)) { + KMSDRM_CreateSurfaces(_this, window); + } + } +} + int KMSDRM_VideoInit(SDL_VideoDevice *_this) { int ret = 0; @@ -1243,6 +1273,7 @@ int KMSDRM_VideoInit(SDL_VideoDevice *_this) #ifdef SDL_INPUT_LINUXEV SDL_EVDEV_Init(); + SDL_EVDEV_SetVTSwitchCallbacks(KMSDRM_ReleaseVT, _this, KMSDRM_AcquireVT, _this); #elif defined(SDL_INPUT_WSCONS) SDL_WSCONS_Init(); #endif @@ -1261,6 +1292,7 @@ void KMSDRM_VideoQuit(SDL_VideoDevice *_this) KMSDRM_DeinitDisplays(_this); #ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_SetVTSwitchCallbacks(NULL, NULL, NULL, NULL); SDL_EVDEV_Quit(); #elif defined(SDL_INPUT_WSCONS) SDL_WSCONS_Quit(); From 3ab98a357269c7c547db6cef7aba9ff4f7b51650 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 20:43:44 -0800 Subject: [PATCH 304/725] Removed debug print statements (thanks @stsp!) --- src/core/linux/SDL_evdev_kbd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index 2085b07e790fa..2fb3034a39cc2 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -313,13 +313,11 @@ typedef void (*signal_handler)(int signum); static void kbd_vt_release_signal_action(int signum) { -printf("kbd_vt_release_signal_action\n"); SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_RELEASE); } static void kbd_vt_acquire_signal_action(int signum) { -printf("kbd_vt_acquire_signal_action\n"); SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_ACQUIRE); } From 59f93e20a714cf4f6ff3dd3ed7daf3a73e7e7656 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 9 Nov 2023 11:11:07 +0100 Subject: [PATCH 305/725] Add SDL Video Capture, with back-end for linux/macos/ios/android --- CMakeLists.txt | 9 + VisualC-WinRT/SDL-UWP.vcxproj | 3 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 9 + VisualC/SDL/SDL.vcxproj | 1 + VisualC/SDL/SDL.vcxproj.filters | 3 + include/SDL3/SDL.h | 1 + include/SDL3/SDL_video_capture.h | 369 +++++++ include/build_config/SDL_build_config.h.cmake | 4 + include/build_config/SDL_build_config_ios.h | 2 + include/build_config/SDL_build_config_macos.h | 2 + src/dynapi/SDL_dynapi.sym | 16 + src/dynapi/SDL_dynapi_overrides.h | 16 + src/dynapi/SDL_dynapi_procs.h | 16 + src/video/SDL_sysvideocapture.h | 90 ++ src/video/SDL_video.c | 10 + src/video/SDL_video_capture.c | 948 +++++++++++++++++ src/video/SDL_video_capture_apple.m | 615 +++++++++++ src/video/SDL_video_capture_c.h | 33 + src/video/SDL_video_capture_v4l2.c | 965 ++++++++++++++++++ src/video/android/SDL_android_video_capture.c | 678 ++++++++++++ test/CMakeLists.txt | 2 + test/testvideocapture.c | 770 ++++++++++++++ test/testvideocaptureminimal.c | 206 ++++ 23 files changed, 4768 insertions(+) create mode 100644 include/SDL3/SDL_video_capture.h create mode 100644 src/video/SDL_sysvideocapture.h create mode 100644 src/video/SDL_video_capture.c create mode 100644 src/video/SDL_video_capture_apple.m create mode 100644 src/video/SDL_video_capture_c.h create mode 100644 src/video/SDL_video_capture_v4l2.c create mode 100644 src/video/android/SDL_android_video_capture.c create mode 100644 test/testvideocapture.c create mode 100644 test/testvideocaptureminimal.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ca03351edb19c..5564c756014a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,6 +343,7 @@ set_option(SDL_METAL "Enable Metal support" ${APPLE}) set_option(SDL_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS}) dep_option(SDL_KMSDRM_SHARED "Dynamically load KMS DRM support" ON "SDL_KMSDRM" OFF) set_option(SDL_OFFSCREEN "Use offscreen video driver" ON) +dep_option(SDL_VIDEO_CAPTURE "Enable video capturing" ON SDL_VIDEO OFF) option_string(SDL_BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" OFF) option_string(SDL_FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" OFF) dep_option(SDL_HIDAPI "Enable the HIDAPI subsystem" ON "NOT VISIONOS" OFF) @@ -2047,6 +2048,10 @@ elseif(APPLE) set(HAVE_SDL_FILE TRUE) endif() + if(IOS OR TVOS OR MACOSX OR DARWIN) + sdl_sources("${SDL3_SOURCE_DIR}/src/video/SDL_video_capture_apple.m") + endif() + if(SDL_MISC) if(IOS OR TVOS OR VISIONOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/ios/*.m") @@ -2230,6 +2235,10 @@ elseif(APPLE) # Actually load the frameworks at the end so we don't duplicate include. if(SDL_FRAMEWORK_COREVIDEO) + find_library(COREMEDIA CoreMedia) + if(COREMEDIA) + sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreMedia") + endif() sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreVideo") endif() if(SDL_FRAMEWORK_COCOA) diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 1085c0f452007..f7eca1ef796b6 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -89,6 +89,7 @@ + @@ -180,6 +181,7 @@ + @@ -520,6 +522,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index ab0ca0cfb7ab8..fc905ac9e8528 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -165,6 +165,9 @@ Header Files + + Header Files + Header Files @@ -405,6 +408,9 @@ Source Files + + Source Files + Source Files @@ -807,6 +813,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 35edb9b8a6a44..fc53003e73fb7 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -653,6 +653,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index b367e7695fe64..c9d6f36e5d477 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1185,6 +1185,9 @@ video + + video + video diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index 498f0520c15c2..6db0e69d47e58 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -76,6 +76,7 @@ #include #include #include +#include "SDL3/SDL_video_capture.h" #include #endif /* SDL_h_ */ diff --git a/include/SDL3/SDL_video_capture.h b/include/SDL3/SDL_video_capture.h new file mode 100644 index 0000000000000..3d3ce7e641981 --- /dev/null +++ b/include/SDL3/SDL_video_capture.h @@ -0,0 +1,369 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_video_capture.h + * + * Video Capture for the SDL library. + */ + +#ifndef SDL_video_capture_h_ +#define SDL_video_capture_h_ + +#include "SDL3/SDL_video.h" + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This is a unique ID for a video capture device for the time it is connected to the system, + * and is never reused for the lifetime of the application. If the device is + * disconnected and reconnected, it will get a new ID. + * + * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + * + * \sa SDL_GetVideoCaptureDevices + */ +typedef Uint32 SDL_VideoCaptureDeviceID; + + +/** + * The structure used to identify an SDL video capture device + */ +struct SDL_VideoCaptureDevice; +typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice; + +#define SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE 1 + +/** + * SDL_VideoCaptureSpec structure + * + * Only those field can be 'desired' when configuring the device: + * - format + * - width + * - height + * + * \sa SDL_GetVideoCaptureFormat + * \sa SDL_GetVideoCaptureFrameSize + * + */ +typedef struct SDL_VideoCaptureSpec +{ + Uint32 format; /**< Frame SDL_PixelFormatEnum format */ + int width; /**< Frame width */ + int height; /**< Frame height */ +} SDL_VideoCaptureSpec; + +/** + * SDL Video Capture Status + * + * Change states but calling the function in this order: + * + * SDL_OpenVideoCapture() + * SDL_SetVideoCaptureSpec() -> Init + * SDL_StartVideoCapture() -> Playing + * SDL_StopVideoCapture() -> Stopped + * SDL_CloseVideoCapture() + * + */ +typedef enum +{ + SDL_VIDEO_CAPTURE_FAIL = -1, /**< Failed */ + SDL_VIDEO_CAPTURE_INIT = 0, /**< Init, spec hasn't been set */ + SDL_VIDEO_CAPTURE_STOPPED, /**< Stopped */ + SDL_VIDEO_CAPTURE_PLAYING /**< Playing */ +} SDL_VideoCaptureStatus; + +/** + * SDL Video Capture Status + */ +typedef struct SDL_VideoCaptureFrame +{ + Uint64 timestampNS; /**< Frame timestamp in nanoseconds when read from the driver */ + int num_planes; /**< Number of planes */ + Uint8 *data[3]; /**< Pointer to data of i-th plane */ + int pitch[3]; /**< Pitch of i-th plane */ + void *internal; /**< Private field */ +} SDL_VideoCaptureFrame; + + +/** + * Get a list of currently connected video capture devices. + * + * \param count a pointer filled in with the number of video capture devices + * \returns a 0 terminated array of video capture instance IDs which should be + * freed with SDL_free(), or NULL on error; call SDL_GetError() for + * more details. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenVideoCapture + */ +extern DECLSPEC SDL_VideoCaptureDeviceID *SDLCALL SDL_GetVideoCaptureDevices(int *count); + +/** + * Open a Video Capture device + * + * \param instance_id the video capture device instance ID + * \returns device, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetVideoCaptureDeviceName + * \sa SDL_GetVideoCaptureDevices + * \sa SDL_OpenVideoCaptureWithSpec + */ +extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id); + +/** + * Set specification + * + * \param device opened video capture device + * \param desired desired video capture spec + * \param obtained obtained video capture spec + * \param allowed_changes allow changes or not + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenVideoCapture + * \sa SDL_OpenVideoCaptureWithSpec + * \sa SDL_GetVideoCaptureSpec + */ +extern DECLSPEC int SDLCALL SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *device, + const SDL_VideoCaptureSpec *desired, + SDL_VideoCaptureSpec *obtained, + int allowed_changes); + +/** + * Open a Video Capture device and set specification + * + * \param instance_id the video capture device instance ID + * \param desired desired video capture spec + * \param obtained obtained video capture spec + * \param allowed_changes allow changes or not + * \returns device, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenVideoCapture + * \sa SDL_SetVideoCaptureSpec + * \sa SDL_GetVideoCaptureSpec + */ +extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCaptureWithSpec(SDL_VideoCaptureDeviceID instance_id, + const SDL_VideoCaptureSpec *desired, + SDL_VideoCaptureSpec *obtained, + int allowed_changes); +/** + * Get device name + * + * \param instance_id the video capture device instance ID + * \returns device name, shouldn't be freed + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetVideoCaptureDevices + */ +extern DECLSPEC const char * SDLCALL SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id); + +/** + * Get the obtained video capture spec + * + * \param device opened video capture device + * \param spec The SDL_VideoCaptureSpec to be initialized by this function. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetVideoCaptureSpec + * \sa SDL_OpenVideoCaptureWithSpec + */ +extern DECLSPEC int SDLCALL SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *device, SDL_VideoCaptureSpec *spec); + + +/** + * Get frame format of video capture device. + * The value can be used to fill SDL_VideoCaptureSpec structure. + * + * \param device opened video capture device + * \param index format between 0 and num -1 + * \param format pointer output format (SDL_PixelFormatEnum) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumVideoCaptureFormats + */ +extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFormat(SDL_VideoCaptureDevice *device, + int index, + Uint32 *format); + +/** + * Number of available formats for the device + * + * \param device opened video capture device + * \returns number of formats or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetVideoCaptureFormat + * \sa SDL_SetVideoCaptureSpec + */ +extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice *device); + +/** + * Get frame sizes of the device and the specified input format. + * The value can be used to fill SDL_VideoCaptureSpec structure. + * + * \param device opened video capture device + * \param format a format that can be used by the device (SDL_PixelFormatEnum) + * \param index framesize between 0 and num -1 + * \param width output width + * \param height output height + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumVideoCaptureFrameSizes + */ +extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDevice *device, Uint32 format, int index, int *width, int *height); + +/** + * Number of different framesizes available for the device and pixel format. + * + * \param device opened video capture device + * \param format frame pixel format (SDL_PixelFormatEnum) + * \returns number of framesizes or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetVideoCaptureFrameSize + * \sa SDL_SetVideoCaptureSpec + */ +extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDevice *device, Uint32 format); + + +/** + * Get video capture status + * + * \param device opened video capture device + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_VideoCaptureStatus + */ +extern DECLSPEC SDL_VideoCaptureStatus SDLCALL SDL_GetVideoCaptureStatus(SDL_VideoCaptureDevice *device); + +/** + * Start video capture + * + * \param device opened video capture device + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_StopVideoCapture + */ +extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDevice *device); + +/** + * Acquire a frame. + * The frame is a memory pointer to the image data, whose size and format + * are given by the the obtained spec. + * + * Non blocking API. If there is a frame available, frame->num_planes is non 0. + * If frame->num_planes is 0 and returned code is 0, there is no frame at that time. + * + * After used, the frame should be released with SDL_ReleaseVideoCaptureFrame + * + * \param device opened video capture device + * \param frame pointer to get the frame + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ReleaseVideoCaptureFrame + */ +extern DECLSPEC int SDLCALL SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame); + +/** + * Release a frame. Let the back-end re-use the internal buffer for video capture. + * + * All acquired frames should be released before closing the device. + * + * \param device opened video capture device + * \param frame frame pointer. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AcquireVideoCaptureFrame + */ +extern DECLSPEC int SDLCALL SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame); + +/** + * Stop Video Capture + * + * \param device opened video capture device + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_StartVideoCapture + */ +extern DECLSPEC int SDLCALL SDL_StopVideoCapture(SDL_VideoCaptureDevice *device); + +/** + * Use this function to shut down video_capture processing and close the video_capture device. + * + * \param device opened video capture device + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenVideoCaptureWithSpec + * \sa SDL_OpenVideoCapture + */ +extern DECLSPEC void SDLCALL SDL_CloseVideoCapture(SDL_VideoCaptureDevice *device); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_video_capture_h_ */ diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index b776251f81e42..8b26e0dea929d 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -244,11 +244,15 @@ #cmakedefine USE_POSIX_SPAWN @USE_POSIX_SPAWN@ +#cmakedefine HAVE_COREMEDIA + /* SDL internal assertion support */ #if @SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED@ #cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@ #endif +#cmakedefine SDL_VIDEO_CAPTURE + /* Allow disabling of core subsystems */ #cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@ #cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@ diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index 96391f848f57c..340bbc0c29971 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -197,6 +197,8 @@ #define SDL_VIDEO_METAL 1 #endif +#define HAVE_COREMEDIA 1 + /* Enable system power support */ #define SDL_POWER_UIKIT 1 diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index 43400d3f6ef4c..bf1b682ed02b5 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -260,6 +260,8 @@ #endif #endif +#define HAVE_COREMEDIA 1 + /* Enable system power support */ #define SDL_POWER_MACOSX 1 diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index e6fd996c64299..96e662f2c51e5 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -923,6 +923,22 @@ SDL3_0.0.0 { SDL_SetPropertyWithCleanup; SDL_SetX11EventHook; SDL_GetGlobalProperties; + SDL_OpenVideoCapture; + SDL_SetVideoCaptureSpec; + SDL_OpenVideoCaptureWithSpec; + SDL_GetVideoCaptureDeviceName; + SDL_GetVideoCaptureSpec; + SDL_GetVideoCaptureFormat; + SDL_GetNumVideoCaptureFormats; + SDL_GetVideoCaptureFrameSize; + SDL_GetNumVideoCaptureFrameSizes; + SDL_GetVideoCaptureStatus; + SDL_StartVideoCapture; + SDL_AcquireVideoCaptureFrame; + SDL_ReleaseVideoCaptureFrame; + SDL_StopVideoCapture; + SDL_CloseVideoCapture; + SDL_GetVideoCaptureDevices; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 97d05e88ba0b8..adb202523cbcb 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -948,3 +948,19 @@ #define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL #define SDL_SetX11EventHook SDL_SetX11EventHook_REAL #define SDL_GetGlobalProperties SDL_GetGlobalProperties_REAL +#define SDL_OpenVideoCapture SDL_OpenVideoCapture_REAL +#define SDL_SetVideoCaptureSpec SDL_SetVideoCaptureSpec_REAL +#define SDL_OpenVideoCaptureWithSpec SDL_OpenVideoCaptureWithSpec_REAL +#define SDL_GetVideoCaptureDeviceName SDL_GetVideoCaptureDeviceName_REAL +#define SDL_GetVideoCaptureSpec SDL_GetVideoCaptureSpec_REAL +#define SDL_GetVideoCaptureFormat SDL_GetVideoCaptureFormat_REAL +#define SDL_GetNumVideoCaptureFormats SDL_GetNumVideoCaptureFormats_REAL +#define SDL_GetVideoCaptureFrameSize SDL_GetVideoCaptureFrameSize_REAL +#define SDL_GetNumVideoCaptureFrameSizes SDL_GetNumVideoCaptureFrameSizes_REAL +#define SDL_GetVideoCaptureStatus SDL_GetVideoCaptureStatus_REAL +#define SDL_StartVideoCapture SDL_StartVideoCapture_REAL +#define SDL_AcquireVideoCaptureFrame SDL_AcquireVideoCaptureFrame_REAL +#define SDL_ReleaseVideoCaptureFrame SDL_ReleaseVideoCaptureFrame_REAL +#define SDL_StopVideoCapture SDL_StopVideoCapture_REAL +#define SDL_CloseVideoCapture SDL_CloseVideoCapture_REAL +#define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 64022522244f3..7f3b0e5211258 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -981,3 +981,19 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a), SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGlobalProperties,(void),(),return) +SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCapture,(SDL_VideoCaptureDeviceID a),(a),return) +SDL_DYNAPI_PROC(int,SDL_SetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCaptureWithSpec,(SDL_VideoCaptureDeviceID a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(const char*,SDL_GetVideoCaptureDeviceName,(SDL_VideoCaptureDeviceID a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureSpec *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFormat,(SDL_VideoCaptureDevice *a, int b, Uint32 *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFormats,(SDL_VideoCaptureDevice *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFrameSize,(SDL_VideoCaptureDevice *a, Uint32 b, int c, int *d, int *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFrameSizes,(SDL_VideoCaptureDevice *a, Uint32 b),(a,b),return) +SDL_DYNAPI_PROC(SDL_VideoCaptureStatus,SDL_GetVideoCaptureStatus,(SDL_VideoCaptureDevice *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_StartVideoCapture,(SDL_VideoCaptureDevice *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_AcquireVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_ReleaseVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_StopVideoCapture,(SDL_VideoCaptureDevice *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),) +SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return) diff --git a/src/video/SDL_sysvideocapture.h b/src/video/SDL_sysvideocapture.h new file mode 100644 index 0000000000000..fe71664f51959 --- /dev/null +++ b/src/video/SDL_sysvideocapture.h @@ -0,0 +1,90 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../SDL_internal.h" + +#ifndef SDL_sysvideocapture_h_ +#define SDL_sysvideocapture_h_ + +#include "../SDL_list.h" + +/* The SDL video_capture driver */ +typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice; + +/* Define the SDL video_capture driver structure */ +struct SDL_VideoCaptureDevice +{ + /* * * */ + /* Data common to all devices */ + + /* The device's current video_capture specification */ + SDL_VideoCaptureSpec spec; + + /* Device name */ + char *dev_name; + + /* Current state flags */ + SDL_AtomicInt shutdown; + SDL_AtomicInt enabled; + SDL_bool is_spec_set; + + /* A mutex for locking the queue buffers */ + SDL_Mutex *device_lock; + SDL_Mutex *acquiring_lock; + + /* A thread to feed the video_capture device */ + SDL_Thread *thread; + SDL_threadID threadid; + + /* Queued buffers (if app not using callback). */ + SDL_ListNode *buffer_queue; + + /* * * */ + /* Data private to this driver */ + struct SDL_PrivateVideoCaptureData *hidden; +}; + +extern int OpenDevice(SDL_VideoCaptureDevice *_this); +extern void CloseDevice(SDL_VideoCaptureDevice *_this); + +extern int InitDevice(SDL_VideoCaptureDevice *_this); + +extern int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec); + +extern int StartCapture(SDL_VideoCaptureDevice *_this); +extern int StopCapture(SDL_VideoCaptureDevice *_this); + +extern int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame); +extern int ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame); + +extern int GetNumFormats(SDL_VideoCaptureDevice *_this); +extern int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format); + +extern int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format); +extern int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height); + +extern int GetDeviceName(int index, char *buf, int size); +extern int GetNumDevices(void); + + +extern SDL_bool check_all_device_closed(void); +extern SDL_bool check_device_playing(void); + +#endif /* SDL_sysvideocapture_h_ */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index df0ad23511371..d4ab9a475d1a4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -31,6 +31,7 @@ #include "SDL_video_c.h" #include "../events/SDL_events_c.h" #include "../timer/SDL_timer_c.h" +#include "SDL_video_capture_c.h" #ifdef SDL_VIDEO_OPENGL #include @@ -443,6 +444,7 @@ int SDL_VideoInit(const char *driver_name) SDL_bool init_keyboard = SDL_FALSE; SDL_bool init_mouse = SDL_FALSE; SDL_bool init_touch = SDL_FALSE; + SDL_bool init_video_capture = SDL_FALSE; int i = 0; /* Check to make sure we don't overwrite '_this' */ @@ -471,6 +473,10 @@ int SDL_VideoInit(const char *driver_name) goto pre_driver_error; } init_touch = SDL_TRUE; + if (SDL_VideoCaptureInit() < 0) { + goto pre_driver_error; + } + init_video_capture = SDL_TRUE; /* Select the proper video driver */ video = NULL; @@ -565,6 +571,9 @@ int SDL_VideoInit(const char *driver_name) pre_driver_error: SDL_assert(_this == NULL); + if (init_video_capture) { + SDL_QuitVideoCapture(); + } if (init_touch) { SDL_QuitTouch(); } @@ -3684,6 +3693,7 @@ void SDL_VideoQuit(void) SDL_ClearClipboardData(); /* Halt event processing before doing anything else */ + SDL_QuitVideoCapture(); SDL_QuitTouch(); SDL_QuitMouse(); SDL_QuitKeyboard(); diff --git a/src/video/SDL_video_capture.c b/src/video/SDL_video_capture.c new file mode 100644 index 0000000000000..bd4fc8257758a --- /dev/null +++ b/src/video/SDL_video_capture.c @@ -0,0 +1,948 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL3/SDL.h" +#include "SDL3/SDL_video_capture.h" +#include "SDL_sysvideocapture.h" +#include "SDL_video_capture_c.h" +#include "SDL_pixels_c.h" +#include "../thread/SDL_systhread.h" + +#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 + + +#ifdef SDL_VIDEO_CAPTURE +/* list node entries to share frames between SDL and user app */ +typedef struct entry_t +{ + SDL_VideoCaptureFrame frame; +} entry_t; + +static SDL_VideoCaptureDevice *open_devices[16]; + +static void +close_device(SDL_VideoCaptureDevice *device) +{ + if (!device) { + return; + } + + SDL_AtomicSet(&device->shutdown, 1); + SDL_AtomicSet(&device->enabled, 1); + + if (device->thread != NULL) { + SDL_WaitThread(device->thread, NULL); + } + if (device->device_lock != NULL) { + SDL_DestroyMutex(device->device_lock); + } + if (device->acquiring_lock != NULL) { + SDL_DestroyMutex(device->acquiring_lock); + } + + { + int i, n = SDL_arraysize(open_devices); + for (i = 0; i < n; i++) { + if (open_devices[i] == device) { + open_devices[i] = NULL; + } + } + } + + { + entry_t *entry = NULL; + while (device->buffer_queue != NULL) { + SDL_ListPop(&device->buffer_queue, (void**)&entry); + if (entry) { + SDL_VideoCaptureFrame f = entry->frame; + /* Release frames not acquired, if any */ + if (f.timestampNS) { + ReleaseFrame(device, &f); + } + SDL_free(entry); + } + } + } + + CloseDevice(device); + + SDL_free(device->dev_name); + SDL_free(device); +} + +/* Tell if all device are closed */ +SDL_bool check_all_device_closed(void) +{ + int i, n = SDL_arraysize(open_devices); + int all_closed = SDL_TRUE; + for (i = 0; i < n; i++) { + if (open_devices[i]) { + all_closed = SDL_FALSE; + break; + } + } + return all_closed; +} + +/* Tell if at least one device is in playing state */ +SDL_bool check_device_playing(void) +{ + int i, n = SDL_arraysize(open_devices); + for (i = 0; i < n; i++) { + if (open_devices[i]) { + if (SDL_GetVideoCaptureStatus(open_devices[i]) == SDL_VIDEO_CAPTURE_PLAYING) { + return SDL_TRUE; + } + } + } + return SDL_FALSE; +} + + +#endif /* SDL_VIDEO_CAPTURE */ + +void +SDL_CloseVideoCapture(SDL_VideoCaptureDevice *device) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + SDL_InvalidParamError("device"); + return; + } + close_device(device); +#endif +} + +int +SDL_StartVideoCapture(SDL_VideoCaptureDevice *device) +{ +#ifdef SDL_VIDEO_CAPTURE + SDL_VideoCaptureStatus status; + int result; + if (!device) { + return SDL_InvalidParamError("device"); + } + + if (device->is_spec_set == SDL_FALSE) { + return SDL_SetError("no spec set"); + } + + status = SDL_GetVideoCaptureStatus(device); + if (status != SDL_VIDEO_CAPTURE_INIT) { + return SDL_SetError("invalid state"); + } + + result = StartCapture(device); + if (result < 0) { + return result; + } + + SDL_AtomicSet(&device->enabled, 1); + + return 0; +#else + return SDL_Unsupported(); +#endif +} + +int +SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *device, SDL_VideoCaptureSpec *spec) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + + if (!spec) { + return SDL_InvalidParamError("spec"); + } + + SDL_zerop(spec); + + return GetDeviceSpec(device, spec); +#else + return SDL_Unsupported(); +#endif +} + +int +SDL_StopVideoCapture(SDL_VideoCaptureDevice *device) +{ +#ifdef SDL_VIDEO_CAPTURE + SDL_VideoCaptureStatus status; + int ret; + if (!device) { + return SDL_InvalidParamError("device"); + } + + status = SDL_GetVideoCaptureStatus(device); + + if (status != SDL_VIDEO_CAPTURE_PLAYING) { + return SDL_SetError("invalid state"); + } + + SDL_AtomicSet(&device->enabled, 0); + SDL_AtomicSet(&device->shutdown, 1); + + SDL_LockMutex(device->acquiring_lock); + ret = StopCapture(device); + SDL_UnlockMutex(device->acquiring_lock); + + if (ret < 0) { + return -1; + } + + return 0; +#else + return SDL_Unsupported(); +#endif +} + +#ifdef SDL_VIDEO_CAPTURE + +/* Check spec has valid format and frame size */ +static int +prepare_video_capturespec(SDL_VideoCaptureDevice *device, const SDL_VideoCaptureSpec *desired, SDL_VideoCaptureSpec *obtained, int allowed_changes) +{ + /* Check format */ + { + int i, num = SDL_GetNumVideoCaptureFormats(device); + int is_format_valid = 0; + + for (i = 0; i < num; i++) { + Uint32 format; + if (SDL_GetVideoCaptureFormat(device, i, &format) == 0) { + if (format == desired->format && format != SDL_PIXELFORMAT_UNKNOWN) { + is_format_valid = 1; + obtained->format = format; + break; + } + } + } + + if (!is_format_valid) { + if (allowed_changes) { + for (i = 0; i < num; i++) { + Uint32 format; + if (SDL_GetVideoCaptureFormat(device, i, &format) == 0) { + if (format != SDL_PIXELFORMAT_UNKNOWN) { + obtained->format = format; + is_format_valid = 1; + break; + } + } + } + + } else { + SDL_SetError("Not allowed to change the format"); + return -1; + } + } + + if (!is_format_valid) { + SDL_SetError("Invalid format"); + return -1; + } + } + + /* Check frame size */ + { + int i, num = SDL_GetNumVideoCaptureFrameSizes(device, obtained->format); + int is_framesize_valid = 0; + + for (i = 0; i < num; i++) { + int w, h; + if (SDL_GetVideoCaptureFrameSize(device, obtained->format, i, &w, &h) == 0) { + if (desired->width == w && desired->height == h) { + is_framesize_valid = 1; + obtained->width = w; + obtained->height = h; + break; + } + } + } + + if (!is_framesize_valid) { + if (allowed_changes) { + int w, h; + if (SDL_GetVideoCaptureFrameSize(device, obtained->format, 0, &w, &h) == 0) { + is_framesize_valid = 1; + obtained->width = w; + obtained->height = h; + } + } else { + SDL_SetError("Not allowed to change the frame size"); + return -1; + } + } + + if (!is_framesize_valid) { + SDL_SetError("Invalid frame size"); + return -1; + } + + } + + return 0; +} + +#endif /* SDL_VIDEO_CAPTURE */ + +const char * +SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id) +{ +#ifdef SDL_VIDEO_CAPTURE + int index = instance_id - 1; + static char buf[256]; + buf[0] = 0; + buf[255] = 0; + + if (instance_id == 0) { + SDL_InvalidParamError("instance_id"); + return NULL; + } + + if (GetDeviceName(index, buf, sizeof (buf)) < 0) { + buf[0] = 0; + } + return buf; +#else + SDL_Unsupported(); + return NULL; +#endif +} + + +SDL_VideoCaptureDeviceID * +SDL_GetVideoCaptureDevices(int *count) +{ + + int i; +#ifdef SDL_VIDEO_CAPTURE + int num = GetNumDevices(); +#else + int num = 0; +#endif + SDL_VideoCaptureDeviceID *ret; + + ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); + + if (ret == NULL) { + SDL_OutOfMemory(); + if (count) { + *count = 0; + } + return NULL; + } + + for (i = 0; i < num; i++) { + ret[i] = i + 1; + } + ret[num] = 0; + + if (count) { + *count = num; + } + + return ret; +} + +#ifdef SDL_VIDEO_CAPTURE + +/* Video capture thread function */ +static int SDLCALL +SDL_CaptureVideoThread(void *devicep) +{ + const int delay = 20; + SDL_VideoCaptureDevice *device = (SDL_VideoCaptureDevice *) devicep; + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("Start thread 'SDL_CaptureVideo'"); +#endif + + +#ifdef SDL_VIDEO_DRIVER_ANDROID + // TODO + /* + { + // Set thread priority to THREAD_PRIORITY_VIDEO + extern void Android_JNI_VideoCaptureSetThreadPriority(int, int); + Android_JNI_VideoCaptureSetThreadPriority(device->iscapture, device); + }*/ +#else + /* The video_capture mixing is always a high priority thread */ + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); +#endif + + /* Perform any thread setup */ + device->threadid = SDL_ThreadID(); + + /* Init state */ + while (!SDL_AtomicGet(&device->enabled)) { + SDL_Delay(delay); + } + + /* Loop, filling the video_capture buffers */ + while (!SDL_AtomicGet(&device->shutdown)) { + SDL_VideoCaptureFrame f; + int ret; + entry_t *entry; + + SDL_zero(f); + + SDL_LockMutex(device->acquiring_lock); + ret = AcquireFrame(device, &f); + SDL_UnlockMutex(device->acquiring_lock); + + if (ret == 0) { + if (f.num_planes == 0) { + continue; + } + } + + if (ret < 0) { + /* Flag it as an error */ +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("dev[%p] error AcquireFrame: %d %s", (void *)device, ret, SDL_GetError()); +#endif + f.num_planes = 0; + } + + + entry = SDL_malloc(sizeof (entry_t)); + if (entry == NULL) { + goto error_mem; + } + + entry->frame = f; + + SDL_LockMutex(device->device_lock); + ret = SDL_ListAdd(&device->buffer_queue, entry); + SDL_UnlockMutex(device->device_lock); + + if (ret < 0) { + SDL_free(entry); + goto error_mem; + } + } + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("dev[%p] End thread 'SDL_CaptureVideo'", (void *)device); +#endif + return 0; + +error_mem: +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("dev[%p] End thread 'SDL_CaptureVideo' with error: %s", (void *)device, SDL_GetError()); +#endif + SDL_AtomicSet(&device->shutdown, 1); + SDL_OutOfMemory(); + return 0; +} +#endif + +SDL_VideoCaptureDevice * +SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id) +{ +#ifdef SDL_VIDEO_CAPTURE + int i, n = SDL_arraysize(open_devices); + int id = -1; + SDL_VideoCaptureDevice *device = NULL; + const char *device_name = NULL; + + if (!SDL_WasInit(SDL_INIT_VIDEO)) { + SDL_SetError("Video subsystem is not initialized"); + goto error; + } + + /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */ + /* Find an available device ID... */ + for (i = 0; i < n; i++) { + if (open_devices[i] == NULL) { + id = i; + break; + } + } + + if (id == -1) { + SDL_SetError("Too many open video capture devices"); + goto error; + } + + if (instance_id != 0) { + device_name = SDL_GetVideoCaptureDeviceName(instance_id); + if (device_name == NULL) { + goto error; + } + } else { + SDL_VideoCaptureDeviceID *devices = SDL_GetVideoCaptureDevices(NULL); + if (devices && devices[0]) { + device_name = SDL_GetVideoCaptureDeviceName(devices[0]); + SDL_free(devices); + } + } + + /* Let the user override. */ + { + const char *dev = SDL_getenv("SDL_VIDEO_CAPTURE_DEVICE_NAME"); + if (dev && dev[0]) { + device_name = dev; + } + } + + if (device_name == NULL) { + goto error; + } + + device = (SDL_VideoCaptureDevice *) SDL_calloc(1, sizeof (SDL_VideoCaptureDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + goto error; + } + device->dev_name = SDL_strdup(device_name); + + + SDL_AtomicSet(&device->shutdown, 0); + SDL_AtomicSet(&device->enabled, 0); + + device->device_lock = SDL_CreateMutex(); + if (device->device_lock == NULL) { + SDL_SetError("Couldn't create acquiring_lock"); + goto error; + } + + device->acquiring_lock = SDL_CreateMutex(); + if (device->acquiring_lock == NULL) { + SDL_SetError("Couldn't create acquiring_lock"); + goto error; + } + + if (OpenDevice(device) < 0) { + goto error; + } + + /* empty */ + device->buffer_queue = NULL; + open_devices[id] = device; /* add it to our list of open devices. */ + + + /* Start the video_capture thread */ + { + const size_t stacksize = 64 * 1024; + char threadname[64]; + + SDL_snprintf(threadname, sizeof (threadname), "SDLVideoC%d", id); + device->thread = SDL_CreateThreadInternal(SDL_CaptureVideoThread, threadname, stacksize, device); + + if (device->thread == NULL) { + SDL_SetError("Couldn't create video_capture thread"); + goto error; + } + } + + return device; + +error: + close_device(device); + return NULL; +#else + SDL_Unsupported(); + return NULL; +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *device, + const SDL_VideoCaptureSpec *desired, + SDL_VideoCaptureSpec *obtained, + int allowed_changes) +{ +#ifdef SDL_VIDEO_CAPTURE + SDL_VideoCaptureSpec _obtained; + SDL_VideoCaptureSpec _desired; + int result; + + if (!device) { + return SDL_InvalidParamError("device"); + } + + if (device->is_spec_set == SDL_TRUE) { + return SDL_SetError("already configured"); + } + + if (!desired) { + SDL_zero(_desired); + desired = &_desired; + allowed_changes = SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE; + } else { + /* in case desired == obtained */ + _desired = *desired; + desired = &_desired; + } + + if (!obtained) { + obtained = &_obtained; + } + + SDL_zerop(obtained); + + if (prepare_video_capturespec(device, desired, obtained, allowed_changes) < 0) { + return -1; + } + + device->spec = *obtained; + + result = InitDevice(device); + if (result < 0) { + return result; + } + + *obtained = device->spec; + + device->is_spec_set = SDL_TRUE; + + return 0; +#else + SDL_zero(*obtained); + return SDL_Unsupported(); +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + + if (!frame) { + return SDL_InvalidParamError("frame"); + } + + SDL_zerop(frame); + + if (device->thread == NULL) { + int ret; + + /* Wait for a frame */ + while ((ret = AcquireFrame(device, frame)) == 0) { + if (frame->num_planes) { + return 0; + } + } + return -1; + } else { + entry_t *entry = NULL; + + SDL_LockMutex(device->device_lock); + SDL_ListPop(&device->buffer_queue, (void**)&entry); + SDL_UnlockMutex(device->device_lock); + + if (entry) { + *frame = entry->frame; + SDL_free(entry); + + /* Error from thread */ + if (frame->num_planes == 0 && frame->timestampNS == 0) { + return SDL_SetError("error from acquisition thread"); + } + + + } else { + /* Queue is empty. Not an error. */ + } + } + + return 0; +#else + return SDL_Unsupported(); +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + + if (frame == NULL) { + return SDL_InvalidParamError("frame"); + } + + if (ReleaseFrame(device, frame) < 0) { + return -1; + } + + SDL_zerop(frame); + + return 0; +#else + return SDL_Unsupported(); +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice *device) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + return GetNumFormats(device); +#else + return 0; +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_GetVideoCaptureFormat(SDL_VideoCaptureDevice *device, int index, Uint32 *format) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + if (!format) { + return SDL_InvalidParamError("format"); + } + *format = 0; + return GetFormat(device, index, format); +#else + return SDL_Unsupported(); +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDevice *device, Uint32 format) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + return GetNumFrameSizes(device, format); +#else + return 0; +#endif /* SDL_VIDEO_CAPTURE */ +} + +int +SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDevice *device, Uint32 format, int index, int *width, int *height) +{ +#ifdef SDL_VIDEO_CAPTURE + if (!device) { + return SDL_InvalidParamError("device"); + } + if (!width) { + return SDL_InvalidParamError("width"); + } + if (!height) { + return SDL_InvalidParamError("height"); + } + *width = 0; + *height = 0; + return GetFrameSize(device, format, index, width, height); +#else + return SDL_Unsupported(); +#endif +} + +SDL_VideoCaptureDevice * +SDL_OpenVideoCaptureWithSpec( + SDL_VideoCaptureDeviceID instance_id, + const SDL_VideoCaptureSpec *desired, + SDL_VideoCaptureSpec *obtained, + int allowed_changes) +{ +#ifdef SDL_VIDEO_CAPTURE + SDL_VideoCaptureDevice *device; + + if ((device = SDL_OpenVideoCapture(instance_id)) == NULL) { + return NULL; + } + + if (SDL_SetVideoCaptureSpec(device, desired, obtained, allowed_changes) < 0) { + SDL_CloseVideoCapture(device); + return NULL; + } + return device; +#else + SDL_Unsupported(); + return NULL; +#endif +} + +SDL_VideoCaptureStatus +SDL_GetVideoCaptureStatus(SDL_VideoCaptureDevice *device) +{ +#ifdef SDL_VIDEO_CAPTURE + if (device == NULL) { + return SDL_VIDEO_CAPTURE_INIT; + } + + if (device->is_spec_set == SDL_FALSE) { + return SDL_VIDEO_CAPTURE_INIT; + } + + if (SDL_AtomicGet(&device->shutdown)) { + return SDL_VIDEO_CAPTURE_STOPPED; + } + + if (SDL_AtomicGet(&device->enabled)) { + return SDL_VIDEO_CAPTURE_PLAYING; + } + return SDL_VIDEO_CAPTURE_INIT; +#else + SDL_Unsupported(); + return SDL_VIDEO_CAPTURE_FAIL; +#endif +} + +int +SDL_VideoCaptureInit(void) +{ +#ifdef SDL_VIDEO_CAPTURE + SDL_zeroa(open_devices); + return 0; +#else + return 0; +#endif +} + +void +SDL_QuitVideoCapture(void) +{ +#ifdef SDL_VIDEO_CAPTURE + int i, n = SDL_arraysize(open_devices); + for (i = 0; i < n; i++) { + close_device(open_devices[i]); + } + + SDL_zeroa(open_devices); +#endif +} + +#ifdef SDL_VIDEO_CAPTURE + +#if defined(__linux__) && !defined(__ANDROID__) + +/* See SDL_video_capture_v4l2.c */ + +#elif defined(__ANDROID__) && __ANDROID_API__ >= 24 + +/* See SDL_android_video_capture.c */ + +#elif defined(__IPHONEOS__) || defined(__MACOS__) + +/* See SDL_video_capture_apple.m */ +#else + +int +OpenDevice(SDL_VideoCaptureDevice *_this) +{ + return SDL_SetError("not implemented"); +} + +void +CloseDevice(SDL_VideoCaptureDevice *_this) +{ + return; +} + +int +InitDevice(SDL_VideoCaptureDevice *_this) +{ + size_t size, pitch; + SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE); + SDL_Log("Buffer size: %d x %d", _this->spec.width, _this->spec.height); + return -1; +} + +int +GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) +{ + return SDL_Unsupported(); +} + +int +StartCapture(SDL_VideoCaptureDevice *_this) +{ + return SDL_Unsupported(); +} + +int +StopCapture(SDL_VideoCaptureDevice *_this) +{ + return -1; +} + +int +AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + return -1; +} + +int +ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + return -1; +} + +int +GetNumFormats(SDL_VideoCaptureDevice *_this) +{ + return -1; +} + +int +GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) +{ + return -1; +} + +int +GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) +{ + return -1; +} + +int +GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) +{ + return -1; +} + +int +GetDeviceName(int index, char *buf, int size) +{ + return -1; +} + +int +GetNumDevices(void) +{ + return -1; +} +#endif + +#endif /* SDL_VIDEO_CAPTURE */ diff --git a/src/video/SDL_video_capture_apple.m b/src/video/SDL_video_capture_apple.m new file mode 100644 index 0000000000000..3e58cf4e7a61c --- /dev/null +++ b/src/video/SDL_video_capture_apple.m @@ -0,0 +1,615 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2021 Valve Corporation + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_CAPTURE + +#include "SDL3/SDL.h" +#include "SDL3/SDL_video_capture.h" +#include "SDL_sysvideocapture.h" +#include "SDL_video_capture_c.h" +#include "../thread/SDL_systhread.h" + +#if defined(HAVE_COREMEDIA) && defined(__MACOS__) && (__MAC_OS_X_VERSION_MAX_ALLOWED < 101500) +/* AVCaptureDeviceTypeBuiltInWideAngleCamera requires macOS SDK 10.15 */ +#undef HAVE_COREMEDIA +#endif + +#if TARGET_OS_TV +#undef HAVE_COREMEDIA +#endif + +#ifndef HAVE_COREMEDIA +int InitDevice(SDL_VideoCaptureDevice *_this) { + return -1; +} +int OpenDevice(SDL_VideoCaptureDevice *_this) { + return -1; +} +int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) { + return -1; +} +void CloseDevice(SDL_VideoCaptureDevice *_this) { +} +int GetDeviceName(int index, char *buf, int size) { + return -1; +} +int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) { + return -1; +} +int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) { + return -1; +} +int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) { + return -1; +} +int GetNumDevices(void) { + return 0; +} +int GetNumFormats(SDL_VideoCaptureDevice *_this) { + return 0; +} +int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) { + return 0; +} +int ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) { + return 0; +} +int StartCapture(SDL_VideoCaptureDevice *_this) { + return 0; +} +int StopCapture(SDL_VideoCaptureDevice *_this) { + return 0; +} + +#else + +#import +#import + +/* + * Need to link with:: CoreMedia CoreVideo + * + * Add in pInfo.list: + * NSCameraUsageDescription Access camera + * + * + * MACOSX: + * Add to the Code Sign Entitlement file: + * com.apple.security.device.camera + * + * + * IOS: + * + * - Need to link with:: CoreMedia CoreVideo + * - Add #define SDL_VIDEO_CAPTURE 1 + * to SDL_build_config_ios.h + */ + +@class MySampleBufferDelegate; + +struct SDL_PrivateVideoCaptureData +{ + dispatch_queue_t queue; + MySampleBufferDelegate *delegate; + AVCaptureSession *session; + CMSimpleQueueRef frame_queue; +}; + +static NSString * +fourcc_to_nstring(Uint32 code) +{ + Uint8 buf[4]; + *(Uint32 *)buf = code; + return [NSString stringWithFormat:@"%c%c%c%c", buf[3], buf[2], buf[1], buf[0]]; +} + +static NSArray * +discover_devices() +{ + NSArray *deviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera]; + + AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession + discoverySessionWithDeviceTypes:deviceType + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; + + NSArray *devices = discoverySession.devices; + + if ([devices count] > 0) { + return devices; + } else { + AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (captureDevice == nil) { + return devices; + } else { + NSArray *default_device = @[ captureDevice ]; + return default_device; + } + } + + return devices; +} + +static AVCaptureDevice * +get_device_by_name(const char *dev_name) +{ + NSArray *devices = discover_devices(); + + for (AVCaptureDevice *device in devices) { + char buf[1024]; + NSString *cameraID = [device localizedName]; + const char *str = [cameraID UTF8String]; + SDL_snprintf(buf, sizeof (buf) - 1, "%s", str); + if (SDL_strcmp(buf, dev_name) == 0) { + return device; + } + } + return nil; +} + +static Uint32 +nsfourcc_to_sdlformat(NSString *nsfourcc) +{ + const char *str = [nsfourcc UTF8String]; + + /* FIXME + * on IOS this mode gives 2 planes, and it's NV12 + * on macos, 1 plane/ YVYU + * + */ +#ifdef __MACOS__ + if (SDL_strcmp("420v", str) == 0) return SDL_PIXELFORMAT_YVYU; +#else + if (SDL_strcmp("420v", str) == 0) return SDL_PIXELFORMAT_NV12; +#endif + if (SDL_strcmp("yuvs", str) == 0) return SDL_PIXELFORMAT_UYVY; + if (SDL_strcmp("420f", str) == 0) return SDL_PIXELFORMAT_UNKNOWN; + + SDL_Log("Unknown format '%s'", str); + + return SDL_PIXELFORMAT_UNKNOWN; +} + +static NSString * +sdlformat_to_nsfourcc(Uint32 fmt) +{ + const char *str = ""; + NSString *result; + +#ifdef __MACOS__ + if (fmt == SDL_PIXELFORMAT_YVYU) str = "420v"; +#else + if (fmt == SDL_PIXELFORMAT_NV12) str = "420v"; +#endif + if (fmt == SDL_PIXELFORMAT_UYVY) str = "yuvs"; + + result = [[NSString alloc] initWithUTF8String: str]; + + return result; +} + + +@interface MySampleBufferDelegate : NSObject + @property struct SDL_PrivateVideoCaptureData *hidden; + - (void) set: (struct SDL_PrivateVideoCaptureData *) val; +@end + +@implementation MySampleBufferDelegate + + - (void) set: (struct SDL_PrivateVideoCaptureData *) val { + _hidden = val; + } + + - (void) captureOutput:(AVCaptureOutput *)output + didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *) connection { + CFRetain(sampleBuffer); + CMSimpleQueueEnqueue(_hidden->frame_queue, sampleBuffer); + } + + - (void)captureOutput:(AVCaptureOutput *)output + didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection { + SDL_Log("Drop frame.."); + } +@end + +int +OpenDevice(SDL_VideoCaptureDevice *_this) +{ + _this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData)); + if (_this->hidden == NULL) { + SDL_OutOfMemory(); + goto error; + } + + return 0; + +error: + return -1; +} + +void +CloseDevice(SDL_VideoCaptureDevice *_this) +{ + if (!_this) { + return; + } + + if (_this->hidden) { + AVCaptureSession *session = _this->hidden->session; + + if (session) { + AVCaptureInput *input; + AVCaptureVideoDataOutput *output; + input = [session.inputs objectAtIndex:0]; + [session removeInput:input]; + output = (AVCaptureVideoDataOutput*)[session.outputs objectAtIndex:0]; + [session removeOutput:output]; + // TODO more cleanup ? + } + + if (_this->hidden->frame_queue) { + CFRelease(_this->hidden->frame_queue); + } + + SDL_free(_this->hidden); + _this->hidden = NULL; + } +} + +int +InitDevice(SDL_VideoCaptureDevice *_this) +{ + NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format); + int w = _this->spec.width; + int h = _this->spec.height; + + NSError *error = nil; + AVCaptureDevice *device = nil; + AVCaptureDeviceInput *input = nil; + AVCaptureVideoDataOutput *output = nil; + + AVCaptureDeviceFormat *spec_format = nil; + +#ifdef __MACOS__ + if (@available(macOS 10.15, *)) { + /* good. */ + } else { + return -1; + } +#endif + + device = get_device_by_name(_this->dev_name); + if (!device) { + goto error; + } + + _this->hidden->session = [[AVCaptureSession alloc] init]; + if (_this->hidden->session == nil) { + goto error; + } + + [_this->hidden->session setSessionPreset:AVCaptureSessionPresetHigh]; + + // Pick format that matches the spec + { + NSArray *formats = [device formats]; + for (AVCaptureDeviceFormat *format in formats) { + CMFormatDescriptionRef formatDescription = [format formatDescription]; + FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription); + NSString *str = fourcc_to_nstring(mediaSubType); + if (str == fmt) { + CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription); + if (dim.width == w && dim.height == h) { + spec_format = format; + break; + } + } + } + } + + if (spec_format == nil) { + SDL_SetError("format not found"); + goto error; + } + + // Set format + if ([device lockForConfiguration:NULL] == YES) { + device.activeFormat = spec_format; + [device unlockForConfiguration]; + } else { + SDL_SetError("Cannot lockForConfiguration"); + goto error; + } + + // Input + input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; + if (!input) { + SDL_SetError("Cannot create AVCaptureDeviceInput"); + goto error; + } + + // Output + output = [[AVCaptureVideoDataOutput alloc] init]; + +#ifdef __MACOS__ + // FIXME this now fail on ios ... but not using anything works... + + // Specify the pixel format + output.videoSettings = + [NSDictionary dictionaryWithObject: + [NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8] + forKey:(id)kCVPixelBufferPixelFormatTypeKey]; +#endif + + _this->hidden->delegate = [[MySampleBufferDelegate alloc] init]; + [_this->hidden->delegate set:_this->hidden]; + + + CMSimpleQueueCreate(kCFAllocatorDefault, 30 /* buffers */, &_this->hidden->frame_queue); + if (_this->hidden->frame_queue == nil) { + goto error; + } + + _this->hidden->queue = dispatch_queue_create("my_queue", NULL); + [output setSampleBufferDelegate:_this->hidden->delegate queue:_this->hidden->queue]; + + + if ([_this->hidden->session canAddInput:input] ){ + [_this->hidden->session addInput:input]; + } else { + SDL_SetError("Cannot add AVCaptureDeviceInput"); + goto error; + } + + if ([_this->hidden->session canAddOutput:output] ){ + [_this->hidden->session addOutput:output]; + } else { + SDL_SetError("Cannot add AVCaptureVideoDataOutput"); + goto error; + } + + [_this->hidden->session commitConfiguration]; + + return 0; + +error: + return -1; +} + +int +GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) +{ + if (spec) { + *spec = _this->spec; + return 0; + } + return -1; +} + +int +StartCapture(SDL_VideoCaptureDevice *_this) +{ + [_this->hidden->session startRunning]; + return 0; +} + +int +StopCapture(SDL_VideoCaptureDevice *_this) +{ + [_this->hidden->session stopRunning]; + return 0; +} + +int +AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + if (CMSimpleQueueGetCount(_this->hidden->frame_queue) > 0) { + int i, numPlanes, planar; + CMSampleBufferRef sampleBuffer; + CVImageBufferRef image; + + sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue); + frame->internal = (void *) sampleBuffer; + frame->timestampNS = SDL_GetTicksNS(); + + i = 0; + image = CMSampleBufferGetImageBuffer(sampleBuffer); + numPlanes = CVPixelBufferGetPlaneCount(image); + planar = CVPixelBufferIsPlanar(image); + +#if 0 + int w = CVPixelBufferGetWidth(image); + int h = CVPixelBufferGetHeight(image); + int sz = CVPixelBufferGetDataSize(image); + int pitch = CVPixelBufferGetBytesPerRow(image); + SDL_Log("buffer planar=%d count:%d %d x %d sz=%d pitch=%d", planar, numPlanes, w, h, sz, pitch); +#endif + + CVPixelBufferLockBaseAddress(image, 0); + + if (planar == 0 && numPlanes == 0) { + frame->pitch[0] = CVPixelBufferGetBytesPerRow(image); + frame->data[0] = CVPixelBufferGetBaseAddress(image); + frame->num_planes = 1; + } else { + for (i = 0; i < numPlanes && i < 3; i++) { + int rowStride = 0; + uint8_t *data = NULL; + frame->num_planes += 1; + + rowStride = CVPixelBufferGetBytesPerRowOfPlane(image, i); + data = CVPixelBufferGetBaseAddressOfPlane(image, i); + frame->data[i] = data; + frame->pitch[i] = rowStride; + } + } + + /* Unlocked when frame is released */ + + } else { + // no frame + SDL_Delay(20); // TODO fix some delay + } + return 0; +} + +int +ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + if (frame->internal){ + CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal; + + CVImageBufferRef image = CMSampleBufferGetImageBuffer(sampleBuffer); + CVPixelBufferUnlockBaseAddress(image, 0); + + CFRelease(sampleBuffer); + } + return 0; +} + +int +GetNumFormats(SDL_VideoCaptureDevice *_this) +{ + AVCaptureDevice *device = get_device_by_name(_this->dev_name); + if (device) { + // LIST FORMATS + NSMutableOrderedSet *array_formats = [NSMutableOrderedSet new]; + NSArray *formats = [device formats]; + for (AVCaptureDeviceFormat *format in formats) { + // NSLog(@"%@", formats); + CMFormatDescriptionRef formatDescription = [format formatDescription]; + //NSLog(@"%@", formatDescription); + FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription); + NSString *str = fourcc_to_nstring(mediaSubType); + [array_formats addObject:str]; + } + return [array_formats count]; + } + return 0; +} + +int +GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) +{ + AVCaptureDevice *device = get_device_by_name(_this->dev_name); + if (device) { + // LIST FORMATS + NSMutableOrderedSet *array_formats = [NSMutableOrderedSet new]; + NSArray *formats = [device formats]; + NSString *str; + + for (AVCaptureDeviceFormat *f in formats) { + FourCharCode mediaSubType; + CMFormatDescriptionRef formatDescription; + + formatDescription = [f formatDescription]; + mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription); + str = fourcc_to_nstring(mediaSubType); + [array_formats addObject:str]; + } + + str = array_formats[index]; + *format = nsfourcc_to_sdlformat(str); + + return 0; + } + return -1; +} + +int +GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) +{ + AVCaptureDevice *device = get_device_by_name(_this->dev_name); + if (device) { + NSString *fmt = sdlformat_to_nsfourcc(format); + int count = 0; + + NSArray *formats = [device formats]; + for (AVCaptureDeviceFormat *f in formats) { + CMFormatDescriptionRef formatDescription = [f formatDescription]; + FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription); + NSString *str = fourcc_to_nstring(mediaSubType); + + if (str == fmt) { + count += 1; + } + } + return count; + } + return 0; +} + +int +GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) +{ + AVCaptureDevice *device = get_device_by_name(_this->dev_name); + if (device) { + NSString *fmt = sdlformat_to_nsfourcc(format); + int count = 0; + + NSArray *formats = [device formats]; + for (AVCaptureDeviceFormat *f in formats) { + CMFormatDescriptionRef formatDescription = [f formatDescription]; + FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription); + NSString *str = fourcc_to_nstring(mediaSubType); + + if (str == fmt) { + if (index == count) { + CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription); + *width = dim.width; + *height = dim.height; + return 0; + } + count += 1; + } + } + } + return -1; +} + +int +GetDeviceName(int index, char *buf, int size) +{ + NSArray *devices = discover_devices(); + if (index < [devices count]) { + AVCaptureDevice *device = devices[index]; + NSString *cameraID = [device localizedName]; + const char *str = [cameraID UTF8String]; + SDL_snprintf(buf, size, "%s", str); + return 0; + } + return -1; +} + +int +GetNumDevices(void) +{ + NSArray *devices = discover_devices(); + return [devices count]; +} + +#endif /* HAVE_COREMEDIA */ + +#endif /* SDL_VIDEO_CAPTURE */ + diff --git a/src/video/SDL_video_capture_c.h b/src/video/SDL_video_capture_c.h new file mode 100644 index 0000000000000..36f2494d6e683 --- /dev/null +++ b/src/video/SDL_video_capture_c.h @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../SDL_internal.h" +#include "../../include/SDL3/SDL_video_capture.h" + +#ifndef SDL_video_capture_c_h_ +#define SDL_video_capture_c_h_ + +/* Initialize the video_capture subsystem */ +int SDL_VideoCaptureInit(void); + +/* Shutdown the video_capture subsystem */ +void SDL_QuitVideoCapture(void); + +#endif /* SDL_video_capture_c_h_ */ diff --git a/src/video/SDL_video_capture_v4l2.c b/src/video/SDL_video_capture_v4l2.c new file mode 100644 index 0000000000000..539cc17112396 --- /dev/null +++ b/src/video/SDL_video_capture_v4l2.c @@ -0,0 +1,965 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_CAPTURE + +#include "SDL3/SDL.h" +#include "SDL3/SDL_video_capture.h" +#include "SDL_sysvideocapture.h" +#include "SDL_video_capture_c.h" +#include "SDL_pixels_c.h" +#include "../thread/SDL_systhread.h" + +#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 + +#if defined(__linux__) && !defined(__ANDROID__) + +enum io_method { + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR +}; + +struct buffer { + void *start; + size_t length; + int available; /* Is available in userspace */ +}; + +struct SDL_PrivateVideoCaptureData +{ + int fd; + enum io_method io; + int nb_buffers; + struct buffer *buffers; + int first_start; + int driver_pitch; +}; + +#include +#include +#include /* low-level i/o */ +#include +#include +#include +#include + +static int +xioctl(int fh, int request, void *arg) +{ + int r; + + do { + r = ioctl(fh, request, arg); + } while (r == -1 && errno == EINTR); + + return r; +} + +/* -1:error 1:frame 0:no frame*/ +static int +acquire_frame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + struct v4l2_buffer buf; + int i; + + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + size_t size = _this->hidden->buffers[0].length; + + switch (io) { + case IO_METHOD_READ: + if (read(fd, _this->hidden->buffers[0].start, size) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + return SDL_SetError("read"); + } + } + + frame->num_planes = 1; + frame->data[0] = _this->hidden->buffers[0].start; + frame->pitch[0] = _this->hidden->driver_pitch; + break; + + case IO_METHOD_MMAP: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + return SDL_SetError("VIDIOC_DQBUF: %d", errno); + } + } + + if ((int)buf.index < 0 || (int)buf.index >= _this->hidden->nb_buffers) { + return SDL_SetError("invalid buffer index"); + } + + frame->num_planes = 1; + frame->data[0] = _this->hidden->buffers[buf.index].start; + frame->pitch[0] = _this->hidden->driver_pitch; + _this->hidden->buffers[buf.index].available = 1; + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("debug mmap: image %d/%d num_planes:%d data[0]=%p", buf.index, _this->hidden->nb_buffers, frame->num_planes, (void*)frame->data[0]); +#endif + break; + + case IO_METHOD_USERPTR: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + + if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + return SDL_SetError("VIDIOC_DQBUF"); + } + } + + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + if (buf.m.userptr == (unsigned long)_this->hidden->buffers[i].start && buf.length == size) { + break; + } + } + + if (i >= _this->hidden->nb_buffers) { + return SDL_SetError("invalid buffer index"); + } + + frame->num_planes = 1; + frame->data[0] = (void*)buf.m.userptr; + frame->pitch[0] = _this->hidden->driver_pitch; + _this->hidden->buffers[i].available = 1; +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("debug userptr: image %d/%d num_planes:%d data[0]=%p", buf.index, _this->hidden->nb_buffers, frame->num_planes, (void*)frame->data[0]); +#endif + break; + } + + return 1; +} + + +int +ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + struct v4l2_buffer buf; + int i; + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + if (frame->num_planes && frame->data[0] == _this->hidden->buffers[i].start) { + break; + } + } + + if (i >= _this->hidden->nb_buffers) { + return SDL_SetError("invalid buffer index"); + } + + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + _this->hidden->buffers[i].available = 0; + break; + + case IO_METHOD_USERPTR: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)frame->data[0]; + buf.length = (int) _this->hidden->buffers[i].length; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + _this->hidden->buffers[i].available = 0; + break; + } + + return 0; +} + + +int +AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + fd_set fds; + struct timeval tv; + int ret; + + int fd = _this->hidden->fd; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* Timeout. */ + tv.tv_sec = 0; + tv.tv_usec = 300 * 1000; + + ret = select(fd + 1, &fds, NULL, NULL, &tv); + + if (ret == -1) { + if (errno == EINTR) { +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("continue .."); +#endif + return 0; + } + return SDL_SetError("select"); + } + + if (ret == 0) { + /* Timeout. Not an error */ + SDL_SetError("timeout select"); + return 0; + } + + ret = acquire_frame(_this, frame); + if (ret < 0) { + return -1; + } + + if (ret == 1){ + frame->timestampNS = SDL_GetTicksNS(); + } else if (ret == 0) { +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("No frame continue: %s", SDL_GetError()); +#endif + } + + /* EAGAIN - continue select loop. */ + return 0; +} + + +int +StopCapture(SDL_VideoCaptureDevice *_this) +{ + enum v4l2_buf_type type; + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(fd, VIDIOC_STREAMOFF, &type) == -1) { + return SDL_SetError("VIDIOC_STREAMOFF"); + } + break; + } + + return 0; +} + +static int +enqueue_buffers(SDL_VideoCaptureDevice *_this) +{ + int i; + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + if (_this->hidden->buffers[i].available == 0) { + struct v4l2_buffer buf; + + SDL_zero(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + } + } + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + if (_this->hidden->buffers[i].available == 0) { + struct v4l2_buffer buf; + + SDL_zero(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)_this->hidden->buffers[i].start; + buf.length = (int) _this->hidden->buffers[i].length; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + } + } + break; + } + return 0; +} + +static int +pre_enqueue_buffers(SDL_VideoCaptureDevice *_this) +{ + struct v4l2_requestbuffers req; + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + { + SDL_zero(req); + req.count = _this->hidden->nb_buffers; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) { + if (errno == EINVAL) { + return SDL_SetError("Does not support memory mapping"); + } else { + return SDL_SetError("VIDIOC_REQBUFS"); + } + } + + if (req.count < 2) { + return SDL_SetError("Insufficient buffer memory"); + } + + _this->hidden->nb_buffers = req.count; + } + break; + + case IO_METHOD_USERPTR: + { + SDL_zero(req); + req.count = _this->hidden->nb_buffers; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) { + if (errno == EINVAL) { + return SDL_SetError("Does not support user pointer i/o"); + } else { + return SDL_SetError("VIDIOC_REQBUFS"); + } + } + } + break; + } + return 0; +} + +int +StartCapture(SDL_VideoCaptureDevice *_this) +{ + enum v4l2_buf_type type; + + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + + + if (_this->hidden->first_start == 0) { + _this->hidden->first_start = 1; + } else { + int old = _this->hidden->nb_buffers; + // TODO mmap; doesn't work with stop->start +#if 1 + /* Can change nb_buffers for mmap */ + if (pre_enqueue_buffers(_this) < 0) { + return -1; + } + if (old != _this->hidden->nb_buffers) { + SDL_SetError("different nb of buffers requested"); + return -1; + } +#endif + _this->hidden->first_start = 1; + } + + if (enqueue_buffers(_this) < 0) { + return -1; + } + + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) { + return SDL_SetError("VIDIOC_STREAMON"); + } + break; + } + + return 0; +} + +static int alloc_buffer_read(SDL_VideoCaptureDevice *_this, size_t buffer_size) +{ + _this->hidden->buffers[0].length = buffer_size; + _this->hidden->buffers[0].start = SDL_calloc(1, buffer_size); + + if (!_this->hidden->buffers[0].start) { + return SDL_OutOfMemory(); + } + return 0; +} + +static int +alloc_buffer_mmap(SDL_VideoCaptureDevice *_this) +{ + int fd = _this->hidden->fd; + int i; + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + struct v4l2_buffer buf; + + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QUERYBUF"); + } + + _this->hidden->buffers[i].length = buf.length; + _this->hidden->buffers[i].start = + mmap(NULL /* start anywhere */, + buf.length, + PROT_READ | PROT_WRITE /* required */, + MAP_SHARED /* recommended */, + fd, buf.m.offset); + + if (MAP_FAILED == _this->hidden->buffers[i].start) { + return SDL_SetError("mmap"); + } + } + return 0; +} + +static int +alloc_buffer_userp(SDL_VideoCaptureDevice *_this, size_t buffer_size) +{ + int i; + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + _this->hidden->buffers[i].length = buffer_size; + _this->hidden->buffers[i].start = SDL_calloc(1, buffer_size); + + if (!_this->hidden->buffers[i].start) { + return SDL_OutOfMemory(); + } + } + return 0; +} + +static Uint32 +format_v4l2_2_sdl(Uint32 fmt) +{ + switch (fmt) { +#define CASE(x, y) case x: return y + CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); + CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); +#undef CASE + default: + SDL_Log("Unknown format V4L2_PIX_FORMAT '%d'", fmt); + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +static Uint32 +format_sdl_2_v4l2(Uint32 fmt) +{ + switch (fmt) { +#define CASE(y, x) case x: return y + CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); + CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); +#undef CASE + default: + return 0; + } +} + +int +GetNumFormats(SDL_VideoCaptureDevice *_this) +{ + int fd = _this->hidden->fd; + int i = 0; + struct v4l2_fmtdesc fmtdesc; + + SDL_zero(fmtdesc); + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + while (ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0) { + fmtdesc.index++; + i++; + } + return i; +} + +int +GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) +{ + int fd = _this->hidden->fd; + struct v4l2_fmtdesc fmtdesc; + + SDL_zero(fmtdesc); + fmtdesc.index = index; + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0) { + *format = format_v4l2_2_sdl(fmtdesc.pixelformat); + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + if (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED) { + SDL_Log("%s format emulated", SDL_GetPixelFormatName(*format)); + } + if (fmtdesc.flags & V4L2_FMT_FLAG_COMPRESSED) { + SDL_Log("%s format compressed", SDL_GetPixelFormatName(*format)); + } +#endif + return 0; + } + + return -1; +} + +int +GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) +{ + int fd = _this->hidden->fd; + int i = 0; + struct v4l2_frmsizeenum frmsizeenum; + + SDL_zero(frmsizeenum); + frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + frmsizeenum.pixel_format = format_sdl_2_v4l2(format); + while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { + frmsizeenum.index++; + if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + i++; + } else if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + i += (1 + (frmsizeenum.stepwise.max_width - frmsizeenum.stepwise.min_width) / frmsizeenum.stepwise.step_width) + * (1 + (frmsizeenum.stepwise.max_height - frmsizeenum.stepwise.min_height) / frmsizeenum.stepwise.step_height); + } else if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { + SDL_SetError("V4L2_FRMSIZE_TYPE_CONTINUOUS not handled"); + } + } + return i; +} + +int +GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) +{ + int fd = _this->hidden->fd; + struct v4l2_frmsizeenum frmsizeenum; + int i = 0; + + SDL_zero(frmsizeenum); + frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + frmsizeenum.pixel_format = format_sdl_2_v4l2(format); + while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { + frmsizeenum.index++; + + if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + if (i == index) { + *width = frmsizeenum.discrete.width; + *height = frmsizeenum.discrete.height; + return 0; + } + i++; + } else if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + unsigned int w; + for (w = frmsizeenum.stepwise.min_width; w <= frmsizeenum.stepwise.max_width; w += frmsizeenum.stepwise.step_width) { + unsigned int h; + for (h = frmsizeenum.stepwise.min_height; h <= frmsizeenum.stepwise.max_height; h += frmsizeenum.stepwise.step_height) { + if (i == index) { + *width = h; + *height = w; + return 0; + } + i++; + } + } + } else if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { + } + } + + return -1; +} + + + +static void +dbg_v4l2_pixelformat(const char *str, int f) { + SDL_Log("%s V4L2_format=%d %c%c%c%c", str, f, + (f >> 0) & 0xff, + (f >> 8) & 0xff, + (f >> 16) & 0xff, + (f >> 24) & 0xff); +} + +int +GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) +{ + struct v4l2_format fmt; + int fd = _this->hidden->fd; + unsigned int min; + + SDL_zero(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + /* Preserve original settings as set by v4l2-ctl for example */ + if (xioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { + return SDL_SetError("Error VIDIOC_G_FMT"); + } + + /* Buggy driver paranoia. */ + min = fmt.fmt.pix.width * 2; + if (fmt.fmt.pix.bytesperline < min) { + fmt.fmt.pix.bytesperline = min; + } + min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; + if (fmt.fmt.pix.sizeimage < min) { + fmt.fmt.pix.sizeimage = min; + } + + //spec->width = fmt.fmt.pix.width; + //spec->height = fmt.fmt.pix.height; + _this->hidden->driver_pitch = fmt.fmt.pix.bytesperline; + //spec->format = format_v4l2_2_sdl(fmt.fmt.pix.pixelformat); + + return 0; +} + +int +InitDevice(SDL_VideoCaptureDevice *_this) +{ + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + + int fd = _this->hidden->fd; + enum io_method io = _this->hidden->io; + int ret = -1; + + /* Select video input, video standard and tune here. */ + SDL_zero(cropcap); + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0) { + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; /* reset to default */ + + if (xioctl(fd, VIDIOC_S_CROP, &crop) == -1) { + switch (errno) { + case EINVAL: + /* Cropping not supported. */ + break; + default: + /* Errors ignored. */ + break; + } + } + } else { + /* Errors ignored. */ + } + + + { + struct v4l2_format fmt; + SDL_zero(fmt); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = _this->spec.width; + fmt.fmt.pix.height = _this->spec.height; + + + fmt.fmt.pix.pixelformat = format_sdl_2_v4l2(_this->spec.format); + // fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("set SDL format %s", SDL_GetPixelFormatName(_this->spec.format)); + dbg_v4l2_pixelformat("set format", fmt.fmt.pix.pixelformat); +#endif + + if (xioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { + return SDL_SetError("Error VIDIOC_S_FMT"); + } + } + + GetDeviceSpec(_this, &_this->spec); + + if (pre_enqueue_buffers(_this) < 0) { + return -1; + } + + { + _this->hidden->buffers = SDL_calloc(_this->hidden->nb_buffers, sizeof(*_this->hidden->buffers)); + if (!_this->hidden->buffers) { + return SDL_OutOfMemory(); + } + } + + { + size_t size, pitch; + SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE); + + switch (io) { + case IO_METHOD_READ: + ret = alloc_buffer_read(_this, size); + break; + + case IO_METHOD_MMAP: + ret = alloc_buffer_mmap(_this); + break; + + case IO_METHOD_USERPTR: + ret = alloc_buffer_userp(_this, size); + break; + } + } + + if (ret < 0) { + return -1; + } + + return 0; +} + +void +CloseDevice(SDL_VideoCaptureDevice *_this) +{ + if (!_this) { + return; + } + + if (_this->hidden) { + if (_this->hidden->buffers) { + int i; + enum io_method io = _this->hidden->io; + + switch (io) { + case IO_METHOD_READ: + SDL_free(_this->hidden->buffers[0].start); + break; + + case IO_METHOD_MMAP: + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + if (munmap(_this->hidden->buffers[i].start, _this->hidden->buffers[i].length) == -1) { + SDL_SetError("munmap"); + } + } + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < _this->hidden->nb_buffers; ++i) { + SDL_free(_this->hidden->buffers[i].start); + } + break; + } + + SDL_free(_this->hidden->buffers); + } + + if (_this->hidden->fd != -1) { + if (close(_this->hidden->fd)) { + SDL_SetError("close video capture device"); + } + } + SDL_free(_this->hidden); + + _this->hidden = NULL; + } +} + + +int +OpenDevice(SDL_VideoCaptureDevice *_this) +{ + struct stat st; + struct v4l2_capability cap; + int fd; + enum io_method io; + + _this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData)); + if (_this->hidden == NULL) { + SDL_OutOfMemory(); + return -1; + } + + _this->hidden->fd = -1; + + if (stat(_this->dev_name, &st) == -1) { + SDL_SetError("Cannot identify '%s': %d, %s", _this->dev_name, errno, strerror(errno)); + return -1; + } + + if (!S_ISCHR(st.st_mode)) { + SDL_SetError("%s is no device", _this->dev_name); + return -1; + } + + fd = open(_this->dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); + if (fd == -1) { + SDL_SetError("Cannot open '%s': %d, %s", _this->dev_name, errno, strerror(errno)); + return -1; + } + + _this->hidden->fd = fd; + _this->hidden->io = IO_METHOD_MMAP; +// _this->hidden->io = IO_METHOD_USERPTR; +// _this->hidden->io = IO_METHOD_READ; +// + if (_this->hidden->io == IO_METHOD_READ) { + _this->hidden->nb_buffers = 1; + } else { + _this->hidden->nb_buffers = 8; /* Number of image as internal buffer, */ + } + io = _this->hidden->io; + + if (xioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { + if (errno == EINVAL) { + return SDL_SetError("%s is no V4L2 device", _this->dev_name); + } else { + return SDL_SetError("Error VIDIOC_QUERYCAP errno=%d device%s is no V4L2 device", errno, _this->dev_name); + } + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + return SDL_SetError("%s is no video capture device", _this->dev_name); + } + +#if 0 + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + SDL_Log("%s is video capture device - single plane", _this->dev_name); + } + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) { + SDL_Log("%s is video capture device - multiple planes", _this->dev_name); + } +#endif + + switch (io) { + case IO_METHOD_READ: + if (!(cap.capabilities & V4L2_CAP_READWRITE)) { + return SDL_SetError("%s does not support read i/o", _this->dev_name); + } + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + return SDL_SetError("%s does not support streaming i/o", _this->dev_name); + } + break; + } + + + + + return 0; +} + + + +int +GetDeviceName(int index, char *buf, int size) { + SDL_snprintf(buf, size, "/dev/video%d", index); + return 0; +} + +int +GetNumDevices(void) { + int num; + for (num = 0; num < 128; num++) { + static char buf[256]; + buf[0] = 0; + buf[255] = 0; + GetDeviceName(num, buf, sizeof (buf)); + SDL_RWops *src = SDL_RWFromFile(buf, "rb"); + if (src == NULL) { + // When file does not exist, an error is set. Clear it. + SDL_ClearError(); + return num; + } + SDL_RWclose(src); + } + return num; +} + +#endif + +#endif /* SDL_VIDEO_CAPTURE */ diff --git a/src/video/android/SDL_android_video_capture.c b/src/video/android/SDL_android_video_capture.c new file mode 100644 index 0000000000000..244d779c2d6b4 --- /dev/null +++ b/src/video/android/SDL_android_video_capture.c @@ -0,0 +1,678 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL3/SDL.h" +#include "SDL3/SDL_video_capture.h" +#include "../SDL_sysvideocapture.h" +#include "../SDL_video_capture_c.h" +#include "../SDL_pixels_c.h" +#include "../../thread/SDL_systhread.h" + +#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 + +#if defined(__ANDROID__) && __ANDROID_API__ >= 24 + +/* + * APP_PLATFORM=android-24 + * minSdkVersion=24 + * + * link with: -lcamera2ndk -lmediandk + * + * AndroidManifest.xml: + * + * + * + * + * Add: #define SDL_VIDEO_CAPTURE 1 + * in: include/build_config/SDL_build_config_android.h + * + * + * Very likely SDL must be build with YUV support (done by default) + * + * https://developer.android.com/reference/android/hardware/camera2/CameraManager + * "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler), + * before configuring sessions on any of the camera devices. * " + */ + +#include +#include +#include +#include + +#include "../../core/android/SDL_android.h" + + +static ACameraManager *cameraMgr = NULL; +static ACameraIdList *cameraIdList = NULL; + +static void +create_cameraMgr(void) +{ + if (cameraMgr == NULL) { + + if (!Android_JNI_RequestPermission("android.permission.CAMERA")) { + SDL_SetError("This app doesn't have CAMERA permission"); + return; + } + + cameraMgr = ACameraManager_create(); + if (cameraMgr == NULL) { + SDL_Log("Error creating ACameraManager"); + } else { + SDL_Log("Create ACameraManager"); + } + } +} + +static void +delete_cameraMgr(void) +{ + if (cameraIdList) { + ACameraManager_deleteCameraIdList(cameraIdList); + cameraIdList = NULL; + } + + if (cameraMgr) { + ACameraManager_delete(cameraMgr); + cameraMgr = NULL; + } +} + +struct SDL_PrivateVideoCaptureData +{ + ACameraDevice *device; + ACameraCaptureSession *session; + ACameraDevice_StateCallbacks dev_callbacks; + ACameraCaptureSession_stateCallbacks capture_callbacks; + ACaptureSessionOutputContainer *sessionOutputContainer; + AImageReader *reader; + int num_formats; + int count_formats[6]; // see format_2_id +}; + + +/**/ +#define FORMAT_SDL SDL_PIXELFORMAT_NV12 + +static int +format_2_id(int fmt) { + switch (fmt) { +#define CASE(x, y) case x: return y + CASE(FORMAT_SDL, 0); + CASE(SDL_PIXELFORMAT_RGB565, 1); + CASE(SDL_PIXELFORMAT_RGB888, 2); + CASE(SDL_PIXELFORMAT_RGBA8888, 3); + CASE(SDL_PIXELFORMAT_RGBX8888, 4); + CASE(SDL_PIXELFORMAT_UNKNOWN, 5); +#undef CASE + default: + return 5; + } +} + +static int +id_2_format(int fmt) { + switch (fmt) { +#define CASE(x, y) case y: return x + CASE(FORMAT_SDL, 0); + CASE(SDL_PIXELFORMAT_RGB565, 1); + CASE(SDL_PIXELFORMAT_RGB888, 2); + CASE(SDL_PIXELFORMAT_RGBA8888, 3); + CASE(SDL_PIXELFORMAT_RGBX8888, 4); + CASE(SDL_PIXELFORMAT_UNKNOWN, 5); +#undef CASE + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +static Uint32 +format_android_2_sdl(Uint32 fmt) +{ + switch (fmt) { +#define CASE(x, y) case x: return y + CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL); + CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565); + CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_RGB888); + CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888); + CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888); + + CASE(AIMAGE_FORMAT_RGBA_FP16, SDL_PIXELFORMAT_UNKNOWN); // 64bits + CASE(AIMAGE_FORMAT_RAW_PRIVATE, SDL_PIXELFORMAT_UNKNOWN); + CASE(AIMAGE_FORMAT_JPEG, SDL_PIXELFORMAT_UNKNOWN); +#undef CASE + default: + SDL_Log("Unknown format AIMAGE_FORMAT '%d'", fmt); + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +static Uint32 +format_sdl_2_android(Uint32 fmt) +{ + switch (fmt) { +#define CASE(x, y) case y: return x + CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL); + CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565); + CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_RGB888); + CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888); + CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888); +#undef CASE + default: + return 0; + } +} + + +static void +onDisconnected(void *context, ACameraDevice *device) +{ + // SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context; + SDL_Log("CB onDisconnected"); +} + +static void +onError(void *context, ACameraDevice *device, int error) +{ + // SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context; + SDL_Log("CB onError"); +} + + +static void +onClosed(void* context, ACameraCaptureSession *session) +{ + // SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context; + SDL_Log("CB onClosed"); +} + +static void +onReady(void* context, ACameraCaptureSession *session) +{ + // SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context; + SDL_Log("CB onReady"); +} + +static void +onActive(void* context, ACameraCaptureSession *session) +{ + // SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context; + SDL_Log("CB onActive"); +} + +int +OpenDevice(SDL_VideoCaptureDevice *_this) +{ + camera_status_t res; + + /* Cannot open a second camera, while the first one is opened. + * If you want to play several camera, they must all be opened first, then played. + * + * https://developer.android.com/reference/android/hardware/camera2/CameraManager + * "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler), + * before configuring sessions on any of the camera devices. * " + * + */ + if (check_device_playing()) { + return SDL_SetError("A camera is already playing"); + } + + _this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData)); + if (_this->hidden == NULL) { + return SDL_OutOfMemory(); + } + + create_cameraMgr(); + + _this->hidden->dev_callbacks.context = (void *) _this; + _this->hidden->dev_callbacks.onDisconnected = onDisconnected; + _this->hidden->dev_callbacks.onError = onError; + + res = ACameraManager_openCamera(cameraMgr, _this->dev_name, &_this->hidden->dev_callbacks, &_this->hidden->device); + if (res != ACAMERA_OK) { + return SDL_SetError("Failed to open camera"); + } + + return 0; +} + +void +CloseDevice(SDL_VideoCaptureDevice *_this) +{ + if (_this && _this->hidden) { + if (_this->hidden->session) { + ACameraCaptureSession_close(_this->hidden->session); + } + + if (_this->hidden->sessionOutputContainer) { + ACaptureSessionOutputContainer_free(_this->hidden->sessionOutputContainer); + } + + if (_this->hidden->reader) { + AImageReader_delete(_this->hidden->reader); + } + + if (_this->hidden->device) { + ACameraDevice_close(_this->hidden->device); + } + + SDL_free(_this->hidden); + + _this->hidden = NULL; + } + + if (check_all_device_closed()) { + delete_cameraMgr(); + } +} + +int +InitDevice(SDL_VideoCaptureDevice *_this) +{ + size_t size, pitch; + SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE); + SDL_Log("Buffer size: %d x %d", _this->spec.width, _this->spec.height); + return 0; +} + +int +GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) +{ + if (spec) { + *spec = _this->spec; + return 0; + } + return -1; +} + +int +StartCapture(SDL_VideoCaptureDevice *_this) +{ + camera_status_t res; + media_status_t res2; + ANativeWindow *window = NULL; + ACaptureSessionOutput *sessionOutput; + ACameraOutputTarget *outputTarget; + ACaptureRequest *request; + + res2 = AImageReader_new(_this->spec.width, _this->spec.height, format_sdl_2_android(_this->spec.format), 10 /* nb buffers */, &_this->hidden->reader); + if (res2 != AMEDIA_OK) { + SDL_SetError("Error AImageReader_new"); + goto error; + } + res2 = AImageReader_getWindow(_this->hidden->reader, &window); + if (res2 != AMEDIA_OK) { + SDL_SetError("Error AImageReader_new"); + goto error; + + } + + + res = ACaptureSessionOutput_create(window, &sessionOutput); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACaptureSessionOutput_create"); + goto error; + } + res = ACaptureSessionOutputContainer_create(&_this->hidden->sessionOutputContainer); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACaptureSessionOutputContainer_create"); + goto error; + } + res = ACaptureSessionOutputContainer_add(_this->hidden->sessionOutputContainer, sessionOutput); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACaptureSessionOutputContainer_add"); + goto error; + } + + + res = ACameraOutputTarget_create(window, &outputTarget); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACameraOutputTarget_create"); + goto error; + } + + + res = ACameraDevice_createCaptureRequest(_this->hidden->device, TEMPLATE_RECORD, &request); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACameraDevice_createCaptureRequest"); + goto error; + } + + res = ACaptureRequest_addTarget(request, outputTarget); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACaptureRequest_addTarget"); + goto error; + } + + + _this->hidden->capture_callbacks.context = (void *) _this; + _this->hidden->capture_callbacks.onClosed = onClosed; + _this->hidden->capture_callbacks.onReady = onReady; + _this->hidden->capture_callbacks.onActive = onActive; + + res = ACameraDevice_createCaptureSession(_this->hidden->device, + _this->hidden->sessionOutputContainer, + &_this->hidden->capture_callbacks, + &_this->hidden->session); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACameraDevice_createCaptureSession"); + goto error; + } + + res = ACameraCaptureSession_setRepeatingRequest(_this->hidden->session, NULL, 1, &request, NULL); + if (res != ACAMERA_OK) { + SDL_SetError("Error ACameraDevice_createCaptureSession"); + goto error; + } + + return 0; + +error: + return -1; +} + +int +StopCapture(SDL_VideoCaptureDevice *_this) +{ + ACameraCaptureSession_close(_this->hidden->session); + _this->hidden->session = NULL; + return 0; +} + +int +AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + media_status_t res; + AImage *image; + res = AImageReader_acquireNextImage(_this->hidden->reader, &image); + /* We could also use this one: + res = AImageReader_acquireLatestImage(_this->hidden->reader, &image); + */ + if (res == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE ) { + + SDL_Delay(20); // TODO fix some delay +#if DEBUG_VIDEO_CAPTURE_CAPTURE +// SDL_Log("AImageReader_acquireNextImage: AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE"); +#endif + return 0; + } else if (res == AMEDIA_OK ) { + int i = 0; + int32_t numPlanes = 0; + AImage_getNumberOfPlanes(image, &numPlanes); + + frame->timestampNS = SDL_GetTicksNS(); + + for (i = 0; i < numPlanes && i < 3; i++) { + int dataLength = 0; + int rowStride = 0; + uint8_t *data = NULL; + frame->num_planes += 1; + AImage_getPlaneRowStride(image, i, &rowStride); + res = AImage_getPlaneData(image, i, &data, &dataLength); + if (res == AMEDIA_OK) { + frame->data[i] = data; + frame->pitch[i] = rowStride; + } + } + + if (frame->num_planes == 3) { + /* plane 2 and 3 are interleaved NV12. SDL only takes two planes for this format */ + int pixelStride = 0; + AImage_getPlanePixelStride(image, 1, &pixelStride); + if (pixelStride == 2) { + frame->num_planes -= 1; + } + } + + frame->internal = (void*)image; + return 0; + } else if (res == AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED) { + SDL_SetError("AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED"); + } else { + SDL_SetError("AImageReader_acquireNextImage: %d", res); + } + + return -1; +} + +int +ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) +{ + if (frame->internal){ + AImage_delete((AImage *)frame->internal); + } + return 0; +} + +int +GetNumFormats(SDL_VideoCaptureDevice *_this) +{ + camera_status_t res; + int i; + int unknown = 0; + ACameraMetadata *metadata; + ACameraMetadata_const_entry entry; + + if (_this->hidden->num_formats != 0) { + return _this->hidden->num_formats; + } + + res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata); + if (res != ACAMERA_OK) { + return -1; + } + + res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry); + if (res != ACAMERA_OK) { + return -1; + } + + SDL_Log("got entry ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS"); + + for (i = 0; i < entry.count; i += 4) { + int32_t format = entry.data.i32[i + 0]; + int32_t type = entry.data.i32[i + 3]; + Uint32 fmt; + + if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) { + continue; + } + + fmt = format_android_2_sdl(format); + _this->hidden->count_formats[format_2_id(fmt)] += 1; + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + if (fmt != SDL_PIXELFORMAT_UNKNOWN) { + int w = entry.data.i32[i + 1]; + int h = entry.data.i32[i + 2]; + SDL_Log("Got format android 0x%08x -> %s %d x %d", format, SDL_GetPixelFormatName(fmt), w, h); + } else { + unknown += 1; + } +#endif + } + +#if DEBUG_VIDEO_CAPTURE_CAPTURE + if (unknown) { + SDL_Log("Got unknown android"); + } +#endif + + + if ( _this->hidden->count_formats[0]) _this->hidden->num_formats += 1; + if ( _this->hidden->count_formats[1]) _this->hidden->num_formats += 1; + if ( _this->hidden->count_formats[2]) _this->hidden->num_formats += 1; + if ( _this->hidden->count_formats[3]) _this->hidden->num_formats += 1; + if ( _this->hidden->count_formats[4]) _this->hidden->num_formats += 1; + if ( _this->hidden->count_formats[5]) _this->hidden->num_formats += 1; + + return _this->hidden->num_formats; +} + +int +GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) +{ + int i; + int i2 = 0; + + if (_this->hidden->num_formats == 0) { + GetNumFormats(_this); + } + + if (index < 0 || index >= _this->hidden->num_formats) { + return -1; + } + + for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) { + if (_this->hidden->count_formats[i] == 0) { + continue; + } + + if (i2 == index) { + *format = id_2_format(i); + } + + i2++; + + } + return 0; +} + +int +GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) +{ + int i, i2 = 0, index; + if (_this->hidden->num_formats == 0) { + GetNumFormats(_this); + } + + index = format_2_id(format); + + for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) { + if (_this->hidden->count_formats[i] == 0) { + continue; + } + + if (i2 == index) { + /* number of resolution for this format */ + return _this->hidden->count_formats[i]; + } + + i2++; + } + + return -1; +} + +int +GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) +{ + camera_status_t res; + int i, i2 = 0; + ACameraMetadata *metadata; + ACameraMetadata_const_entry entry; + + if (_this->hidden->num_formats == 0) { + GetNumFormats(_this); + } + + res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata); + if (res != ACAMERA_OK) { + return -1; + } + + res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry); + if (res != ACAMERA_OK) { + return -1; + } + + for (i = 0; i < entry.count; i += 4) { + int32_t f = entry.data.i32[i + 0]; + int w = entry.data.i32[i + 1]; + int h = entry.data.i32[i + 2]; + int32_t type = entry.data.i32[i + 3]; + Uint32 fmt; + + if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) { + continue; + } + + + fmt = format_android_2_sdl(f); + if (fmt != format) { + continue; + } + + if (i2 == index) { + *width = w; + *height = h; + return 0; + } + + i2++; + } + return -1; +} + +int +GetDeviceName(int index, char *buf, int size) +{ + create_cameraMgr(); + + if (cameraIdList == NULL) { + GetNumDevices(); + } + + if (cameraIdList) { + if (index >= 0 && index < cameraIdList->numCameras) { + SDL_snprintf(buf, size, "%s", cameraIdList->cameraIds[index]); + return 0; + } + } + + return -1; +} + +int +GetNumDevices(void) +{ + camera_status_t res; + create_cameraMgr(); + + if (cameraIdList) { + ACameraManager_deleteCameraIdList(cameraIdList); + cameraIdList = NULL; + } + + res = ACameraManager_getCameraIdList(cameraMgr, &cameraIdList); + + if (res == ACAMERA_OK) { + if (cameraIdList) { + return cameraIdList->numCameras; + } + } + return -1; +} + +#endif + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d7ff59047305..bac37027a2cbd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -358,6 +358,8 @@ add_sdl_test_executable(teststreaming NEEDS_RESOURCES TESTUTILS SOURCES teststre add_sdl_test_executable(testtimer NONINTERACTIVE NONINTERACTIVE_ARGS --no-interactive NONINTERACTIVE_TIMEOUT 60 SOURCES testtimer.c) add_sdl_test_executable(testurl SOURCES testurl.c) add_sdl_test_executable(testver NONINTERACTIVE SOURCES testver.c) +add_sdl_test_executable(testvideocapture SOURCES testvideocapture.c) +add_sdl_test_executable(testvideocaptureminimal SOURCES testvideocaptureminimal.c) add_sdl_test_executable(testviewport NEEDS_RESOURCES TESTUTILS SOURCES testviewport.c) add_sdl_test_executable(testwm SOURCES testwm.c) add_sdl_test_executable(testyuv NONINTERACTIVE NONINTERACTIVE_ARGS "--automated" NEEDS_RESOURCES TESTUTILS SOURCES testyuv.c testyuv_cvt.c) diff --git a/test/testvideocapture.c b/test/testvideocapture.c new file mode 100644 index 0000000000000..aff7642b1e3c4 --- /dev/null +++ b/test/testvideocapture.c @@ -0,0 +1,770 @@ +/* + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ +#include "SDL3/SDL_main.h" +#include "SDL3/SDL.h" +#include "SDL3/SDL_test.h" +#include "SDL3/SDL_video_capture.h" +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +static const char *usage = "\ + \n\ + =========================================================================\n\ + \n\ +Use keyboards:\n\ + o: open first video capture device. (close previously opened)\n\ + l: switch to, and list video capture devices\n\ + i: information about status (Init, Playing, Stopped)\n\ + f: formats and resolutions available\n\ + s: start / stop capture\n\ + h: display help\n\ + esc: exit \n\ + \n\ + =========================================================================\n\ + \n\ +"; + +typedef struct { + Uint64 next_check; + int frame_counter; + int check_delay; + double last_fps; +} measure_fps_t; + +static void +update_fps(measure_fps_t *m) +{ + Uint64 now = SDL_GetTicks(); + Uint64 deadline; + m->frame_counter++; + if (m->check_delay == 0) { + m->check_delay = 1500; + } + deadline = m->next_check; + if (now >= deadline) { + /* Print out some timing information */ + const Uint64 then = m->next_check - m->check_delay; + m->last_fps = ((double) m->frame_counter * 1000) / (now - then); + m->next_check = now + m->check_delay; + m->frame_counter = 0; + } +} + +#if defined(__linux__) && !defined(__ANDROID__) +static void load_average(float *val) +{ + FILE *fp = 0; + char line[1024]; + fp = fopen("/proc/loadavg", "rt"); + if (fp) { + char *s = fgets(line, sizeof(line), fp); + if (s) { + SDL_sscanf(s, "%f", val); + } + fclose(fp); + } +} +#endif + + +struct data_capture_t { + SDL_VideoCaptureDevice *device; + SDL_VideoCaptureSpec obtained; + int stopped; + SDL_VideoCaptureFrame frame_current; + measure_fps_t fps_capture; + SDL_Texture *texture; + int texture_updated; +}; + +#define SAVE_CAPTURE_STATE(x) \ + data_capture_tab[(x)].device = device; \ + data_capture_tab[(x)].obtained = obtained; \ + data_capture_tab[(x)].stopped = stopped; \ + data_capture_tab[(x)].frame_current = frame_current; \ + data_capture_tab[(x)].fps_capture = fps_capture; \ + data_capture_tab[(x)].texture = texture; \ + data_capture_tab[(x)].texture_updated = texture_updated; \ + + +#define RESTORE_CAPTURE_STATE(x) \ + device = data_capture_tab[(x)].device; \ + obtained = data_capture_tab[(x)].obtained; \ + stopped = data_capture_tab[(x)].stopped; \ + frame_current = data_capture_tab[(x)].frame_current; \ + fps_capture = data_capture_tab[(x)].fps_capture; \ + texture = data_capture_tab[(x)].texture; \ + texture_updated = data_capture_tab[(x)].texture_updated; \ + + + + + +static SDL_VideoCaptureDeviceID get_instance_id(int index) { + int ret = 0; + int num = 0; + SDL_VideoCaptureDeviceID *devices; + devices = SDL_GetVideoCaptureDevices(&num); + if (devices) { + if (index >= 0 && index < num) { + ret = devices[index]; + } + SDL_free(devices); + } + + if (ret == 0) { + SDL_Log("invalid index"); + } + + return ret; +} + + + +int main(int argc, char **argv) +{ + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Event evt; + int quit = 0; + + SDLTest_CommonState *state; + + int current_dev = 0; + measure_fps_t fps_main; + + + SDL_FRect r_playstop = { 50, 50, 120, 50 }; + SDL_FRect r_close = { 50 + (120 + 50) * 1, 50, 120, 50 }; + + SDL_FRect r_open = { 50 + (120 + 50) * 2, 50, 120, 50 }; + + SDL_FRect r_format = { 50 + (120 + 50) * 3, 50, 120, 50 }; + SDL_FRect r_listdev = { 50 + (120 + 50) * 4, 50, 120, 50 }; + + SDL_VideoCaptureDevice *device; + SDL_VideoCaptureSpec obtained; + int stopped = 0; + SDL_VideoCaptureFrame frame_current; + measure_fps_t fps_capture; + SDL_Texture *texture = NULL; + int texture_updated = 0; + + struct data_capture_t data_capture_tab[16]; + const int data_capture_tab_size = SDL_arraysize(data_capture_tab); + + SDL_zero(fps_main); + SDL_zero(fps_capture); + SDL_zero(frame_current); + SDL_zeroa(data_capture_tab); + + /* Set 0 to disable TouchEvent to be duplicated as MouseEvent with SDL_TOUCH_MOUSEID */ + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + /* Set 0 to disable MouseEvent to be duplicated as TouchEvent with SDL_MOUSE_TOUCHID */ + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); + + { + int i; + for (i = 0; i < data_capture_tab_size; i++) { + data_capture_tab[i].device = NULL; + } + } + + /* Initialize test framework */ + state = SDLTest_CommonCreateState(argv, 0); + if (state == NULL) { + return 1; + } + + /* Enable standard application logging */ + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + /* Parse commandline */ + { + int i; + for (i = 1; i < argc;) { + int consumed; + + consumed = SDLTest_CommonArg(state, i); + if (consumed <= 0) { + static const char *options[] = {NULL}; + SDLTest_CommonLogUsage(state, argv[0], options); + SDLTest_CommonDestroyState(state); + return 1; + } + + i += consumed; + } + } + + SDL_Log("%s", usage); + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); + return 1; + } + + window = SDL_CreateWindow("Local Video", 1000, 800, 0); + if (window == NULL) { + SDL_Log("Couldn't create window: %s", SDL_GetError()); + return 1; + } + + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + + renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (renderer == NULL) { + /* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */ + return 1; + } + + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_INFO); + + device = SDL_OpenVideoCapture(0); + + if (!device) { + SDL_Log("Error SDL_OpenVideoCapture: %s", SDL_GetError()); + } + + { + /* List formats */ + int i, num = SDL_GetNumVideoCaptureFormats(device); + for (i = 0; i < num; i++) { + Uint32 format; + SDL_GetVideoCaptureFormat(device, i, &format); + SDL_Log("format %d/%d: %s", i, num, SDL_GetPixelFormatName(format)); + { + int w, h; + int j, num2 = SDL_GetNumVideoCaptureFrameSizes(device, format); + for (j = 0; j < num2; j++) { + SDL_GetVideoCaptureFrameSize(device, format, j, &w, &h); + SDL_Log(" framesizes %d/%d : %d x %d", j, num2, w, h); + } + } + } + } + + /* Set Spec */ + { + int ret; + /* forced_format */ + SDL_VideoCaptureSpec desired; + SDL_zero(desired); + desired.width = 640 * 2; + desired.height = 360 * 2; + desired.format = SDL_PIXELFORMAT_NV12; + ret = SDL_SetVideoCaptureSpec(device, &desired, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE); + + if (ret < 0) { + SDL_SetVideoCaptureSpec(device, NULL, &obtained, 0); + } + } + + SDL_Log("Open capture video device. Obtained spec: size=%d x %d format=%s", + obtained.width, obtained.height, SDL_GetPixelFormatName(obtained.format)); + + { + SDL_VideoCaptureSpec spec; + if (SDL_GetVideoCaptureSpec(device, &spec) == 0) { + SDL_Log("Read spec: size=%d x %d format=%s", + spec.width, spec.height, SDL_GetPixelFormatName(spec.format)); + } else { + SDL_Log("Error read spec: %s", SDL_GetError()); + } + } + + if (SDL_StartVideoCapture(device) < 0) { + SDL_Log("error SDL_StartVideoCapture(): %s", SDL_GetError()); + } + + while (!quit) { + + SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255); + SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, 0x33, 0x33, 0x33, 255); + + SDL_RenderFillRect(renderer, &r_playstop); + SDL_RenderFillRect(renderer, &r_close); + SDL_RenderFillRect(renderer, &r_open); + SDL_RenderFillRect(renderer, &r_format); + SDL_RenderFillRect(renderer, &r_listdev); + + SDL_SetRenderDrawColor(renderer, 0xcc, 0xcc, 0xcc, 255); + + SDLTest_DrawString(renderer, r_playstop.x + 5, r_playstop.y + 5, "play stop"); + SDLTest_DrawString(renderer, r_close.x + 5, r_close.y + 5, "close"); + SDLTest_DrawString(renderer, r_open.x + 5, r_open.y + 5, "open dev"); + SDLTest_DrawString(renderer, r_format.x + 5, r_format.y + 5, "formats"); + + { + char buf[256]; + SDL_snprintf(buf, 256, "device %d", current_dev); + SDLTest_DrawString(renderer, r_listdev.x + 5, r_listdev.y + 5, buf); + } + + while (SDL_PollEvent(&evt)) { + SDL_FRect *r = NULL; + SDL_FPoint pt; + int sym = 0; + + pt.x = 0; + pt.y = 0; + + SDL_ConvertEventToRenderCoordinates(renderer, &evt); + + switch (evt.type) + { + case SDL_EVENT_KEY_DOWN: + { + sym = evt.key.keysym.sym; + break; + } + case SDL_EVENT_QUIT: + { + quit = 1; + SDL_Log("Ctlr+C : Quit!"); + } + break; + + case SDL_EVENT_FINGER_DOWN: + { + pt.x = evt.tfinger.x; + pt.y = evt.tfinger.y; + } + break; + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + { + pt.x = evt.button.x; + pt.y = evt.button.y; + } + break; + } + + if (pt.x != 0 && pt.y != 0) { + if (SDL_PointInRectFloat(&pt, &r_playstop)) { + r = &r_playstop; + sym = SDLK_s; + } + if (SDL_PointInRectFloat(&pt, &r_close)) { + r = &r_close; + sym = SDLK_c; + } + if (SDL_PointInRectFloat(&pt, &r_open)) { + r = &r_open; + sym = SDLK_o; + } + + if (SDL_PointInRectFloat(&pt, &r_format)) { + r = &r_format; + sym = SDLK_f; + } + if (SDL_PointInRectFloat(&pt, &r_listdev)) { + r = &r_listdev; + sym = SDLK_l; + } + } + + + if (r) { + SDL_SetRenderDrawColor(renderer, 0x33, 0, 0, 255); + SDL_RenderFillRect(renderer, r); + } + + + if (sym == SDLK_c) { + if (frame_current.num_planes) { + SDL_ReleaseVideoCaptureFrame(device, &frame_current); + } + SDL_CloseVideoCapture(device); + device = NULL; + SDL_Log("Close"); + } + + if (sym == SDLK_o) { + if (device) { + SDL_Log("Close previous .."); + if (frame_current.num_planes) { + SDL_ReleaseVideoCaptureFrame(device, &frame_current); + } + SDL_CloseVideoCapture(device); + } + + texture_updated = 0; + + SDL_ClearError(); + + SDL_Log("Try to open:%s", SDL_GetVideoCaptureDeviceName(get_instance_id(current_dev))); + + obtained.width = 640 * 2; + obtained.height = 360 * 2; + device = SDL_OpenVideoCaptureWithSpec(get_instance_id(current_dev), &obtained, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE); + + /* spec may have changed because of re-open */ + if (texture) { + SDL_DestroyTexture(texture); + texture = NULL; + } + + SDL_Log("Open device:%p %s", (void*)device, SDL_GetError()); + stopped = 0; + } + + if (sym == SDLK_l) { + int num = 0; + SDL_VideoCaptureDeviceID *devices; + int i; + devices = SDL_GetVideoCaptureDevices(&num); + + SDL_Log("Num devices : %d", num); + for (i = 0; i < num; i++) { + SDL_Log("Device %d/%d : %s", i, num, SDL_GetVideoCaptureDeviceName(devices[i])); + } + SDL_free(devices); + + SAVE_CAPTURE_STATE(current_dev); + + current_dev += 1; + if (current_dev == num || current_dev >= (int) SDL_arraysize(data_capture_tab)) { + current_dev = 0; + } + + RESTORE_CAPTURE_STATE(current_dev); + SDL_Log("--> select dev %d / %d", current_dev, num); + } + + if (sym == SDLK_i) { + SDL_VideoCaptureStatus status = SDL_GetVideoCaptureStatus(device); + if (status == SDL_VIDEO_CAPTURE_STOPPED) { SDL_Log("STOPPED"); } + if (status == SDL_VIDEO_CAPTURE_PLAYING) { SDL_Log("PLAYING"); } + if (status == SDL_VIDEO_CAPTURE_INIT) { SDL_Log("INIT"); } + } + + if (sym == SDLK_s) { + if (stopped) { + SDL_Log("Stop"); + SDL_StopVideoCapture(device); + } else { + SDL_Log("Start"); + SDL_StartVideoCapture(device); + } + stopped = !stopped; + } + + if (sym == SDLK_f) { + SDL_Log("List formats"); + + if (!device) { + device = SDL_OpenVideoCapture(get_instance_id(current_dev)); + } + + /* List formats */ + { + int i, num = SDL_GetNumVideoCaptureFormats(device); + for (i = 0; i < num; i++) { + Uint32 format; + SDL_GetVideoCaptureFormat(device, i, &format); + SDL_Log("format %d/%d : %s", i, num, SDL_GetPixelFormatName(format)); + { + int w, h; + int j, num2 = SDL_GetNumVideoCaptureFrameSizes(device, format); + for (j = 0; j < num2; j++) { + SDL_GetVideoCaptureFrameSize(device, format, j, &w, &h); + SDL_Log(" framesizes %d/%d : %d x %d", j, num2, w, h); + } + } + } + } + } + if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) { + quit = 1; + SDL_Log("Key : Escape!"); + } + + if (sym == SDLK_h || sym == SDLK_F1) { + SDL_Log("%s", usage); + } + } + + + SAVE_CAPTURE_STATE(current_dev); + + { + int i, n = SDL_arraysize(data_capture_tab); + for (i = 0; i < n; i++) { + RESTORE_CAPTURE_STATE(i); + + if (!device) { + /* device has been closed */ + frame_current.num_planes = 0; + texture_updated = 0; + } else { + int ret; + SDL_VideoCaptureFrame frame_next; + SDL_zero(frame_next); + + ret = SDL_AcquireVideoCaptureFrame(device, &frame_next); + if (ret < 0) { + SDL_Log("dev[%d] err SDL_AcquireVideoCaptureFrame: %s", i, SDL_GetError()); + } +#if 1 + if (frame_next.num_planes) { + SDL_Log("dev[%d] frame: %p at %" SDL_PRIu64, i, (void*)frame_next.data[0], frame_next.timestampNS); + } +#endif + + if (frame_next.num_planes) { + + update_fps(&fps_capture); + + if (frame_current.num_planes) { + ret = SDL_ReleaseVideoCaptureFrame(device, &frame_current); + if (ret < 0) { + SDL_Log("dev[%d] err SDL_ReleaseVideoCaptureFrame: %s", i, SDL_GetError()); + } + } + frame_current = frame_next; + texture_updated = 0; + } + } + + SAVE_CAPTURE_STATE(i); + } + } + + + RESTORE_CAPTURE_STATE(current_dev); + + + + /* Moving square */ + SDL_SetRenderDrawColor(renderer, 0, 0xff, 0, 255); + { + SDL_FRect r; + static float x = 0; + x += 10; + if (x > 1000) { + x = 0; + } + r.x = x; + r.y = 100; + r.w = r.h = 10; + SDL_RenderFillRect(renderer, &r); + } + + SDL_SetRenderDrawColor(renderer, 0x33, 0x33, 0x33, 255); + + + SAVE_CAPTURE_STATE(current_dev); + + { + int i, n = SDL_arraysize(data_capture_tab); + for (i = 0; i < n; i++) { + RESTORE_CAPTURE_STATE(i); + + /* Update SDL_Texture with last video frame (only once per new frame) */ + if (frame_current.num_planes && texture_updated == 0) { + + /* Create texture with appropriate format (for DMABUF or not) */ + if (texture == NULL) { + Uint32 format = obtained.format; + texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, obtained.width, obtained.height); + if (texture == NULL) { + SDL_Log("Couldn't create texture: %s", SDL_GetError()); + return 1; + } + } + + { + /* Use software data */ + if (frame_current.num_planes == 1) { + SDL_UpdateTexture(texture, NULL, + frame_current.data[0], frame_current.pitch[0]); + } else if (frame_current.num_planes == 2) { + SDL_UpdateNVTexture(texture, NULL, + frame_current.data[0], frame_current.pitch[0], + frame_current.data[1], frame_current.pitch[1]); + } else if (frame_current.num_planes == 3) { + SDL_UpdateYUVTexture(texture, NULL, frame_current.data[0], frame_current.pitch[0], + frame_current.data[1], frame_current.pitch[1], + frame_current.data[2], frame_current.pitch[2]); + } + texture_updated = 1; + } + } + + SAVE_CAPTURE_STATE(i); + } + } + + + RESTORE_CAPTURE_STATE(current_dev); + + { + int i, n = SDL_arraysize(data_capture_tab); + int win_w, win_h; + int total_texture_updated = 0; + int curr_texture_updated = 0; + for (i = 0; i < n; i++) { + if (data_capture_tab[i].texture_updated) { + total_texture_updated += 1; + } + } + + SDL_GetRenderOutputSize(renderer, &win_w, &win_h); + + + for (i = 0; i < n; i++) { + RESTORE_CAPTURE_STATE(i); + /* RenderCopy the SDL_Texture */ + if (texture_updated == 1) { + /* Scale texture to fit the screen */ + + int tw, th; + int w; + SDL_FRect d; + SDL_QueryTexture(texture, NULL, NULL, &tw, &th); + + w = win_w / total_texture_updated; + + if (tw > w - 20) { + float scale = (float) (w - 20) / (float) tw; + tw = w - 20; + th = (int)((float) th * scale); + } + d.x = (float)(10 + curr_texture_updated * w); + d.y = (float)(win_h - th); + d.w = (float)tw; + d.h = (float)(th - 10); + SDL_RenderTexture(renderer, texture, NULL, &d); + + curr_texture_updated += 1; + } + } + + } + + RESTORE_CAPTURE_STATE(current_dev); + + + /* display status and FPS */ + if (!device) { +#ifdef __IOS__ + const float x_offset = 500; +#else + const float x_offset = 0; +#endif + char buf[256]; + SDL_snprintf(buf, 256, "Device %d (%s) is not opened", current_dev, SDL_GetVideoCaptureDeviceName(get_instance_id(current_dev))); + SDLTest_DrawString(renderer, x_offset + 10, 10, buf); + } else { +#ifdef __IOS__ + const float x_offset = 500; +#else + const float x_offset = 0; +#endif + const char *status = "no status"; + char buf[256]; + + if (device) { + SDL_VideoCaptureStatus s = SDL_GetVideoCaptureStatus(device); + if (s == SDL_VIDEO_CAPTURE_INIT) { + status = "init"; + } else if (s == SDL_VIDEO_CAPTURE_PLAYING) { + status = "playing"; + } else if (s == SDL_VIDEO_CAPTURE_STOPPED) { + status = "stopped"; + } else if (s == SDL_VIDEO_CAPTURE_FAIL) { + status = "failed"; + } + + } + + /* capture device, capture fps, capture status */ + SDL_snprintf(buf, 256, "Device %d - %2.2f fps - %s", current_dev, fps_capture.last_fps, status); + SDLTest_DrawString(renderer, x_offset + 10, 10, buf); + + /* capture spec */ + SDL_snprintf(buf, sizeof(buf), "%d x %d %s", obtained.width, obtained.height, SDL_GetPixelFormatName(obtained.format)); + SDLTest_DrawString(renderer, x_offset + 10, 20, buf); + + /* video fps */ + SDL_snprintf(buf, sizeof(buf), "%2.2f fps", fps_main.last_fps); + SDLTest_DrawString(renderer, x_offset + 10, 30, buf); + + } + + /* display last error */ + { + SDLTest_DrawString(renderer, 400, 10, SDL_GetError()); + } + + /* display load average */ +#if defined(__linux__) && !defined(__ANDROID__) + { + float val = 0.0f; + char buf[128]; + load_average(&val); + if (val != 0.0f) { + SDL_snprintf(buf, sizeof(buf), "load avg %2.2f percent", val); + SDLTest_DrawString(renderer, 800, 10, buf); + } + } +#endif + + + SDL_Delay(20); + SDL_RenderPresent(renderer); + + update_fps(&fps_main); + + } + + + + SAVE_CAPTURE_STATE(current_dev); + + { + int i, n = SDL_arraysize(data_capture_tab); + for (i = 0; i < n; i++) { + RESTORE_CAPTURE_STATE(i); + + if (device) { + if (SDL_StopVideoCapture(device) < 0) { + SDL_Log("error SDL_StopVideoCapture(): %s", SDL_GetError()); + } + if (frame_current.num_planes) { + SDL_ReleaseVideoCaptureFrame(device, &frame_current); + } + SDL_CloseVideoCapture(device); + } + + if (texture) { + SDL_DestroyTexture(texture); + } + } + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + + SDL_Quit(); + + SDLTest_CommonDestroyState(state); + + return 0; +} diff --git a/test/testvideocaptureminimal.c b/test/testvideocaptureminimal.c new file mode 100644 index 0000000000000..870dcab66037a --- /dev/null +++ b/test/testvideocaptureminimal.c @@ -0,0 +1,206 @@ +/* + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ +#include "SDL3/SDL_main.h" +#include "SDL3/SDL.h" +#include "SDL3/SDL_test.h" +#include "SDL3/SDL_video_capture.h" +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +int main(int argc, char **argv) +{ + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Event evt; + int quit = 0; + SDLTest_CommonState *state = NULL; + + SDL_VideoCaptureDevice *device = NULL; + SDL_VideoCaptureSpec obtained; + + SDL_VideoCaptureFrame frame_current; + SDL_Texture *texture = NULL; + int texture_updated = 0; + + SDL_zero(evt); + SDL_zero(obtained); + SDL_zero(frame_current); + + /* Set 0 to disable TouchEvent to be duplicated as MouseEvent with SDL_TOUCH_MOUSEID */ + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + /* Set 0 to disable MouseEvent to be duplicated as TouchEvent with SDL_MOUSE_TOUCHID */ + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); + + /* Initialize test framework */ + state = SDLTest_CommonCreateState(argv, 0); + if (state == NULL) { + return 1; + } + + /* Enable standard application logging */ + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); + return 1; + } + + window = SDL_CreateWindow("Local Video", 1000, 800, 0); + if (window == NULL) { + SDL_Log("Couldn't create window: %s", SDL_GetError()); + return 1; + } + + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + + renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (renderer == NULL) { + /* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */ + return 1; + } + + device = SDL_OpenVideoCaptureWithSpec(0, NULL, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE); + if (!device) { + SDL_Log("No video capture? %s", SDL_GetError()); + return 1; + } + + if (SDL_StartVideoCapture(device) < 0) { + SDL_Log("error SDL_StartVideoCapture(): %s", SDL_GetError()); + return 1; + } + + /* Create texture with appropriate format */ + if (texture == NULL) { + texture = SDL_CreateTexture(renderer, obtained.format, SDL_TEXTUREACCESS_STATIC, obtained.width, obtained.height); + if (texture == NULL) { + SDL_Log("Couldn't create texture: %s", SDL_GetError()); + return 1; + } + } + + while (!quit) { + while (SDL_PollEvent(&evt)) { + int sym = 0; + switch (evt.type) + { + case SDL_EVENT_KEY_DOWN: + { + sym = evt.key.keysym.sym; + break; + } + + case SDL_EVENT_QUIT: + { + quit = 1; + SDL_Log("Ctlr+C : Quit!"); + } + } + + if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) { + quit = 1; + SDL_Log("Key : Escape!"); + } + } + + { + SDL_VideoCaptureFrame frame_next; + SDL_zero(frame_next); + + if (SDL_AcquireVideoCaptureFrame(device, &frame_next) < 0) { + SDL_Log("err SDL_AcquireVideoCaptureFrame: %s", SDL_GetError()); + } +#if 0 + if (frame_next.num_planes) { + SDL_Log("frame: %p at %" SDL_PRIu64, (void*)frame_next.data[0], frame_next.timestampNS); + } +#endif + + if (frame_next.num_planes) { + if (frame_current.num_planes) { + if (SDL_ReleaseVideoCaptureFrame(device, &frame_current) < 0) { + SDL_Log("err SDL_ReleaseVideoCaptureFrame: %s", SDL_GetError()); + } + } + + /* It's not needed to keep the frame once updated the texture is updated. + * But in case of 0-copy, it's needed to have the frame while using the texture. + */ + frame_current = frame_next; + texture_updated = 0; + } + } + + /* Update SDL_Texture with last video frame (only once per new frame) */ + if (frame_current.num_planes && texture_updated == 0) { + /* Use software data */ + if (frame_current.num_planes == 1) { + SDL_UpdateTexture(texture, NULL, + frame_current.data[0], frame_current.pitch[0]); + } else if (frame_current.num_planes == 2) { + SDL_UpdateNVTexture(texture, NULL, + frame_current.data[0], frame_current.pitch[0], + frame_current.data[1], frame_current.pitch[1]); + } else if (frame_current.num_planes == 3) { + SDL_UpdateYUVTexture(texture, NULL, frame_current.data[0], frame_current.pitch[0], + frame_current.data[1], frame_current.pitch[1], + frame_current.data[2], frame_current.pitch[2]); + } + texture_updated = 1; + } + + SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255); + SDL_RenderClear(renderer); + { + int win_w, win_h, tw, th, w; + SDL_FRect d; + SDL_QueryTexture(texture, NULL, NULL, &tw, &th); + SDL_GetRenderOutputSize(renderer, &win_w, &win_h); + w = win_w; + if (tw > w - 20) { + float scale = (float) (w - 20) / (float) tw; + tw = w - 20; + th = (int)((float) th * scale); + } + d.x = (float)(10 ); + d.y = (float)(win_h - th); + d.w = (float)tw; + d.h = (float)(th - 10); + SDL_RenderTexture(renderer, texture, NULL, &d); + } + SDL_Delay(10); + SDL_RenderPresent(renderer); + } + + if (SDL_StopVideoCapture(device) < 0) { + SDL_Log("error SDL_StopVideoCapture(): %s", SDL_GetError()); + } + if (frame_current.num_planes) { + SDL_ReleaseVideoCaptureFrame(device, &frame_current); + } + SDL_CloseVideoCapture(device); + + if (texture) { + SDL_DestroyTexture(texture); + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + SDLTest_CommonDestroyState(state); + + return 0; +} From 4ac3f5c07e934d72019c5db340d2f840ae41004b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 9 Nov 2023 09:01:29 -0800 Subject: [PATCH 306/725] Updated Xcode project with the video capture API --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 42 ++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 657b54b2b1c0b..32f2baf0f119a 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -413,6 +413,16 @@ F3B38CDB296E2E52005DA6D3 /* SDL_oldnames.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CDF296E2E52005DA6D3 /* SDL_intrin.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; }; + F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; }; + F3DDCC572AFD42B600B0842B /* SDL_surface_pixel_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */; }; + F3DDCC582AFD42B600B0842B /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */; }; + F3DDCC592AFD42B600B0842B /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */; }; + F3DDCC5A2AFD42B600B0842B /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */; }; + F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; }; + F3DDCC5C2AFD42B600B0842B /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */; }; + F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; }; + F3DDCC5E2AFD42B600B0842B /* SDL_video_capture_v4l2.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */; }; + F3DDCC602AFD432500B0842B /* SDL_video_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */; }; F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F07D59269640160074468B /* SDL_hidapi_luna.c */; }; @@ -914,6 +924,16 @@ F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_oldnames.h; path = SDL3/SDL_oldnames.h; sourceTree = ""; }; F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_intrin.h; path = SDL3/SDL_intrin.h; sourceTree = ""; }; F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = ""; }; + F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = ""; }; + F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_surface_pixel_impl.h; sourceTree = ""; }; + F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_capture.c; sourceTree = ""; }; + F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_video_capture_apple.m; sourceTree = ""; }; + F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_capture_c.h; sourceTree = ""; }; + F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = ""; }; + F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysvideocapture.h; sourceTree = ""; }; + F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = ""; }; + F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_capture_v4l2.c; sourceTree = ""; }; + F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_video_capture.h; path = SDL3/SDL_video_capture.h; sourceTree = ""; }; F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_properties.c; sourceTree = ""; }; F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_properties.h; path = SDL3/SDL_properties.h; sourceTree = ""; }; F3F07D59269640160074468B /* SDL_hidapi_luna.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_luna.c; sourceTree = ""; }; @@ -1093,6 +1113,7 @@ F3F7D8B22933074900816151 /* SDL_timer.h */, F3F7D8AF2933074900816151 /* SDL_touch.h */, F3F7D8E42933074D00816151 /* SDL_version.h */, + F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */, F3F7D8C52933074B00816151 /* SDL_video.h */, F3F7D8D42933074C00816151 /* SDL_vulkan.h */, F3F7D8CF2933074C00816151 /* SDL.h */, @@ -1407,6 +1428,7 @@ A7D8A64C23E2513D00DCD162 /* SDL_blit.c */, A7D8A76B23E2513E00DCD162 /* SDL_blit.h */, A7D8A77323E2513E00DCD162 /* SDL_bmp.c */, + F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */, A7D8A67B23E2513E00DCD162 /* SDL_clipboard.c */, A7D8A60423E2513D00DCD162 /* SDL_egl_c.h */, A7D8A6B623E2513E00DCD162 /* SDL_egl.c */, @@ -1414,16 +1436,24 @@ A7D8A74023E2513E00DCD162 /* SDL_pixels_c.h */, A7D8A64D23E2513D00DCD162 /* SDL_pixels.c */, A7D8A60C23E2513D00DCD162 /* SDL_rect_c.h */, + F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */, A7D8A63423E2513D00DCD162 /* SDL_rect.c */, A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */, A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */, A7D8A60D23E2513D00DCD162 /* SDL_shape_internals.h */, A7D8A76923E2513E00DCD162 /* SDL_shape.c */, A7D8A60323E2513D00DCD162 /* SDL_stretch.c */, + F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */, A7D8A61423E2513D00DCD162 /* SDL_surface.c */, A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */, - A7D8A60E23E2513D00DCD162 /* SDL_video.c */, + F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */, + F3DDCC522AFD42B600B0842B /* SDL_video_c.h */, + F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */, + F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */, + F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */, + F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */, E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */, + A7D8A60E23E2513D00DCD162 /* SDL_video.c */, A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */, A7D8A64023E2513D00DCD162 /* SDL_vulkan_utils.c */, A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */, @@ -2103,7 +2133,9 @@ A7D8B61723E2514300DCD162 /* SDL_assert_c.h in Headers */, F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */, F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */, + F3DDCC602AFD432500B0842B /* SDL_video_capture.h in Headers */, A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */, + F3DDCC5A2AFD42B600B0842B /* SDL_video_capture_c.h in Headers */, A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */, F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */, F3F7D9A52933074E00816151 /* SDL_bits.h in Headers */, @@ -2119,6 +2151,7 @@ A7D8BB6F23E2514500DCD162 /* SDL_clipboardevents_c.h in Headers */, F3F7D9D92933074E00816151 /* SDL_close_code.h in Headers */, A7D8AECA23E2514100DCD162 /* SDL_cocoaclipboard.h in Headers */, + F3DDCC5C2AFD42B600B0842B /* SDL_sysvideocapture.h in Headers */, A7D8AF1223E2514100DCD162 /* SDL_cocoaevents.h in Headers */, A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */, A7D8AF0623E2514100DCD162 /* SDL_cocoamessagebox.h in Headers */, @@ -2263,6 +2296,7 @@ F3F7D9012933074E00816151 /* SDL_touch.h in Headers */, A7D8BB6323E2514500DCD162 /* SDL_touch_c.h in Headers */, A1626A522617008D003F1973 /* SDL_triangle.h in Headers */, + F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */, A7D8BBD223E2574800DCD162 /* SDL_uikitappdelegate.h in Headers */, A7D8BBD423E2574800DCD162 /* SDL_uikitclipboard.h in Headers */, A7D8BBD623E2574800DCD162 /* SDL_uikitevents.h in Headers */, @@ -2277,6 +2311,7 @@ A7D8BBE623E2574800DCD162 /* SDL_uikitviewcontroller.h in Headers */, A7D8BBE823E2574800DCD162 /* SDL_uikitvulkan.h in Headers */, A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */, + F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */, F386F6F02884663E001840AA /* SDL_utils_c.h in Headers */, F3973FA228A59BDD00B84553 /* SDL_vacopy.h in Headers */, F3F7D9D52933074E00816151 /* SDL_version.h in Headers */, @@ -2308,6 +2343,7 @@ A7D8B56F23E2514300DCD162 /* usb_ids.h in Headers */, A7D8B25423E2514200DCD162 /* vk_icd.h in Headers */, A7D8B24E23E2514200DCD162 /* vk_layer.h in Headers */, + F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */, A7D8B26623E2514200DCD162 /* vk_platform.h in Headers */, A7D8B2AE23E2514200DCD162 /* vk_sdk_platform.h in Headers */, A7D8B26023E2514200DCD162 /* vulkan.h in Headers */, @@ -2323,6 +2359,7 @@ A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */, A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */, + F3DDCC572AFD42B600B0842B /* SDL_surface_pixel_impl.h in Headers */, A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */, A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */, @@ -2469,6 +2506,7 @@ A7D8B86623E2514400DCD162 /* SDL_audiocvt.c in Sources */, A7D8B3AA23E2514200DCD162 /* SDL_shape.c in Sources */, A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */, + F3DDCC5E2AFD42B600B0842B /* SDL_video_capture_v4l2.c in Sources */, A7D8BBE323E2574800DCD162 /* SDL_uikitvideo.m in Sources */, 5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */, A7D8A97523E2514000DCD162 /* SDL_coremotionsensor.m in Sources */, @@ -2486,6 +2524,7 @@ A7D8AB7323E2514100DCD162 /* SDL_offscreenframebuffer.c in Sources */, A7D8B3BF23E2514200DCD162 /* yuv_rgb.c in Sources */, A7D8B43423E2514300DCD162 /* SDL_systhread.c in Sources */, + F3DDCC592AFD42B600B0842B /* SDL_video_capture_apple.m in Sources */, A7D8BB3323E2514500DCD162 /* SDL_windowevents.c in Sources */, A7D8BABB23E2514400DCD162 /* s_scalbn.c in Sources */, F3973FAB28A59BDD00B84553 /* SDL_crc16.c in Sources */, @@ -2521,6 +2560,7 @@ A7D8B86023E2514400DCD162 /* SDL_audiotypecvt.c in Sources */, A7D8BBC523E2561500DCD162 /* SDL_steamcontroller.c in Sources */, A7D8AD3223E2514100DCD162 /* SDL_blit_N.c in Sources */, + F3DDCC582AFD42B600B0842B /* SDL_video_capture.c in Sources */, A7D8BB7B23E2514500DCD162 /* SDL_dropevents.c in Sources */, A7D8BACD23E2514500DCD162 /* e_atan2.c in Sources */, A7D8BA8B23E2514400DCD162 /* s_sin.c in Sources */, From 61c39ce8489ae52933825a8c8b06553eedc3d0e9 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 17:37:36 +0100 Subject: [PATCH 307/725] ci: re-enable Intel compilers on ci --- .github/workflows/main.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 62b0e9b8c3e9a..46d2b1e87e76b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,10 +25,10 @@ jobs: - { name: Windows (clang64), os: windows-latest, shell: 'msys2 {0}', msystem: clang64, msys-env: mingw-w64-clang-x86_64, artifact: 'SDL-msys2-clang64' } - { name: Windows (ucrt64), os: windows-latest, shell: 'msys2 {0}', msystem: ucrt64, msys-env: mingw-w64-ucrt-x86_64, artifact: 'SDL-msys2-ucrt64' } - { name: Ubuntu 20.04, os: ubuntu-20.04, shell: sh, artifact: 'SDL-ubuntu20.04' } - #- { name: Intel oneAPI (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-oneapi', intel: true, - # source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icx; export CXX=icx;'} - #- { name: Intel Compiler (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-icc', intel: true, cmake: '-DSDL_CLANG_TIDY=OFF', - # source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icc; export CXX=icpc; export CFLAGS=-diag-disable=10441; export CXXFLAGS=-diag-disable=10441; '} + - { name: Intel oneAPI (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-oneapi', intel: true, + source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icx; export CXX=icx;'} + - { name: Intel Compiler (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-icc', intel: true, cmake: '-DSDL_CLANG_TIDY=OFF', + source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icc; export CXX=icpc; export CFLAGS=-diag-disable=10441; export CXXFLAGS=-diag-disable=10441; '} - { name: Ubuntu 22.04, os: ubuntu-22.04, shell: sh, artifact: 'SDL-ubuntu22.04' } - { name: MacOS (Framework), os: macos-latest, shell: sh, cmake: '-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DSDL_FRAMEWORK=ON -DSDL_CLANG_TIDY=OFF', skip_test_pkgconfig: true, artifact: 'SDL-macos-framework', no-static: true } - { name: MacOS (GNU prefix), os: macos-latest, shell: sh, cmake: '-DCMAKE_OSX_ARCHITECTURES="x86_64" -DCLANG_TIDY_BINARY="$(brew --prefix llvm)/bin/clang-tidy"', artifact: 'SDL-macos-gnu' } @@ -74,12 +74,16 @@ jobs: - name: Setup Intel oneAPI if: matrix.platform.intel run: | - # Setup oneAPI repo - wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB - sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB - sudo echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + # Download the key to system keyring + wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \ + | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null + + # Add signed entry to apt sources and configure the APT client to use Intel repository: + echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + + # Update package list sudo apt-get update -y - + # Install oneAPI sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic From 23db9716814bfad469227a5d7069dc1898310d96 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 18:45:54 +0100 Subject: [PATCH 308/725] x11: Ignore deprecated declaration of XKeycodeToKeysym --- src/video/x11/SDL_x11sym.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 08447ebd40e08..9fdb205877310 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -193,11 +193,19 @@ SDL_X11_SYM(void,XkbFreeKeyboard,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),) SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c),return) #endif +/* XKeycodeToKeysym is a deprecated function */ +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif #if NeedWidePrototypes SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) #else SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return) #endif +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif #ifdef X_HAVE_UTF8_STRING SDL_X11_MODULE(UTF8) From d8600f717e1e90808757f7c7ba41b2d1a2858d1a Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 9 Nov 2023 22:29:15 +0100 Subject: [PATCH 309/725] Pointer as bool (libsdl-org#7214) --- VisualC-GDK/tests/testgdk/src/testgdk.cpp | 6 +- cmake/test/main_gui.c | 2 +- src/SDL.c | 2 +- src/SDL_assert.c | 16 +- src/SDL_error.c | 2 +- src/SDL_guid.c | 2 +- src/SDL_hashtable.c | 30 ++-- src/SDL_hints.c | 34 ++-- src/SDL_list.c | 4 +- src/SDL_log.c | 12 +- src/atomic/SDL_spinlock.c | 2 +- src/audio/SDL_audio.c | 114 ++++++------ src/audio/SDL_audiocvt.c | 46 ++--- src/audio/SDL_audiodev.c | 6 +- src/audio/SDL_audioqueue.c | 32 ++-- src/audio/SDL_wave.c | 36 ++-- src/audio/aaudio/SDL_aaudio.c | 18 +- src/audio/alsa/SDL_alsa_audio.c | 36 ++-- src/audio/android/SDL_androidaudio.c | 10 +- src/audio/directsound/SDL_directsound.c | 18 +- src/audio/disk/SDL_diskaudio.c | 12 +- src/audio/dsp/SDL_dspaudio.c | 4 +- src/audio/emscripten/SDL_emscriptenaudio.c | 4 +- src/audio/haiku/SDL_haikuaudio.cc | 6 +- src/audio/jack/SDL_jackaudio.c | 18 +- src/audio/n3ds/SDL_n3dsaudio.c | 6 +- src/audio/netbsd/SDL_netbsdaudio.c | 4 +- src/audio/openslES/SDL_openslES.c | 6 +- src/audio/pipewire/SDL_pipewire.c | 64 +++---- src/audio/ps2/SDL_ps2audio.c | 6 +- src/audio/psp/SDL_pspaudio.c | 6 +- src/audio/pulseaudio/SDL_pulseaudio.c | 44 ++--- src/audio/qnx/SDL_qsa_audio.c | 2 +- src/audio/sndio/SDL_sndioaudio.c | 20 +-- src/audio/vita/SDL_vitaaudio.c | 6 +- src/audio/wasapi/SDL_wasapi.c | 22 +-- src/audio/wasapi/SDL_wasapi_win32.c | 4 +- src/core/SDL_runapp.c | 2 +- src/core/android/SDL_android.c | 46 ++--- src/core/freebsd/SDL_evdev_kbd_freebsd.c | 10 +- src/core/haiku/SDL_BeApp.cc | 6 +- src/core/linux/SDL_dbus.c | 20 +-- src/core/linux/SDL_evdev.c | 38 ++-- src/core/linux/SDL_evdev_kbd.c | 12 +- src/core/linux/SDL_fcitx.c | 2 +- src/core/linux/SDL_ibus.c | 30 ++-- src/core/linux/SDL_ime.c | 6 +- src/core/linux/SDL_system_theme.c | 4 +- src/core/linux/SDL_threadprio.c | 10 +- src/core/linux/SDL_udev.c | 90 +++++----- src/core/ngage/SDL_ngage_runapp.cpp | 2 +- src/core/openbsd/SDL_wscons_kbd.c | 8 +- src/core/openbsd/SDL_wscons_mouse.c | 4 +- src/core/windows/SDL_hid.c | 6 +- src/core/windows/SDL_immdevice.c | 4 +- src/core/windows/SDL_windows.c | 8 +- src/core/windows/SDL_xinput.c | 4 +- src/core/winrt/SDL_winrtapp_direct3d.cpp | 2 +- src/dynapi/SDL_dynapi.c | 6 +- src/events/SDL_displayevents.c | 2 +- src/events/SDL_keyboard.c | 10 +- src/events/SDL_mouse.c | 28 +-- src/events/SDL_touch.c | 16 +- src/events/SDL_windowevents.c | 8 +- src/file/SDL_rwops.c | 24 +-- src/file/n3ds/SDL_rwopsromfs.c | 2 +- src/filesystem/android/SDL_sysfilesystem.c | 2 +- src/filesystem/emscripten/SDL_sysfilesystem.c | 6 +- src/filesystem/gdk/SDL_sysfilesystem.cpp | 6 +- src/filesystem/haiku/SDL_sysfilesystem.cc | 10 +- src/filesystem/n3ds/SDL_sysfilesystem.c | 4 +- src/filesystem/ps2/SDL_sysfilesystem.c | 4 +- src/filesystem/psp/SDL_sysfilesystem.c | 4 +- src/filesystem/riscos/SDL_sysfilesystem.c | 24 +-- src/filesystem/unix/SDL_sysfilesystem.c | 66 +++---- src/filesystem/vita/SDL_sysfilesystem.c | 6 +- src/filesystem/windows/SDL_sysfilesystem.c | 10 +- src/filesystem/winrt/SDL_sysfilesystem.cpp | 16 +- src/haptic/SDL_haptic.c | 8 +- src/haptic/android/SDL_syshaptic.c | 24 +-- src/haptic/darwin/SDL_syshaptic.c | 40 ++--- src/haptic/linux/SDL_syshaptic.c | 30 ++-- src/haptic/windows/SDL_dinputhaptic.c | 36 ++-- src/haptic/windows/SDL_windowshaptic.c | 10 +- src/haptic/windows/SDL_xinputhaptic.c | 14 +- src/joystick/SDL_gamepad.c | 118 ++++++------- src/joystick/SDL_joystick.c | 22 +-- src/joystick/android/SDL_sysjoystick.c | 26 +-- src/joystick/bsd/SDL_bsdjoystick.c | 30 ++-- src/joystick/darwin/SDL_iokitjoystick.c | 20 +-- src/joystick/emscripten/SDL_sysjoystick.c | 20 +-- src/joystick/hidapi/SDL_hidapi_gamecube.c | 6 +- src/joystick/hidapi/SDL_hidapi_luna.c | 4 +- src/joystick/hidapi/SDL_hidapi_ps3.c | 10 +- src/joystick/hidapi/SDL_hidapi_ps4.c | 4 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 4 +- src/joystick/hidapi/SDL_hidapi_rumble.c | 2 +- src/joystick/hidapi/SDL_hidapi_shield.c | 6 +- src/joystick/hidapi/SDL_hidapi_stadia.c | 4 +- src/joystick/hidapi/SDL_hidapi_steam.c | 4 +- src/joystick/hidapi/SDL_hidapi_switch.c | 8 +- src/joystick/hidapi/SDL_hidapi_wii.c | 4 +- src/joystick/hidapi/SDL_hidapi_xbox360.c | 4 +- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 4 +- src/joystick/hidapi/SDL_hidapi_xboxone.c | 14 +- src/joystick/hidapi/SDL_hidapijoystick.c | 24 +-- src/joystick/linux/SDL_sysjoystick.c | 88 +++++----- src/joystick/virtual/SDL_virtualjoystick.c | 24 +-- src/joystick/windows/SDL_dinputjoystick.c | 18 +- src/joystick/windows/SDL_rawinputjoystick.c | 10 +- .../windows/SDL_windows_gaming_input.c | 8 +- src/joystick/windows/SDL_windowsjoystick.c | 14 +- src/joystick/windows/SDL_xinputjoystick.c | 4 +- src/loadso/dlopen/SDL_sysloadso.c | 8 +- src/loadso/windows/SDL_sysloadso.c | 8 +- src/locale/SDL_locale.c | 4 +- src/locale/unix/SDL_syslocale.c | 6 +- src/locale/windows/SDL_syslocale.c | 6 +- src/misc/SDL_url.c | 2 +- src/misc/windows/SDL_sysurl.c | 2 +- src/power/SDL_power.c | 4 +- src/power/linux/SDL_syspower.c | 10 +- src/render/SDL_render.c | 136 +++++++-------- src/render/SDL_yuv_sw.c | 2 +- src/render/direct3d/SDL_render_d3d.c | 44 ++--- src/render/direct3d11/SDL_render_d3d11.c | 44 ++--- src/render/direct3d12/SDL_render_d3d12.c | 36 ++-- src/render/opengl/SDL_render_gl.c | 32 ++-- src/render/opengl/SDL_shaders_gl.c | 2 +- src/render/opengles2/SDL_render_gles2.c | 40 ++--- src/render/ps2/SDL_render_ps2.c | 16 +- src/render/psp/SDL_render_psp.c | 42 ++--- src/render/software/SDL_blendfillrect.c | 6 +- src/render/software/SDL_blendline.c | 8 +- src/render/software/SDL_blendpoint.c | 6 +- src/render/software/SDL_drawline.c | 8 +- src/render/software/SDL_drawpoint.c | 4 +- src/render/software/SDL_render_sw.c | 70 ++++---- src/render/software/SDL_rotate.c | 6 +- src/render/software/SDL_triangle.c | 6 +- src/render/vitagxm/SDL_render_vita_gxm.c | 24 +-- .../vitagxm/SDL_render_vita_gxm_memory.c | 8 +- .../vitagxm/SDL_render_vita_gxm_tools.c | 6 +- src/sensor/SDL_sensor.c | 2 +- src/sensor/android/SDL_androidsensor.c | 4 +- src/sensor/vita/SDL_vitasensor.c | 4 +- src/sensor/windows/SDL_windowssensor.c | 8 +- src/stdlib/SDL_getenv.c | 22 +-- src/stdlib/SDL_iconv.c | 28 +-- src/stdlib/SDL_string.c | 10 +- src/test/SDL_test_common.c | 8 +- src/test/SDL_test_compare.c | 4 +- src/test/SDL_test_crc32.c | 12 +- src/test/SDL_test_font.c | 8 +- src/test/SDL_test_fuzzer.c | 2 +- src/test/SDL_test_harness.c | 34 ++-- src/test/SDL_test_md5.c | 8 +- src/test/SDL_test_memory.c | 4 +- src/test/SDL_test_random.c | 6 +- src/thread/SDL_thread.c | 34 ++-- src/thread/generic/SDL_syscond.c | 6 +- src/thread/generic/SDL_sysmutex.c | 2 +- src/thread/generic/SDL_syssem.c | 6 +- src/thread/n3ds/SDL_syscond.c | 8 +- src/thread/n3ds/SDL_sysmutex.c | 2 +- src/thread/n3ds/SDL_syssem.c | 8 +- src/thread/n3ds/SDL_systhread.c | 2 +- src/thread/ngage/SDL_syssem.cpp | 8 +- src/thread/ps2/SDL_syssem.c | 10 +- src/thread/psp/SDL_syscond.c | 6 +- src/thread/psp/SDL_sysmutex.c | 2 +- src/thread/psp/SDL_syssem.c | 10 +- src/thread/pthread/SDL_syscond.c | 6 +- src/thread/pthread/SDL_sysmutex.c | 2 +- src/thread/pthread/SDL_syssem.c | 10 +- src/thread/pthread/SDL_systhread.c | 4 +- src/thread/stdcpp/SDL_syscond.cpp | 6 +- src/thread/stdcpp/SDL_sysmutex.cpp | 4 +- src/thread/stdcpp/SDL_sysrwlock.cpp | 2 +- src/thread/vita/SDL_syscond.c | 10 +- src/thread/vita/SDL_sysmutex.c | 6 +- src/thread/vita/SDL_syssem.c | 10 +- src/thread/windows/SDL_syscond_cv.c | 16 +- src/thread/windows/SDL_sysmutex.c | 10 +- src/thread/windows/SDL_sysrwlock_srw.c | 8 +- src/thread/windows/SDL_syssem.c | 22 +-- src/thread/windows/SDL_systhread.c | 8 +- src/timer/SDL_timer.c | 8 +- src/video/SDL_RLEaccel.c | 14 +- src/video/SDL_blit.c | 6 +- src/video/SDL_blit_A.c | 6 +- src/video/SDL_blit_N.c | 8 +- src/video/SDL_bmp.c | 8 +- src/video/SDL_clipboard.c | 22 +-- src/video/SDL_egl.c | 50 +++--- src/video/SDL_fillrect.c | 14 +- src/video/SDL_pixels.c | 34 ++-- src/video/SDL_rect.c | 4 +- src/video/SDL_rect_impl.h | 32 ++-- src/video/SDL_shape.c | 20 +-- src/video/SDL_surface.c | 78 ++++----- src/video/SDL_surface_pixel_impl.h | 10 +- src/video/SDL_video.c | 162 +++++++++--------- src/video/SDL_vulkan_utils.c | 14 +- src/video/SDL_yuv.c | 10 +- src/video/android/SDL_androidmouse.c | 8 +- src/video/android/SDL_androidtouch.c | 2 +- src/video/android/SDL_androidvideo.c | 4 +- src/video/android/SDL_androidvulkan.c | 6 +- src/video/android/SDL_androidwindow.c | 4 +- src/video/dummy/SDL_nullframebuffer.c | 4 +- src/video/dummy/SDL_nullvideo.c | 2 +- src/video/emscripten/SDL_emscriptenevents.c | 4 +- .../emscripten/SDL_emscriptenframebuffer.c | 4 +- src/video/emscripten/SDL_emscriptenmouse.c | 8 +- src/video/emscripten/SDL_emscriptenopengles.c | 2 +- src/video/emscripten/SDL_emscriptenvideo.c | 4 +- src/video/gdk/SDL_gdktextinput.cpp | 18 +- src/video/haiku/SDL_bclipboard.cc | 2 +- src/video/haiku/SDL_bframebuffer.cc | 2 +- src/video/haiku/SDL_bmessagebox.cc | 6 +- src/video/haiku/SDL_bopengl.cc | 8 +- src/video/haiku/SDL_bvideo.cc | 8 +- src/video/haiku/SDL_bwindow.cc | 2 +- src/video/kmsdrm/SDL_kmsdrmdyn.c | 12 +- src/video/kmsdrm/SDL_kmsdrmmouse.c | 14 +- src/video/kmsdrm/SDL_kmsdrmopengles.c | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 36 ++-- src/video/kmsdrm/SDL_kmsdrmvulkan.c | 6 +- src/video/n3ds/SDL_n3dsframebuffer.c | 4 +- src/video/n3ds/SDL_n3dsvideo.c | 10 +- src/video/ngage/SDL_ngageframebuffer.cpp | 4 +- src/video/ngage/SDL_ngagevideo.cpp | 4 +- src/video/ngage/SDL_ngagewindow.cpp | 2 +- .../offscreen/SDL_offscreenframebuffer.c | 4 +- src/video/offscreen/SDL_offscreenvideo.c | 2 +- src/video/offscreen/SDL_offscreenwindow.c | 2 +- src/video/ps2/SDL_ps2video.c | 2 +- src/video/psp/SDL_pspvideo.c | 8 +- src/video/qnx/SDL_qnxgl.c | 2 +- src/video/qnx/SDL_qnxvideo.c | 4 +- src/video/raspberry/SDL_rpimouse.c | 24 +-- src/video/raspberry/SDL_rpivideo.c | 8 +- src/video/riscos/SDL_riscosframebuffer.c | 4 +- src/video/riscos/SDL_riscosmodes.c | 12 +- src/video/riscos/SDL_riscosvideo.c | 4 +- src/video/riscos/SDL_riscoswindow.c | 4 +- src/video/vita/SDL_vitaframebuffer.c | 2 +- src/video/vita/SDL_vitagl_pvr.c | 4 +- src/video/vita/SDL_vitagles_pvr.c | 4 +- src/video/vita/SDL_vitakeyboard.c | 2 +- src/video/vita/SDL_vitamouse.c | 2 +- src/video/vita/SDL_vitatouch.c | 2 +- src/video/vita/SDL_vitavideo.c | 10 +- src/video/vivante/SDL_vivantevideo.c | 8 +- src/video/vivante/SDL_vivantevulkan.c | 6 +- src/video/wayland/SDL_waylandclipboard.c | 20 +-- src/video/wayland/SDL_waylanddatamanager.c | 82 ++++----- src/video/wayland/SDL_waylanddyn.c | 12 +- src/video/wayland/SDL_waylandevents.c | 126 +++++++------- src/video/wayland/SDL_waylandkeyboard.c | 10 +- src/video/wayland/SDL_waylandmessagebox.c | 16 +- src/video/wayland/SDL_waylandmouse.c | 22 +-- src/video/wayland/SDL_waylandvideo.c | 14 +- src/video/wayland/SDL_waylandvulkan.c | 6 +- src/video/wayland/SDL_waylandwindow.c | 46 ++--- src/video/windows/SDL_windowsclipboard.c | 2 +- src/video/windows/SDL_windowsevents.c | 20 ++- src/video/windows/SDL_windowsframebuffer.c | 2 +- src/video/windows/SDL_windowskeyboard.c | 18 +- src/video/windows/SDL_windowsmessagebox.c | 32 ++-- src/video/windows/SDL_windowsmodes.c | 12 +- src/video/windows/SDL_windowsmouse.c | 4 +- src/video/windows/SDL_windowsopengl.c | 14 +- src/video/windows/SDL_windowsopengles.c | 4 +- src/video/windows/SDL_windowsshape.c | 8 +- src/video/windows/SDL_windowsvideo.c | 10 +- src/video/windows/SDL_windowsvulkan.c | 6 +- src/video/windows/SDL_windowswindow.c | 24 +-- src/video/winrt/SDL_winrtgamebar.cpp | 6 +- src/video/winrt/SDL_winrtvideo.cpp | 8 +- src/video/x11/SDL_x11clipboard.c | 6 +- src/video/x11/SDL_x11dyn.c | 12 +- src/video/x11/SDL_x11events.c | 16 +- src/video/x11/SDL_x11framebuffer.c | 4 +- src/video/x11/SDL_x11messagebox.c | 20 +-- src/video/x11/SDL_x11modes.c | 30 ++-- src/video/x11/SDL_x11mouse.c | 10 +- src/video/x11/SDL_x11shape.c | 6 +- src/video/x11/SDL_x11video.c | 12 +- src/video/x11/SDL_x11vulkan.c | 8 +- src/video/x11/SDL_x11window.c | 34 ++-- src/video/x11/SDL_x11xfixes.c | 2 +- src/video/x11/SDL_x11xinput2.c | 18 +- test/checkkeys.c | 2 +- test/checkkeysthreads.c | 4 +- test/gamepadutils.c | 2 +- test/loopwave.c | 4 +- test/testatomic.c | 2 +- test/testaudio.c | 24 +-- test/testaudiocapture.c | 2 +- test/testaudiohotplug.c | 8 +- test/testaudioinfo.c | 6 +- test/testaudiostreamdynamicresample.c | 4 +- test/testautomation.c | 2 +- test/testautomation_mouse.c | 6 +- test/testautomation_render.c | 12 +- test/testautomation_stdlib.c | 4 +- test/testautomation_surface.c | 10 +- test/testautomation_video.c | 24 +-- test/testbounds.c | 2 +- test/testcontroller.c | 12 +- test/testcustomcursor.c | 2 +- test/testdisplayinfo.c | 4 +- test/testdraw.c | 2 +- test/testdrawchessboard.c | 6 +- test/testdropfile.c | 2 +- test/testerror.c | 4 +- test/testevdev.c | 2 +- test/testffmpeg.c | 4 +- test/testfile.c | 20 +-- test/testfilesystem.c | 8 +- test/testgeometry.c | 4 +- test/testgl.c | 2 +- test/testgles.c | 6 +- test/testgles2.c | 6 +- test/testgles2_sdf.c | 12 +- test/testhaptic.c | 8 +- test/testhittesting.c | 4 +- test/testhotplug.c | 4 +- test/testiconv.c | 4 +- test/testime.c | 24 +-- test/testintersections.c | 2 +- test/testkeys.c | 2 +- test/testloadso.c | 6 +- test/testlocale.c | 4 +- test/testlock.c | 4 +- test/testmessage.c | 2 +- test/testmouse.c | 12 +- test/testmultiaudio.c | 4 +- test/testnative.c | 16 +- test/testnativew32.c | 2 +- test/testoffscreen.c | 6 +- test/testoverlay.c | 14 +- test/testplatform.c | 4 +- test/testpopup.c | 4 +- test/testpower.c | 2 +- test/testqsort.c | 2 +- test/testrelative.c | 2 +- test/testrendercopyex.c | 2 +- test/testrendertarget.c | 4 +- test/testresample.c | 4 +- test/testrumble.c | 8 +- test/testrwlock.c | 4 +- test/testscale.c | 2 +- test/testsem.c | 2 +- test/testsensor.c | 6 +- test/testshader.c | 12 +- test/testshape.c | 14 +- test/testsprite.c | 6 +- test/testspriteminimal.c | 2 +- test/teststreaming.c | 12 +- test/testsurround.c | 4 +- test/testthread.c | 6 +- test/testtimer.c | 2 +- test/testutils.c | 20 +-- test/testviewport.c | 4 +- test/testvulkan.c | 10 +- test/testwm.c | 6 +- test/testyuv.c | 14 +- test/torturethread.c | 2 +- 371 files changed, 2448 insertions(+), 2442 deletions(-) diff --git a/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/VisualC-GDK/tests/testgdk/src/testgdk.cpp index 1a962a4c20629..50f93e2fab918 100644 --- a/VisualC-GDK/tests/testgdk/src/testgdk.cpp +++ b/VisualC-GDK/tests/testgdk/src/testgdk.cpp @@ -385,7 +385,7 @@ main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO); - if (state == NULL) { + if (!state) { return 1; } @@ -448,7 +448,7 @@ main(int argc, char *argv[]) /* Create the windows, initialize the renderers, and load the textures */ sprites = (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites)); - if (sprites == NULL) { + if (!sprites) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } @@ -463,7 +463,7 @@ main(int argc, char *argv[]) soundname = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav"); - if (soundname == NULL) { + if (!soundname) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); quit(1); } diff --git a/cmake/test/main_gui.c b/cmake/test/main_gui.c index 715c4306f5cab..c8cc03c1289b1 100644 --- a/cmake/test/main_gui.c +++ b/cmake/test/main_gui.c @@ -10,7 +10,7 @@ int main(int argc, char *argv[]) return 1; } window = SDL_CreateWindow("Hello SDL", 640, 480, 0); - if (window == NULL) { + if (!window) { SDL_Log("could not create window: %s\n", SDL_GetError()); return 1; } diff --git a/src/SDL.c b/src/SDL.c index 2959db8749154..302e625e90dc8 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -557,7 +557,7 @@ int SDL_GetVersion(SDL_version *ver) static SDL_bool check_hint = SDL_TRUE; static SDL_bool legacy_version = SDL_FALSE; - if (ver == NULL) { + if (!ver) { return SDL_InvalidParamError("ver"); } diff --git a/src/SDL_assert.c b/src/SDL_assert.c index ba1c194d9c76d..6c2491aaca0ea 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -106,11 +106,11 @@ static void SDL_GenerateAssertionReport(void) const SDL_AssertData *item = triggered_assertions; /* only do this if the app hasn't assigned an assertion handler. */ - if ((item != NULL) && (assertion_handler != SDL_PromptAssertion)) { + if ((item) && (assertion_handler != SDL_PromptAssertion)) { debug_print("\n\nSDL assertion report.\n"); debug_print("All SDL assertions between last init/quit:\n\n"); - while (item != NULL) { + while (item) { debug_print( "'%s'\n" " * %s (%s:%d)\n" @@ -198,7 +198,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v /* let env. variable override, so unit tests won't block in a GUI. */ envr = SDL_getenv("SDL_ASSERT"); - if (envr != NULL) { + if (envr) { if (message != stack_buf) { SDL_free(message); } @@ -334,9 +334,9 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons #ifndef SDL_THREADS_DISABLED static SDL_SpinLock spinlock = 0; SDL_AtomicLock(&spinlock); - if (assertion_mutex == NULL) { /* never called SDL_Init()? */ + if (!assertion_mutex) { /* never called SDL_Init()? */ assertion_mutex = SDL_CreateMutex(); - if (assertion_mutex == NULL) { + if (!assertion_mutex) { SDL_AtomicUnlock(&spinlock); return SDL_ASSERTION_IGNORE; /* oh well, I guess. */ } @@ -401,7 +401,7 @@ void SDL_AssertionsQuit(void) #if SDL_ASSERT_LEVEL > 0 SDL_GenerateAssertionReport(); #ifndef SDL_THREADS_DISABLED - if (assertion_mutex != NULL) { + if (assertion_mutex) { SDL_DestroyMutex(assertion_mutex); assertion_mutex = NULL; } @@ -429,7 +429,7 @@ void SDL_ResetAssertionReport(void) { SDL_AssertData *next = NULL; SDL_AssertData *item; - for (item = triggered_assertions; item != NULL; item = next) { + for (item = triggered_assertions; item; item = next) { next = (SDL_AssertData *)item->next; item->always_ignore = SDL_FALSE; item->trigger_count = 0; @@ -446,7 +446,7 @@ SDL_AssertionHandler SDL_GetDefaultAssertionHandler(void) SDL_AssertionHandler SDL_GetAssertionHandler(void **userdata) { - if (userdata != NULL) { + if (userdata) { *userdata = assertion_userdata; } return assertion_handler; diff --git a/src/SDL_error.c b/src/SDL_error.c index 00f1bcf7d9447..25fe696c79fa8 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -27,7 +27,7 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { /* Ignore call if invalid format pointer was passed */ - if (fmt != NULL) { + if (fmt) { va_list ap; int result; SDL_error *error = SDL_GetErrBuf(); diff --git a/src/SDL_guid.c b/src/SDL_guid.c index 61387941c7943..fc68db4291001 100644 --- a/src/SDL_guid.c +++ b/src/SDL_guid.c @@ -26,7 +26,7 @@ int SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID) static const char k_rgchHexToASCII[] = "0123456789abcdef"; int i; - if (pszGUID == NULL) { + if (!pszGUID) { return SDL_InvalidParamError("pszGUID"); } if (cbGUID <= 0) { diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 1c3c7bb63b6c9..0b898059853fb 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -53,13 +53,13 @@ SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const S } table = (SDL_HashTable *) SDL_calloc(1, sizeof (SDL_HashTable)); - if (table == NULL) { + if (!table) { SDL_OutOfMemory(); return NULL; } table->table = (SDL_HashItem **) SDL_calloc(num_buckets, sizeof (SDL_HashItem *)); - if (table->table == NULL) { + if (!table->table) { SDL_free(table); SDL_OutOfMemory(); return NULL; @@ -91,7 +91,7 @@ SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const vo // !!! FIXME: grow and rehash table if it gets too saturated. item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem)); - if (item == NULL) { + if (!item) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -110,9 +110,9 @@ SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void *data = table->data; SDL_HashItem *i; - for (i = table->table[hash]; i != NULL; i = i->next) { + for (i = table->table[hash]; i; i = i->next) { if (table->keymatch(key, i->key, data)) { - if (_value != NULL) { + if (_value) { *_value = i->value; } return SDL_TRUE; @@ -129,9 +129,9 @@ SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key) SDL_HashItem *prev = NULL; void *data = table->data; - for (item = table->table[hash]; item != NULL; item = item->next) { + for (item = table->table[hash]; item; item = item->next) { if (table->keymatch(key, item->key, data)) { - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { table->table[hash] = item->next; @@ -152,7 +152,7 @@ SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, co { SDL_HashItem *item = *iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)]; - while (item != NULL) { + while (item) { if (table->keymatch(key, item->key, table->data)) { *_value = item->value; *iter = item; @@ -172,10 +172,10 @@ SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, con SDL_HashItem *item = (SDL_HashItem *) *iter; Uint32 idx = 0; - if (item != NULL) { + if (item) { const SDL_HashItem *orig = item; item = item->next; - if (item == NULL) { + if (!item) { idx = calc_hash(table, orig->key) + 1; // !!! FIXME: we probably shouldn't rehash each time. } } @@ -184,7 +184,7 @@ SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, con item = table->table[idx++]; // skip empty buckets... } - if (item == NULL) { // no more matches? + if (!item) { // no more matches? *_key = NULL; *iter = NULL; return SDL_FALSE; @@ -199,12 +199,12 @@ SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, con SDL_bool SDL_HashTableEmpty(SDL_HashTable *table) { - if (table != NULL) { + if (table) { Uint32 i; for (i = 0; i < table->table_len; i++) { SDL_HashItem *item = table->table[i]; - if (item != NULL) { + if (item) { return SDL_FALSE; } } @@ -214,13 +214,13 @@ SDL_bool SDL_HashTableEmpty(SDL_HashTable *table) void SDL_DestroyHashTable(SDL_HashTable *table) { - if (table != NULL) { + if (table) { void *data = table->data; Uint32 i; for (i = 0; i < table->table_len; i++) { SDL_HashItem *item = table->table[i]; - while (item != NULL) { + while (item) { SDL_HashItem *next = item->next; table->nuke(item->key, item->value, data); SDL_free(item); diff --git a/src/SDL_hints.c b/src/SDL_hints.c index 9ee0bc31c91c8..3e792c6d50e19 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -49,7 +49,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr SDL_Hint *hint; SDL_HintWatch *entry; - if (name == NULL) { + if (!name) { return SDL_FALSE; } @@ -64,7 +64,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr return SDL_FALSE; } if (hint->value != value && - (value == NULL || !hint->value || SDL_strcmp(hint->value, value) != 0)) { + (!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) { char *old_value = hint->value; hint->value = value ? SDL_strdup(value) : NULL; @@ -85,7 +85,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr /* Couldn't find the hint, add a new one */ hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); - if (hint == NULL) { + if (!hint) { return SDL_FALSE; } hint->name = SDL_strdup(name); @@ -103,16 +103,16 @@ SDL_bool SDL_ResetHint(const char *name) SDL_Hint *hint; SDL_HintWatch *entry; - if (name == NULL) { + if (!name) { return SDL_FALSE; } env = SDL_getenv(name); for (hint = SDL_hints; hint; hint = hint->next) { if (SDL_strcmp(name, hint->name) == 0) { - if ((env == NULL && hint->value != NULL) || - (env != NULL && hint->value == NULL) || - (env != NULL && SDL_strcmp(env, hint->value) != 0)) { + if ((!env && hint->value) || + (env && !hint->value) || + (env && SDL_strcmp(env, hint->value) != 0)) { for (entry = hint->callbacks; entry;) { /* Save the next entry in case this one is deleted */ SDL_HintWatch *next = entry->next; @@ -137,9 +137,9 @@ void SDL_ResetHints(void) for (hint = SDL_hints; hint; hint = hint->next) { env = SDL_getenv(hint->name); - if ((env == NULL && hint->value != NULL) || - (env != NULL && hint->value == NULL) || - (env != NULL && SDL_strcmp(env, hint->value) != 0)) { + if ((!env && hint->value) || + (env && !hint->value) || + (env && SDL_strcmp(env, hint->value) != 0)) { for (entry = hint->callbacks; entry;) { /* Save the next entry in case this one is deleted */ SDL_HintWatch *next = entry->next; @@ -166,7 +166,7 @@ const char *SDL_GetHint(const char *name) env = SDL_getenv(name); for (hint = SDL_hints; hint; hint = hint->next) { if (SDL_strcmp(name, hint->name) == 0) { - if (env == NULL || hint->priority == SDL_HINT_OVERRIDE) { + if (!env || hint->priority == SDL_HINT_OVERRIDE) { return hint->value; } break; @@ -177,7 +177,7 @@ const char *SDL_GetHint(const char *name) int SDL_GetStringInteger(const char *value, int default_value) { - if (value == NULL || !*value) { + if (!value || !*value) { return default_value; } if (*value == '0' || SDL_strcasecmp(value, "false") == 0) { @@ -194,7 +194,7 @@ int SDL_GetStringInteger(const char *value, int default_value) SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value) { - if (value == NULL || !*value) { + if (!value || !*value) { return default_value; } if (*value == '0' || SDL_strcasecmp(value, "false") == 0) { @@ -215,7 +215,7 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd SDL_HintWatch *entry; const char *value; - if (name == NULL || !*name) { + if (!name || !*name) { return SDL_InvalidParamError("name"); } if (!callback) { @@ -225,7 +225,7 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd SDL_DelHintCallback(name, callback, userdata); entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); - if (entry == NULL) { + if (!entry) { return SDL_OutOfMemory(); } entry->callback = callback; @@ -236,10 +236,10 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd break; } } - if (hint == NULL) { + if (!hint) { /* Need to add a hint entry for this watcher */ hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); - if (hint == NULL) { + if (!hint) { SDL_free(entry); return SDL_OutOfMemory(); } diff --git a/src/SDL_list.c b/src/SDL_list.c index 8c4b509e3e211..64c39245e62a4 100644 --- a/src/SDL_list.c +++ b/src/SDL_list.c @@ -27,7 +27,7 @@ int SDL_ListAdd(SDL_ListNode **head, void *ent) { SDL_ListNode *node = SDL_malloc(sizeof(*node)); - if (node == NULL) { + if (!node) { return SDL_OutOfMemory(); } @@ -43,7 +43,7 @@ void SDL_ListPop(SDL_ListNode **head, void **ent) SDL_ListNode **ptr = head; /* Invalid or empty */ - if (head == NULL || *head == NULL) { + if (!head || !*head) { return; } diff --git a/src/SDL_log.c b/src/SDL_log.c index 214574e34d5f3..a9ac740c42783 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -112,7 +112,7 @@ static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { void SDL_InitLog(void) { - if (log_function_mutex == NULL) { + if (!log_function_mutex) { /* if this fails we'll try to continue without it. */ log_function_mutex = SDL_CreateMutex(); } @@ -305,7 +305,7 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va return; } - if (log_function_mutex == NULL) { + if (!log_function_mutex) { /* this mutex creation can race if you log from two threads at startup. You should have called SDL_Init first! */ log_function_mutex = SDL_CreateMutex(); } @@ -323,7 +323,7 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va if (len >= sizeof(stack_buf) && SDL_size_add_overflow(len, 1, &len_plus_term) == 0) { /* Allocate exactly what we need, including the zero-terminator */ message = (char *)SDL_malloc(len_plus_term); - if (message == NULL) { + if (!message) { return; } va_copy(aq, ap); @@ -459,7 +459,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority { FILE *pFile; pFile = fopen("SDL_Log.txt", "a"); - if (pFile != NULL) { + if (pFile) { (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); (void)fclose(pFile); } @@ -468,7 +468,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority { FILE *pFile; pFile = fopen("ux0:/data/SDL_Log.txt", "a"); - if (pFile != NULL) { + if (pFile) { (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); (void)fclose(pFile); } @@ -477,7 +477,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority { FILE *pFile; pFile = fopen("sdmc:/3ds/SDL_Log.txt", "a"); - if (pFile != NULL) { + if (pFile) { (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); (void)fclose(pFile); } diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index 6f37fa52ad36f..25615accc452c 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -63,7 +63,7 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) /* Terrible terrible damage */ static SDL_Mutex *_spinlock_mutex; - if (_spinlock_mutex == NULL) { + if (!_spinlock_mutex) { /* Race condition on first lock... */ _spinlock_mutex = SDL_CreateMutex(); } diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index f8f24c3920877..7d44695d24676 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -139,7 +139,7 @@ static int GetDefaultSampleFramesFromFreq(const int freq) void OnAudioStreamCreated(SDL_AudioStream *stream) { - SDL_assert(stream != NULL); + SDL_assert(stream); // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! @@ -159,7 +159,7 @@ void OnAudioStreamCreated(SDL_AudioStream *stream) void OnAudioStreamDestroy(SDL_AudioStream *stream) { - SDL_assert(stream != NULL); + SDL_assert(stream); // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! @@ -207,8 +207,8 @@ static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format. } - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // set the proper end of the stream to the device's format. // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. SDL_LockMutex(stream->lock); @@ -441,7 +441,7 @@ static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) // unbind any still-bound streams... SDL_AudioStream *next; - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = next) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = next) { SDL_LockMutex(stream->lock); next = stream->next_binding; stream->next_binding = NULL; @@ -463,7 +463,7 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) // Destroy any logical devices that still exist... SDL_LockMutex(device->lock); // don't use ObtainPhysicalAudioDeviceObj because we don't want to change refcounts while destroying. - while (device->logical_devices != NULL) { + while (device->logical_devices) { DestroyLogicalAudioDevice(device->logical_devices); } SDL_UnlockMutex(device->lock); // don't use ReleaseAudioDevice because we don't want to change refcounts while destroying. @@ -500,7 +500,7 @@ void RefPhysicalAudioDevice(SDL_AudioDevice *device) static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) { - SDL_assert(name != NULL); + SDL_assert(name); SDL_LockRWLockForReading(current_audio.device_hash_lock); const int shutting_down = SDL_AtomicGet(¤t_audio.shutting_down); @@ -593,8 +593,8 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, p->devid = device->instance_id; p->next = NULL; SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail != NULL); - SDL_assert(current_audio.pending_events_tail->next == NULL); + SDL_assert(current_audio.pending_events_tail); + SDL_assert(!current_audio.pending_events_tail->next); current_audio.pending_events_tail->next = p; current_audio.pending_events_tail = p; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -642,7 +642,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. // on non-default devices, dump everything. // (by "dump" we mean send a REMOVED event; the zombie will keep consuming audio data for these logical devices until explicitly closed.) - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { if (!is_default_device || !logdev->opened_as_default) { // if opened as a default, leave it on the zombie device for later migration. SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *) SDL_malloc(sizeof (SDL_PendingAudioDeviceEvent)); if (p) { // if this failed, no event for you, but you have deeper problems anyhow. @@ -670,8 +670,8 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) if (first_disconnect) { if (pending.next) { // NULL if event is disabled or disaster struck. SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail != NULL); - SDL_assert(current_audio.pending_events_tail->next == NULL); + SDL_assert(current_audio.pending_events_tail); + SDL_assert(!current_audio.pending_events_tail->next); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -817,26 +817,26 @@ int SDL_InitAudio(const char *driver_name) } // Select the proper audio driver - if (driver_name == NULL) { + if (!driver_name) { driver_name = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); } SDL_bool initialized = SDL_FALSE; SDL_bool tried_to_init = SDL_FALSE; - if (driver_name != NULL && *driver_name != 0) { + if (driver_name && *driver_name != 0) { char *driver_name_copy = SDL_strdup(driver_name); const char *driver_attempt = driver_name_copy; - if (driver_name_copy == NULL) { + if (!driver_name_copy) { SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); return SDL_OutOfMemory(); } - while (driver_attempt != NULL && *driver_attempt != 0 && !initialized) { + while (driver_attempt && *driver_attempt != 0 && !initialized) { char *driver_attempt_end = SDL_strchr(driver_attempt, ','); - if (driver_attempt_end != NULL) { + if (driver_attempt_end) { *driver_attempt_end = '\0'; } @@ -863,7 +863,7 @@ int SDL_InitAudio(const char *driver_name) } } - driver_attempt = (driver_attempt_end != NULL) ? (driver_attempt_end + 1) : NULL; + driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL; } SDL_free(driver_name_copy); @@ -940,7 +940,7 @@ void SDL_QuitAudio(void) current_audio.impl.DeinitializeStart(); // Destroy any audio streams that still exist... - while (current_audio.existing_streams != NULL) { + while (current_audio.existing_streams) { SDL_DestroyAudioStream(current_audio.existing_streams); } @@ -955,7 +955,7 @@ void SDL_QuitAudio(void) SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_PendingAudioDeviceEvent *pending_next = NULL; - for (SDL_PendingAudioDeviceEvent *i = pending_events; i != NULL; i = pending_next) { + for (SDL_PendingAudioDeviceEvent *i = pending_events; i; i = pending_next) { pending_next = i->next; SDL_free(i); } @@ -1053,7 +1053,7 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_memset(final_mix_buffer, '\0', work_buffer_size); // start with silence. - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { if (SDL_AtomicGet(&logdev->paused)) { continue; // paused? Skip this logical device. } @@ -1065,7 +1065,7 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_memset(mix_buffer, '\0', work_buffer_size); // start with silence. } - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // We should have updated this elsewhere if the format changed! SDL_assert(AUDIO_SPECS_EQUAL(stream->dst_spec, outspec)); @@ -1127,7 +1127,7 @@ void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device) static int SDLCALL OutputAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; - SDL_assert(device != NULL); + SDL_assert(device); SDL_assert(!device->iscapture); SDL_OutputAudioThreadSetup(device); @@ -1164,7 +1164,7 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) SDL_bool failed = SDL_FALSE; - if (device->logical_devices == NULL) { + if (!device->logical_devices) { device->FlushCapture(device); // nothing wants data, dump anything pending. } else { // this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitCaptureDevice! @@ -1172,7 +1172,7 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) if (br < 0) { // uhoh, device failed for some reason! failed = SDL_TRUE; } else if (br > 0) { // queue the new data to each bound stream. - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { if (SDL_AtomicGet(&logdev->paused)) { continue; // paused? Skip this logical device. } @@ -1193,7 +1193,7 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) logdev->postmix(logdev->postmix_userdata, &outspec, device->postmix_buffer, br); } - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // We should have updated this elsewhere if the format changed! SDL_assert(stream->src_spec.format == (logdev->postmix ? SDL_AUDIO_F32 : device->spec.format)); SDL_assert(stream->src_spec.channels == device->spec.channels); @@ -1233,7 +1233,7 @@ void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device) static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; - SDL_assert(device != NULL); + SDL_assert(device); SDL_assert(device->iscapture); SDL_CaptureAudioThreadSetup(device); @@ -1261,7 +1261,7 @@ static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_bool iscapture) int num_devices = SDL_AtomicGet(iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count); if (num_devices > 0) { retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); - if (retval == NULL) { + if (!retval) { num_devices = 0; SDL_OutOfMemory(); } else { @@ -1287,7 +1287,7 @@ static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_bool iscapture) } SDL_UnlockRWLock(current_audio.device_hash_lock); - if (reqcount != NULL) { + if (reqcount) { *reqcount = num_devices; } @@ -1384,7 +1384,7 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { SDL_AtomicSet(&device->shutdown, 1); - if (device->thread != NULL) { + if (device->thread) { SDL_WaitThread(device->thread, NULL); device->thread = NULL; } @@ -1417,7 +1417,7 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); if (logdev) { DestroyLogicalAudioDevice(logdev); - close_physical = (device->logical_devices == NULL); // no more logical devices? Close the physical device, too. + close_physical = (!device->logical_devices); // no more logical devices? Close the physical device, too. } // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. @@ -1458,7 +1458,7 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) spec->freq = iscapture ? DEFAULT_AUDIO_CAPTURE_FREQUENCY : DEFAULT_AUDIO_OUTPUT_FREQUENCY; const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); // !!! FIXME: should be a hint? - if (env != NULL) { + if (env) { const int val = SDL_atoi(env); if (val > 0) { spec->freq = val; @@ -1469,7 +1469,7 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) if (spec->channels == 0) { spec->channels = iscapture ? DEFAULT_AUDIO_CAPTURE_CHANNELS : DEFAULT_AUDIO_OUTPUT_CHANNELS;; const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); - if (env != NULL) { + if (env) { const int val = SDL_atoi(env); if (val > 0) { spec->channels = val; @@ -1502,7 +1502,7 @@ char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen) static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec *inspec) { SDL_assert(!device->currently_opened); - SDL_assert(device->logical_devices == NULL); + SDL_assert(!device->logical_devices); // Just pretend to open a zombie device. It can still collect logical devices on a default device under the assumption they will all migrate when the default device is officially changed. if (SDL_AtomicGet(&device->zombie)) { @@ -1541,14 +1541,14 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec // Allocate a scratch audio buffer device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); - if (device->work_buffer == NULL) { + if (!device->work_buffer) { ClosePhysicalAudioDevice(device); return SDL_OutOfMemory(); } if (device->spec.format != SDL_AUDIO_F32) { device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); - if (device->mix_buffer == NULL) { + if (!device->mix_buffer) { ClosePhysicalAudioDevice(device); return SDL_OutOfMemory(); } @@ -1561,7 +1561,7 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec SDL_GetAudioThreadName(device, threadname, sizeof (threadname)); device->thread = SDL_CreateThreadInternal(device->iscapture ? CaptureAudioThread : OutputAudioThread, threadname, stacksize, device); - if (device->thread == NULL) { + if (!device->thread) { ClosePhysicalAudioDevice(device); return SDL_SetError("Couldn't create audio thread"); } @@ -1672,7 +1672,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac if (logdev) { if (callback && !device->postmix_buffer) { device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); - if (device->postmix_buffer == NULL) { + if (!device->postmix_buffer) { retval = SDL_OutOfMemory(); } } @@ -1682,7 +1682,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac logdev->postmix_userdata = userdata; if (device->iscapture) { - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // set the proper end of the stream to the device's format. // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. SDL_LockMutex(stream->lock); @@ -1709,7 +1709,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int return 0; // nothing to do } else if (num_streams < 0) { return SDL_InvalidParamError("num_streams"); - } else if (streams == NULL) { + } else if (!streams) { return SDL_InvalidParamError("streams"); } else if (!islogical) { return SDL_SetError("Audio streams are bound to device ids from SDL_OpenAudioDevice, not raw physical devices"); @@ -1726,16 +1726,16 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int // !!! FIXME: Actually, why do we allow there to be an invalid format, again? // make sure start of list is sane. - SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL)); + SDL_assert(!logdev->bound_streams || (!logdev->bound_streams->prev_binding)); // lock all the streams upfront, so we can verify they aren't bound elsewhere and add them all in one block, as this is intended to add everything or nothing. for (int i = 0; i < num_streams; i++) { SDL_AudioStream *stream = streams[i]; - if (stream == NULL) { + if (!stream) { retval = SDL_SetError("Stream #%d is NULL", i); } else { SDL_LockMutex(stream->lock); - SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); + SDL_assert((!stream->bound_device) == ((!stream->prev_binding) || (!stream->next_binding))); if (stream->bound_device) { retval = SDL_SetError("Stream #%d is already bound to a device", i); } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. @@ -1830,7 +1830,7 @@ void SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams) // don't allow unbinding from "simplified" devices (opened with SDL_OpenAudioDeviceStream). Just ignore them. if (stream && stream->bound_device && !stream->bound_device->simplified) { if (stream->bound_device->bound_streams == stream) { - SDL_assert(stream->prev_binding == NULL); + SDL_assert(!stream->prev_binding); stream->bound_device->bound_streams = stream->next_binding; } if (stream->prev_binding) { @@ -1887,12 +1887,12 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au SDL_AudioStream *stream = NULL; SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(logdevid, &device); - if (logdev == NULL) { // this shouldn't happen, but just in case. + if (!logdev) { // this shouldn't happen, but just in case. failed = SDL_TRUE; } else { SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. - SDL_assert(device != NULL); + SDL_assert(device); const SDL_bool iscapture = device->iscapture; if (iscapture) { @@ -1960,7 +1960,7 @@ int SDL_GetSilenceValueForFormat(SDL_AudioFormat format) // called internally by backends when the system default device changes. void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) { - if (new_default_device == NULL) { // !!! FIXME: what should we do in this case? Maybe all devices are lost, so there _isn't_ a default? + if (!new_default_device) { // !!! FIXME: what should we do in this case? Maybe all devices are lost, so there _isn't_ a default? return; // uhoh. } @@ -2007,10 +2007,10 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) SDL_bool needs_migration = SDL_FALSE; SDL_zero(spec); - for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev; logdev = logdev->next) { if (logdev->opened_as_default) { needs_migration = SDL_TRUE; - for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { const SDL_AudioSpec *streamspec = iscapture ? &stream->dst_spec : &stream->src_spec; if (SDL_AUDIO_BITSIZE(streamspec->format) > SDL_AUDIO_BITSIZE(spec.format)) { spec.format = streamspec->format; @@ -2036,7 +2036,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (needs_migration) { const SDL_bool spec_changed = !AUDIO_SPECS_EQUAL(current_default_device->spec, new_default_device->spec); SDL_LogicalAudioDevice *next = NULL; - for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = next) { + for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev; logdev = next) { next = logdev->next; if (!logdev->opened_as_default) { @@ -2083,7 +2083,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) UpdateAudioStreamFormatsPhysical(current_default_device); UpdateAudioStreamFormatsPhysical(new_default_device); - if (current_default_device->logical_devices == NULL) { // nothing left on the current physical device, close it. + if (!current_default_device->logical_devices) { // nothing left on the current physical device, close it. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. RefPhysicalAudioDevice(current_default_device); // hold a temp ref for a moment while we release... ReleaseAudioDevice(current_default_device); // can't hold the lock or the audio thread will deadlock while we WaitThread it. @@ -2105,8 +2105,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (pending.next) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail != NULL); - SDL_assert(current_audio.pending_events_tail->next == NULL); + SDL_assert(current_audio.pending_events_tail); + SDL_assert(!current_audio.pending_events_tail->next); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -2173,7 +2173,7 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL pending_tail = p; } - for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) { + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { p = (SDL_PendingAudioDeviceEvent *)SDL_malloc(sizeof(SDL_PendingAudioDeviceEvent)); if (p) { // if this failed, no event for you, but you have deeper problems anyhow. p->type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED; @@ -2186,8 +2186,8 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL if (pending.next) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail != NULL); - SDL_assert(current_audio.pending_events_tail->next == NULL); + SDL_assert(current_audio.pending_events_tail); + SDL_assert(!current_audio.pending_events_tail->next); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -2225,7 +2225,7 @@ void SDL_UpdateAudio(void) SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_PendingAudioDeviceEvent *pending_next = NULL; - for (SDL_PendingAudioDeviceEvent *i = pending_events; i != NULL; i = pending_next) { + for (SDL_PendingAudioDeviceEvent *i = pending_events; i; i = pending_next) { pending_next = i->next; if (SDL_EventEnabled(i->type)) { SDL_Event event; diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index f4eb332a29815..ed93684f2ef8b 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -221,8 +221,8 @@ static SDL_bool SDL_IsSupportedChannelCount(const int channels) void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, int src_channels, void *dst, SDL_AudioFormat dst_format, int dst_channels, void* scratch) { - SDL_assert(src != NULL); - SDL_assert(dst != NULL); + SDL_assert(src); + SDL_assert(dst); SDL_assert(SDL_IsSupportedAudioFormat(src_format)); SDL_assert(SDL_IsSupportedAudioFormat(dst_format)); SDL_assert(SDL_IsSupportedChannelCount(src_channels)); @@ -278,7 +278,7 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i } } - if (scratch == NULL) { + if (!scratch) { scratch = dst; } @@ -313,7 +313,7 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i SDL_assert(dst_channels <= SDL_arraysize(channel_converters[0])); channel_converter = channel_converters[src_channels - 1][dst_channels - 1]; - SDL_assert(channel_converter != NULL); + SDL_assert(channel_converter); // swap in some SIMD versions for a few of these. if (channel_converter == SDL_ConvertStereoToMono) { @@ -408,7 +408,7 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_ SDL_SetupAudioResampler(); SDL_AudioStream *retval = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream)); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -416,13 +416,13 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_ retval->freq_ratio = 1.0f; retval->queue = SDL_CreateAudioQueue(4096); - if (retval->queue == NULL) { + if (!retval->queue) { SDL_free(retval); return NULL; } retval->lock = SDL_CreateMutex(); - if (retval->lock == NULL) { + if (!retval->lock) { SDL_free(retval->queue); SDL_free(retval); return NULL; @@ -632,9 +632,9 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) SDL_Log("AUDIOSTREAM: wants to put %d bytes", len); #endif - if (stream == NULL) { + if (!stream) { return SDL_InvalidParamError("stream"); - } else if (buf == NULL) { + } else if (!buf) { return SDL_InvalidParamError("buf"); } else if (len < 0) { return SDL_InvalidParamError("len"); @@ -669,7 +669,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) size_t chunk_size = SDL_GetAudioQueueChunkSize(stream->queue); track = SDL_CreateChunkedAudioTrack(&src_spec, buf, len, chunk_size); - if (track == NULL) { + if (!track) { return -1; } @@ -680,7 +680,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) int retval = 0; - if (track != NULL) { + if (track) { SDL_AddTrackToAudioQueue(stream->queue, track); } else { retval = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, buf, len); @@ -701,7 +701,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) int SDL_FlushAudioStream(SDL_AudioStream *stream) { - if (stream == NULL) { + if (!stream) { return SDL_InvalidParamError("stream"); } @@ -721,7 +721,7 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne } Uint8 *ptr = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), newlen); - if (ptr == NULL) { + if (!ptr) { SDL_OutOfMemory(); return NULL; // previous work buffer is still valid! } @@ -741,7 +741,7 @@ static void UpdateAudioStreamHistoryBuffer(SDL_AudioStream* stream, Uint8 *history_buffer = stream->history_buffer; int history_bytes = history_buffer_frames * SDL_AUDIO_FRAMESIZE(stream->input_spec); - if (left_padding != NULL) { + if (left_padding) { // Fill in the left padding using the history buffer SDL_assert(padding_bytes <= history_bytes); SDL_memcpy(left_padding, history_buffer + history_bytes - padding_bytes, padding_bytes); @@ -835,7 +835,7 @@ static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spe { void* iter = SDL_BeginAudioQueueIter(stream->queue); - if (iter == NULL) { + if (!iter) { SDL_zerop(out_spec); *out_flushed = SDL_FALSE; return 0; @@ -1025,9 +1025,9 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) SDL_Log("AUDIOSTREAM: want to get %d converted bytes", len); #endif - if (stream == NULL) { + if (!stream) { return SDL_InvalidParamError("stream"); - } else if (buf == NULL) { + } else if (!buf) { return SDL_InvalidParamError("buf"); } else if (len < 0) { return SDL_InvalidParamError("len"); @@ -1160,7 +1160,7 @@ int SDL_GetAudioStreamQueued(SDL_AudioStream *stream) int SDL_ClearAudioStream(SDL_AudioStream *stream) { - if (stream == NULL) { + if (!stream) { return SDL_InvalidParamError("stream"); } @@ -1177,7 +1177,7 @@ int SDL_ClearAudioStream(SDL_AudioStream *stream) void SDL_DestroyAudioStream(SDL_AudioStream *stream) { - if (stream == NULL) { + if (!stream) { return; } @@ -1214,13 +1214,13 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data *dst_len = 0; } - if (src_data == NULL) { + if (!src_data) { return SDL_InvalidParamError("src_data"); } else if (src_len < 0) { return SDL_InvalidParamError("src_len"); - } else if (dst_data == NULL) { + } else if (!dst_data) { return SDL_InvalidParamError("dst_data"); - } else if (dst_len == NULL) { + } else if (!dst_len) { return SDL_InvalidParamError("dst_len"); } @@ -1229,7 +1229,7 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data int dstlen = 0; SDL_AudioStream *stream = SDL_CreateAudioStream(src_spec, dst_spec); - if (stream != NULL) { + if (stream) { if ((SDL_PutAudioStreamData(stream, src_data, src_len) == 0) && (SDL_FlushAudioStream(stream) == 0)) { dstlen = SDL_GetAudioStreamAvailable(stream); if (dstlen >= 0) { diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index f00b8590dd5ee..f49a9fe7fdcce 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -80,16 +80,16 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD const char *audiodev; char audiopath[1024]; - if (test == NULL) { + if (!test) { test = test_stub; } // Figure out what our audio device is audiodev = SDL_getenv("SDL_PATH_DSP"); - if (audiodev == NULL) { + if (!audiodev) { audiodev = SDL_getenv("AUDIODEV"); } - if (audiodev == NULL) { + if (!audiodev) { if (classic) { audiodev = SDL_PATH_DEV_AUDIO; } else { diff --git a/src/audio/SDL_audioqueue.c b/src/audio/SDL_audioqueue.c index c27bb4094a2e2..37a2f8457d237 100644 --- a/src/audio/SDL_audioqueue.c +++ b/src/audio/SDL_audioqueue.c @@ -92,7 +92,7 @@ static SDL_AudioChunk *CreateAudioChunk(size_t chunk_size) { SDL_AudioChunk *chunk = (SDL_AudioChunk *)SDL_malloc(sizeof(*chunk) + chunk_size); - if (chunk == NULL) { + if (!chunk) { return NULL; } @@ -146,14 +146,14 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) SDL_AudioChunk *chunk = track->tail; // Handle the first chunk - if (chunk == NULL) { + if (!chunk) { chunk = CreateAudioTrackChunk(track); - if (chunk == NULL) { + if (!chunk) { return SDL_OutOfMemory(); } - SDL_assert((track->head == NULL) && (track->tail == NULL) && (track->queued_bytes == 0)); + SDL_assert((!track->head) && (!track->tail) && (track->queued_bytes == 0)); track->head = chunk; track->tail = chunk; } @@ -180,7 +180,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) } // Roll back the changes if we couldn't write all the data - if (chunk == NULL) { + if (!chunk) { chunk = track->tail; SDL_AudioChunk *next = chunk->next; @@ -255,7 +255,7 @@ static SDL_AudioTrack *CreateChunkedAudioTrack(const SDL_AudioSpec *spec, size_t { SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)SDL_calloc(1, sizeof(*track)); - if (track == NULL) { + if (!track) { SDL_OutOfMemory(); return NULL; } @@ -275,7 +275,7 @@ SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size) { SDL_AudioQueue *queue = (SDL_AudioQueue *)SDL_calloc(1, sizeof(*queue)); - if (queue == NULL) { + if (!queue) { SDL_OutOfMemory(); return NULL; } @@ -338,7 +338,7 @@ void SDL_PopAudioQueueHead(SDL_AudioQueue *queue) queue->head = track; - if (track == NULL) { + if (!track) { queue->tail = NULL; } } @@ -352,7 +352,7 @@ SDL_AudioTrack *SDL_CreateChunkedAudioTrack(const SDL_AudioSpec *spec, const Uin { SDL_AudioTrack *track = CreateChunkedAudioTrack(spec, chunk_size); - if (track == NULL) { + if (!track) { return NULL; } @@ -390,14 +390,14 @@ int SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, cons SDL_AudioTrack *track = queue->tail; - if ((track != NULL) && !AUDIO_SPECS_EQUAL(track->spec, *spec)) { + if ((track) && !AUDIO_SPECS_EQUAL(track->spec, *spec)) { SDL_FlushAudioTrack(track); } - if ((track == NULL) || (track->write == NULL)) { + if ((!track) || (!track->write)) { SDL_AudioTrack *new_track = CreateChunkedAudioTrack(spec, queue->chunk_size); - if (new_track == NULL) { + if (!new_track) { return SDL_OutOfMemory(); } @@ -423,7 +423,7 @@ void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue) size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, SDL_bool *out_flushed) { SDL_AudioTrack *iter = *inout_iter; - SDL_assert(iter != NULL); + SDL_assert(iter); SDL_copyp(out_spec, &iter->spec); @@ -462,7 +462,7 @@ int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) SDL_AudioTrack *track = queue->head; for (;;) { - if (track == NULL) { + if (!track) { return SDL_SetError("Reading past end of queue"); } @@ -478,7 +478,7 @@ int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) SDL_AudioTrack *next = track->next; - if (next == NULL) { + if (!next) { return SDL_SetError("Reading past end of incomplete track"); } @@ -495,7 +495,7 @@ int SDL_PeekIntoAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) SDL_AudioTrack *track = queue->head; for (;;) { - if (track == NULL) { + if (!track) { return SDL_SetError("Peeking past end of queue"); } diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 3701a432096de..76785cf914474 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -262,7 +262,7 @@ static void WaveDebugDumpFormat(WaveFile *file, Uint32 rifflen, Uint32 fmtlen, U int res; dumpstr = SDL_malloc(bufsize); - if (dumpstr == NULL) { + if (!dumpstr) { return; } dumpstr[0] = 0; @@ -439,7 +439,7 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4); file->decoderdata = coeffdata; /* Freed in cleanup. */ - if (coeffdata == NULL) { + if (!coeffdata) { return SDL_OutOfMemory(); } coeffdata->coeff = &coeffdata->aligndummy; @@ -682,7 +682,7 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) state.output.pos = 0; state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_calloc(1, outputsize); - if (state.output.data == NULL) { + if (!state.output.data) { return SDL_OutOfMemory(); } @@ -1073,12 +1073,12 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len state.output.pos = 0; state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_malloc(outputsize); - if (state.output.data == NULL) { + if (!state.output.data) { return SDL_OutOfMemory(); } cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8)); - if (cstate == NULL) { + if (!cstate) { SDL_free(state.output.data); return SDL_OutOfMemory(); } @@ -1233,7 +1233,7 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); - if (src == NULL) { + if (!src) { return SDL_OutOfMemory(); } chunk->data = NULL; @@ -1364,7 +1364,7 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 * /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); - if (ptr == NULL) { + if (!ptr) { return SDL_OutOfMemory(); } @@ -1440,7 +1440,7 @@ static WaveRiffSizeHint WaveGetRiffSizeHint(void) { const char *hint = SDL_GetHint(SDL_HINT_WAVE_RIFF_CHUNK_SIZE); - if (hint != NULL) { + if (hint) { if (SDL_strcmp(hint, "force") == 0) { return RiffSizeForce; } else if (SDL_strcmp(hint, "ignore") == 0) { @@ -1459,7 +1459,7 @@ static WaveTruncationHint WaveGetTruncationHint(void) { const char *hint = SDL_GetHint(SDL_HINT_WAVE_TRUNCATION); - if (hint != NULL) { + if (hint) { if (SDL_strcmp(hint, "verystrict") == 0) { return TruncVeryStrict; } else if (SDL_strcmp(hint, "strict") == 0) { @@ -1478,7 +1478,7 @@ static WaveFactChunkHint WaveGetFactChunkHint(void) { const char *hint = SDL_GetHint(SDL_HINT_WAVE_FACT_CHUNK); - if (hint != NULL) { + if (hint) { if (SDL_strcmp(hint, "truncate") == 0) { return FactTruncate; } else if (SDL_strcmp(hint, "strict") == 0) { @@ -1495,7 +1495,7 @@ static WaveFactChunkHint WaveGetFactChunkHint(void) static void WaveFreeChunkData(WaveChunk *chunk) { - if (chunk->data != NULL) { + if (chunk->data) { SDL_free(chunk->data); chunk->data = NULL; } @@ -1544,7 +1544,7 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len if (length > 0) { chunk->data = (Uint8 *)SDL_malloc(length); - if (chunk->data == NULL) { + if (!chunk->data) { return SDL_OutOfMemory(); } @@ -1610,7 +1610,7 @@ static int WaveReadFormat(WaveFile *file) return SDL_SetError("Data of WAVE fmt chunk too big"); } fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size); - if (fmtsrc == NULL) { + if (!fmtsrc) { return SDL_OutOfMemory(); } @@ -1788,7 +1788,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 * SDL_zero(datachunk); envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT"); - if (envchunkcountlimit != NULL) { + if (envchunkcountlimit) { unsigned int count; if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) { chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32; @@ -2081,15 +2081,15 @@ int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8 WaveFile file; /* Make sure we are passed a valid data source */ - if (src == NULL) { + if (!src) { goto done; /* Error may come from RWops. */ - } else if (spec == NULL) { + } else if (!spec) { SDL_InvalidParamError("spec"); goto done; - } else if (audio_buf == NULL) { + } else if (!audio_buf) { SDL_InvalidParamError("audio_buf"); goto done; - } else if (audio_len == NULL) { + } else if (!audio_len) { SDL_InvalidParamError("audio_len"); goto done; } diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 9d9c98b8eec5e..668ffac05ec3e 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -282,7 +282,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device) if (res != AAUDIO_OK) { LOGI("SDL Failed AAudio_createStreamBuilder %d", res); return SDL_SetError("SDL Failed AAudio_createStreamBuilder %d", res); - } else if (builder == NULL) { + } else if (!builder) { LOGI("SDL Failed AAudio_createStreamBuilder - builder NULL"); return SDL_SetError("SDL Failed AAudio_createStreamBuilder - builder NULL"); } @@ -354,7 +354,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device) hidden->num_buffers = 2; hidden->mixbuf_bytes = (hidden->num_buffers * device->buffer_size); hidden->mixbuf = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), hidden->mixbuf_bytes); - if (hidden->mixbuf == NULL) { + if (!hidden->mixbuf) { return SDL_OutOfMemory(); } hidden->processed_bytes = 0; @@ -384,7 +384,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device) static int AAUDIO_OpenDevice(SDL_AudioDevice *device) { #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES - SDL_assert(device->handle != NULL); // AAUDIO_UNSPECIFIED is zero, so legit devices should all be non-zero. + SDL_assert(device->handle); // AAUDIO_UNSPECIFIED is zero, so legit devices should all be non-zero. #endif LOGI(__func__); @@ -397,7 +397,7 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) } device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -407,7 +407,7 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata) { struct SDL_PrivateAudioData *hidden = (struct SDL_PrivateAudioData *)device->hidden; - if (hidden != NULL) { + if (hidden) { if (hidden->stream) { aaudio_result_t res; @@ -433,7 +433,7 @@ static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata) // Pause (block) all non already paused audio devices by taking their mixer lock void AAUDIO_PauseDevices(void) { - if (ctx.handle != NULL) { // AAUDIO driver is used? + if (ctx.handle) { // AAUDIO driver is used? (void) SDL_FindPhysicalAudioDeviceByCallback(PauseOneDevice, NULL); } } @@ -442,7 +442,7 @@ void AAUDIO_PauseDevices(void) static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata) { struct SDL_PrivateAudioData *hidden = device->hidden; - if (hidden != NULL) { + if (hidden) { if (hidden->resume) { hidden->resume = SDL_FALSE; SDL_UnlockMutex(device->lock); @@ -461,7 +461,7 @@ static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata) void AAUDIO_ResumeDevices(void) { - if (ctx.handle != NULL) { // AAUDIO driver is used? + if (ctx.handle) { // AAUDIO driver is used? (void) SDL_FindPhysicalAudioDeviceByCallback(ResumeOneDevice, NULL); } } @@ -495,7 +495,7 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl) SDL_zero(ctx); ctx.handle = SDL_LoadObject(LIB_AAUDIO_SO); - if (ctx.handle == NULL) { + if (!ctx.handle) { LOGI("SDL couldn't find " LIB_AAUDIO_SO); return SDL_FALSE; } diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 4a076419f9f84..71977c23f5132 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -96,7 +96,7 @@ static void *alsa_handle = NULL; static int load_alsa_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(alsa_handle, fn); - if (*addr == NULL) { + if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } @@ -165,7 +165,7 @@ static int load_alsa_syms(void) static void UnloadALSALibrary(void) { - if (alsa_handle != NULL) { + if (alsa_handle) { SDL_UnloadObject(alsa_handle); alsa_handle = NULL; } @@ -174,9 +174,9 @@ static void UnloadALSALibrary(void) static int LoadALSALibrary(void) { int retval = 0; - if (alsa_handle == NULL) { + if (!alsa_handle) { alsa_handle = SDL_LoadObject(alsa_library); - if (alsa_handle == NULL) { + if (!alsa_handle) { retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { @@ -224,12 +224,12 @@ static const ALSA_Device default_capture_handle = { static const char *get_audio_device(void *handle, const int channels) { - SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3. + SDL_assert(handle); // SDL2 used NULL to mean "default" but that's not true in SDL3. ALSA_Device *dev = (ALSA_Device *)handle; if (SDL_strcmp(dev->name, "default") == 0) { const char *device = SDL_getenv("AUDIODEV"); // Is there a standard variable name? - if (device != NULL) { + if (device) { return device; } else if (channels == 6) { return "plug:surround51"; @@ -536,7 +536,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -682,7 +682,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer if (!iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); @@ -705,7 +705,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A char *desc; char *ptr; - if (dev == NULL) { + if (!dev) { return; } @@ -715,7 +715,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A // Make sure not to free the storage associated with desc in this case if (hint) { desc = ALSA_snd_device_name_get_hint(hint, "DESC"); - if (desc == NULL) { + if (!desc) { SDL_free(dev); return; } @@ -723,13 +723,13 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A desc = (char *)name; } - SDL_assert(name != NULL); + SDL_assert(name); // some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output". // just chop the extra lines off, this seems to get a reasonable device // name without extra details. ptr = SDL_strchr(desc, '\n'); - if (ptr != NULL) { + if (ptr) { *ptr = '\0'; } @@ -784,7 +784,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de // if we can find a preferred prefix for the system. for (int i = 0; hints[i]; i++) { char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME"); - if (name == NULL) { + if (!name) { continue; } @@ -813,16 +813,16 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de if (match || (has_default >= 0)) { // did we find a device name prefix we like at all...? for (int i = 0; hints[i]; i++) { char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME"); - if (name == NULL) { + if (!name) { continue; } // only want physical hardware interfaces const SDL_bool is_default = (has_default == i); - if (is_default || (match != NULL && SDL_strncmp(name, match, match_len) == 0)) { + if (is_default || (match && SDL_strncmp(name, match, match_len) == 0)) { char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID"); - const SDL_bool isoutput = (ioid == NULL) || (SDL_strcmp(ioid, "Output") == 0); - const SDL_bool isinput = (ioid == NULL) || (SDL_strcmp(ioid, "Input") == 0); + const SDL_bool isoutput = (!ioid) || (SDL_strcmp(ioid, "Output") == 0); + const SDL_bool isinput = (!ioid) || (SDL_strcmp(ioid, "Input") == 0); SDL_bool have_output = SDL_FALSE; SDL_bool have_input = SDL_FALSE; @@ -942,7 +942,7 @@ static void ALSA_DeinitializeStart(void) ALSA_Device *next; #if SDL_ALSA_HOTPLUG_THREAD - if (ALSA_hotplug_thread != NULL) { + if (ALSA_hotplug_thread) { SDL_AtomicSet(&ALSA_hotplug_shutdown, 1); SDL_WaitThread(ALSA_hotplug_thread, NULL); ALSA_hotplug_thread = NULL; diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index cd0a942640599..b2147f336828f 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -42,7 +42,7 @@ static SDL_AudioDevice *captureDevice = NULL; static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -131,13 +131,13 @@ void ANDROIDAUDIO_PauseDevices(void) { // TODO: Handle multiple devices? struct SDL_PrivateAudioData *hidden; - if (audioDevice != NULL && audioDevice->hidden != NULL) { + if (audioDevice && audioDevice->hidden) { hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; SDL_LockMutex(audioDevice->lock); hidden->resume = SDL_TRUE; } - if (captureDevice != NULL && captureDevice->hidden != NULL) { + if (captureDevice && captureDevice->hidden) { hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; SDL_LockMutex(captureDevice->lock); hidden->resume = SDL_TRUE; @@ -149,7 +149,7 @@ void ANDROIDAUDIO_ResumeDevices(void) { // TODO: Handle multiple devices? struct SDL_PrivateAudioData *hidden; - if (audioDevice != NULL && audioDevice->hidden != NULL) { + if (audioDevice && audioDevice->hidden) { hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; if (hidden->resume) { hidden->resume = SDL_FALSE; @@ -157,7 +157,7 @@ void ANDROIDAUDIO_ResumeDevices(void) } } - if (captureDevice != NULL && captureDevice->hidden != NULL) { + if (captureDevice && captureDevice->hidden) { hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; if (hidden->resume) { hidden->resume = SDL_FALSE; diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index 74fc522be491a..dc869bc46b377 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -62,7 +62,7 @@ static void DSOUND_Unload(void) pDirectSoundCaptureEnumerateW = NULL; pGetDeviceID = NULL; - if (DSoundDLL != NULL) { + if (DSoundDLL) { SDL_UnloadObject(DSoundDLL); DSoundDLL = NULL; } @@ -75,7 +75,7 @@ static int DSOUND_Load(void) DSOUND_Unload(); DSoundDLL = SDL_LoadObject("DSOUND.DLL"); - if (DSoundDLL == NULL) { + if (!DSoundDLL) { SDL_SetError("DirectSound: failed to load DSOUND.DLL"); } else { // Now make sure we have DirectX 8 or better... @@ -176,7 +176,7 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO FindAllDevsData *data = (FindAllDevsData *) userdata; if (guid != NULL) { // skip default device char *str = WIN_LookupAudioDeviceName(desc, guid); - if (str != NULL) { + if (str) { LPGUID cpyguid = (LPGUID)SDL_malloc(sizeof(GUID)); if (cpyguid) { SDL_copyp(cpyguid, guid); @@ -358,7 +358,7 @@ static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b } SDL_assert(ptr1len == (DWORD)buflen); - SDL_assert(ptr2 == NULL); + SDL_assert(!ptr2); SDL_assert(ptr2len == 0); SDL_memcpy(buffer, ptr1, ptr1len); @@ -384,18 +384,18 @@ static void DSOUND_FlushCapture(SDL_AudioDevice *device) static void DSOUND_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { - if (device->hidden->mixbuf != NULL) { + if (device->hidden->mixbuf) { IDirectSoundBuffer_Stop(device->hidden->mixbuf); IDirectSoundBuffer_Release(device->hidden->mixbuf); } - if (device->hidden->sound != NULL) { + if (device->hidden->sound) { IDirectSound_Release(device->hidden->sound); } - if (device->hidden->capturebuf != NULL) { + if (device->hidden->capturebuf) { IDirectSoundCaptureBuffer_Stop(device->hidden->capturebuf); IDirectSoundCaptureBuffer_Release(device->hidden->capturebuf); } - if (device->hidden->capture != NULL) { + if (device->hidden->capture) { IDirectSoundCapture_Release(device->hidden->capture); } SDL_free(device->hidden); @@ -491,7 +491,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index 69d2d6d35afc2..bdcb8b3be954e 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -87,7 +87,7 @@ static void DISKAUDIO_FlushCapture(SDL_AudioDevice *device) static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { - if (device->hidden->io != NULL) { + if (device->hidden->io) { SDL_RWclose(device->hidden->io); } SDL_free(device->hidden->mixbuf); @@ -99,7 +99,7 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device) static const char *get_filename(const SDL_bool iscapture) { const char *devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE); - if (devname == NULL) { + if (!devname) { devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE; } return devname; @@ -112,11 +112,11 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) const char *envr = SDL_getenv(DISKENVR_IODELAY); device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } - if (envr != NULL) { + if (envr) { device->hidden->io_delay = SDL_atoi(envr); } else { device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq); @@ -124,14 +124,14 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) // Open the "audio device" device->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb"); - if (device->hidden->io == NULL) { + if (!device->hidden->io) { return -1; } // Allocate mixing buffer if (!iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 8178d52a299f5..9a2c918bef467 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -70,7 +70,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -191,7 +191,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 51eec747e1440..64b195221bc7e 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -177,7 +177,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -188,7 +188,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 5772fbe056507..1c223721376ae 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -39,7 +39,7 @@ extern "C" static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { - SDL_assert(device->hidden->current_buffer != NULL); + SDL_assert(device->hidden->current_buffer); SDL_assert(device->hidden->current_buffer_len > 0); *buffer_size = device->hidden->current_buffer_len; return device->hidden->current_buffer; @@ -48,7 +48,7 @@ static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static int HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { // We already wrote our output right into the BSoundPlayer's callback's stream. Just clean up our stuff. - SDL_assert(device->hidden->current_buffer != NULL); + SDL_assert(device->hidden->current_buffer); SDL_assert(device->hidden->current_buffer_len > 0); device->hidden->current_buffer = NULL; device->hidden->current_buffer_len = 0; @@ -59,7 +59,7 @@ static int HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i static void FillSound(void *data, void *stream, size_t len, const media_raw_audio_format & format) { SDL_AudioDevice *device = (SDL_AudioDevice *)data; - SDL_assert(device->hidden->current_buffer == NULL); + SDL_assert(!device->hidden->current_buffer); SDL_assert(device->hidden->current_buffer_len == 0); device->hidden->current_buffer = (Uint8 *) stream; device->hidden->current_buffer_len = (int) len; diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 77e2f03fa9909..78a3dac30e086 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -57,7 +57,7 @@ static void *jack_handle = NULL; static int load_jack_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(jack_handle, fn); - if (*addr == NULL) { + if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } @@ -72,7 +72,7 @@ static int load_jack_sym(const char *fn, void **addr) static void UnloadJackLibrary(void) { - if (jack_handle != NULL) { + if (jack_handle) { SDL_UnloadObject(jack_handle); jack_handle = NULL; } @@ -81,9 +81,9 @@ static void UnloadJackLibrary(void) static int LoadJackLibrary(void) { int retval = 0; - if (jack_handle == NULL) { + if (!jack_handle) { jack_handle = SDL_LoadObject(jack_library); - if (jack_handle == NULL) { + if (!jack_handle) { retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { @@ -296,18 +296,18 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); device->hidden->client = client; - if (client == NULL) { + if (!client) { return SDL_SetError("Can't open JACK client"); } devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags); - if (devports == NULL || !devports[0]) { + if (!devports || !devports[0]) { return SDL_SetError("No physical JACK ports available"); } @@ -349,7 +349,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) // Build SDL's ports, which we will connect to the device ports. device->hidden->sdlports = (jack_port_t **)SDL_calloc(channels, sizeof(jack_port_t *)); - if (device->hidden->sdlports == NULL) { + if (!device->hidden->sdlports) { SDL_free(audio_ports); return SDL_OutOfMemory(); } @@ -414,7 +414,7 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) // Make sure a JACK server is running and available. jack_status_t status; jack_client_t *client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL); - if (client == NULL) { + if (!client) { UnloadJackLibrary(); return SDL_FALSE; } diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index c0bb1a2422369..a515d07d048f3 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -83,7 +83,7 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) float mix[12]; device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -134,14 +134,14 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) } device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); data_vaddr = (Uint8 *)linearAlloc(device->buffer_size * NUM_BUFFERS); - if (data_vaddr == NULL) { + if (!data_vaddr) { return SDL_OutOfMemory(); } diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index ca95a3a1656b7..c5f97eb10c014 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -215,7 +215,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -293,7 +293,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer device->hidden->mixlen = device->buffer_size; device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index 5b7112b20b6a1..22bec9dd6f8de 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -327,7 +327,7 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) // Create the sound buffers audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); - if (audiodata->mixbuff == NULL) { + if (!audiodata->mixbuff) { LOGE("mixbuffer allocate - out of memory"); goto failed; } @@ -574,7 +574,7 @@ static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) // Create the sound buffers audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); - if (audiodata->mixbuff == NULL) { + if (!audiodata->mixbuff) { LOGE("mixbuffer allocate - out of memory"); goto failed; } @@ -599,7 +599,7 @@ static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) static int OPENSLES_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 9c46d770b3f38..2e5586eb8f116 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -126,7 +126,7 @@ static void *pipewire_handle = NULL; static int pipewire_dlsym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pipewire_handle, fn); - if (*addr == NULL) { + if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } @@ -142,7 +142,7 @@ static int pipewire_dlsym(const char *fn, void **addr) static int load_pipewire_library(void) { pipewire_handle = SDL_LoadObject(pipewire_library); - return pipewire_handle != NULL ? 0 : -1; + return pipewire_handle ? 0 : -1; } static void unload_pipewire_library(void) @@ -404,7 +404,7 @@ static void *node_object_new(Uint32 id, const char *type, Uint32 version, const // Create the proxy object proxy = pw_registry_bind(hotplug_registry, id, type, version, sizeof(struct node_object)); - if (proxy == NULL) { + if (!proxy) { SDL_SetError("Pipewire: Failed to create proxy object (%i)", errno); return NULL; } @@ -623,16 +623,16 @@ static int metadata_property(void *object, Uint32 subject, const char *key, cons { struct node_object *node = object; - if (subject == PW_ID_CORE && key != NULL && value != NULL) { + if (subject == PW_ID_CORE && key && value) { if (!SDL_strcmp(key, "default.audio.sink")) { - if (pipewire_default_sink_id != NULL) { + if (pipewire_default_sink_id) { SDL_free(pipewire_default_sink_id); } pipewire_default_sink_id = get_name_from_json(value); node->persist = SDL_TRUE; change_default_device(pipewire_default_sink_id); } else if (!SDL_strcmp(key, "default.audio.source")) { - if (pipewire_default_source_id != NULL) { + if (pipewire_default_source_id) { SDL_free(pipewire_default_source_id); } pipewire_default_source_id = get_name_from_json(value); @@ -678,7 +678,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p if (node_desc && node_path) { node = node_object_new(id, type, version, &interface_node_events, &interface_core_events); - if (node == NULL) { + if (!node) { SDL_SetError("Pipewire: Failed to allocate interface node"); return; } @@ -687,7 +687,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p desc_buffer_len = SDL_strlen(node_desc) + 1; path_buffer_len = SDL_strlen(node_path) + 1; node->userdata = io = SDL_calloc(1, sizeof(struct io_node) + desc_buffer_len + path_buffer_len); - if (io == NULL) { + if (!io) { node_object_destroy(node); SDL_OutOfMemory(); return; @@ -708,7 +708,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p } } else if (!SDL_strcmp(type, PW_TYPE_INTERFACE_Metadata)) { node = node_object_new(id, type, version, &metadata_node_events, &metadata_core_events); - if (node == NULL) { + if (!node) { SDL_SetError("Pipewire: Failed to allocate metadata node"); return; } @@ -736,22 +736,22 @@ static int hotplug_loop_init(void) spa_list_init(&hotplug_io_list); hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLAudioHotplug", NULL); - if (hotplug_loop == NULL) { + if (!hotplug_loop) { return SDL_SetError("Pipewire: Failed to create hotplug detection loop (%i)", errno); } hotplug_context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(hotplug_loop), NULL, 0); - if (hotplug_context == NULL) { + if (!hotplug_context) { return SDL_SetError("Pipewire: Failed to create hotplug detection context (%i)", errno); } hotplug_core = PIPEWIRE_pw_context_connect(hotplug_context, NULL, 0); - if (hotplug_core == NULL) { + if (!hotplug_core) { return SDL_SetError("Pipewire: Failed to connect hotplug detection context (%i)", errno); } hotplug_registry = pw_core_get_registry(hotplug_core, PW_VERSION_REGISTRY, 0); - if (hotplug_registry == NULL) { + if (!hotplug_registry) { return SDL_SetError("Pipewire: Failed to acquire hotplug detection registry (%i)", errno); } @@ -783,11 +783,11 @@ static void hotplug_loop_destroy(void) hotplug_init_complete = SDL_FALSE; hotplug_events_enabled = SDL_FALSE; - if (pipewire_default_sink_id != NULL) { + if (pipewire_default_sink_id) { SDL_free(pipewire_default_sink_id); pipewire_default_sink_id = NULL; } - if (pipewire_default_source_id != NULL) { + if (pipewire_default_source_id) { SDL_free(pipewire_default_source_id); pipewire_default_source_id = NULL; } @@ -826,10 +826,10 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe spa_list_for_each (io, &hotplug_io_list, link) { SDL_AudioDevice *device = SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id)); - if (pipewire_default_sink_id != NULL && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { + if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { SDL_assert(!io->is_capture); *default_output = device; - } else if (pipewire_default_source_id != NULL && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { + } else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { SDL_assert(io->is_capture); *default_capture = device; } @@ -965,7 +965,7 @@ static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device) { struct pw_stream *stream = device->hidden->stream; struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream); - if (pw_buf != NULL) { // just requeue it without any further thought. + if (pw_buf) { // just requeue it without any further thought. PIPEWIRE_pw_stream_queue_buffer(stream, pw_buf); } } @@ -1062,7 +1062,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) struct SDL_PrivateAudioData *priv; struct pw_properties *props; const char *app_name, *app_id, *stream_name, *stream_role, *error; - Uint32 node_id = device->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle); + Uint32 node_id = !device->handle ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle); const SDL_bool iscapture = device->iscapture; int res; @@ -1071,9 +1071,9 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) // Get the hints for the application name, stream name and role app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); - if (app_name == NULL || *app_name == '\0') { + if (!app_name || *app_name == '\0') { app_name = SDL_GetHint(SDL_HINT_APP_NAME); - if (app_name == NULL || *app_name == '\0') { + if (!app_name || *app_name == '\0') { app_name = "SDL Application"; } } @@ -1082,7 +1082,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) app_id = SDL_GetHint(SDL_HINT_APP_ID); stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); - if (stream_name == NULL || *stream_name == '\0') { + if (!stream_name || *stream_name == '\0') { stream_name = "Audio Stream"; } @@ -1091,20 +1091,20 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) * but 'Game' seems more appropriate for the majority of SDL applications. */ stream_role = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_ROLE); - if (stream_role == NULL || *stream_role == '\0') { + if (!stream_role || *stream_role == '\0') { stream_role = "Game"; } // Initialize the Pipewire stream info from the SDL audio spec initialize_spa_info(&device->spec, &spa_info); params = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &spa_info); - if (params == NULL) { + if (!params) { return SDL_SetError("Pipewire: Failed to set audio format parameters"); } priv = SDL_calloc(1, sizeof(struct SDL_PrivateAudioData)); device->hidden = priv; - if (priv == NULL) { + if (!priv) { return SDL_OutOfMemory(); } @@ -1119,23 +1119,23 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) SDL_GetAudioThreadName(device, thread_name, sizeof(thread_name)); priv->loop = PIPEWIRE_pw_thread_loop_new(thread_name, NULL); - if (priv->loop == NULL) { + if (!priv->loop) { return SDL_SetError("Pipewire: Failed to create stream loop (%i)", errno); } // Load the realtime module so Pipewire can set the loop thread to the appropriate priority. props = PIPEWIRE_pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", NULL); - if (props == NULL) { + if (!props) { return SDL_SetError("Pipewire: Failed to create stream context properties (%i)", errno); } priv->context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), props, 0); - if (priv->context == NULL) { + if (!priv->context) { return SDL_SetError("Pipewire: Failed to create stream context (%i)", errno); } props = PIPEWIRE_pw_properties_new(NULL, NULL); - if (props == NULL) { + if (!props) { return SDL_SetError("Pipewire: Failed to create stream properties (%i)", errno); } @@ -1143,7 +1143,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, iscapture ? "Capture" : "Playback"); PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_ROLE, stream_role); PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name); - if (app_id != NULL) { + if (app_id) { PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ID, app_id); } PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_NAME, stream_name); @@ -1165,7 +1165,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) PIPEWIRE_pw_thread_loop_lock(hotplug_loop); node = io_list_get_by_id(node_id); - if (node != NULL) { + if (node) { PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path); } PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); @@ -1177,7 +1177,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) // Create the new stream priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props, iscapture ? &stream_input_events : &stream_output_events, device); - if (priv->stream == NULL) { + if (!priv->stream) { return SDL_SetError("Pipewire: Failed to create stream (%i)", errno); } diff --git a/src/audio/ps2/SDL_ps2audio.c b/src/audio/ps2/SDL_ps2audio.c index 78717cc12a2e9..fd64d86e1b5dc 100644 --- a/src/audio/ps2/SDL_ps2audio.c +++ b/src/audio/ps2/SDL_ps2audio.c @@ -30,7 +30,7 @@ static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -73,7 +73,7 @@ static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device) 64, so spec->size should be a multiple of 64 as well. */ const int mixlen = device->buffer_size * NUM_BUFFERS; device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen); - if (device->hidden->rawbuf == NULL) { + if (!device->hidden->rawbuf) { return SDL_SetError("Couldn't allocate mixing buffer"); } @@ -112,7 +112,7 @@ static void PS2AUDIO_CloseDevice(SDL_AudioDevice *device) device->hidden->channel = -1; } - if (device->hidden->rawbuf != NULL) { + if (device->hidden->rawbuf) { SDL_aligned_free(device->hidden->rawbuf); device->hidden->rawbuf = NULL; } diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index ff9bb358f3fe3..057b4b14f6bf2 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -41,7 +41,7 @@ static inline SDL_bool isBasicAudioConfig(const SDL_AudioSpec *spec) static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -93,7 +93,7 @@ static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device) 64, so spec->size should be a multiple of 64 as well. */ const int mixlen = device->buffer_size * NUM_BUFFERS; device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen); - if (device->hidden->rawbuf == NULL) { + if (!device->hidden->rawbuf) { return SDL_SetError("Couldn't allocate mixing buffer"); } @@ -141,7 +141,7 @@ static void PSPAUDIO_CloseDevice(SDL_AudioDevice *device) device->hidden->channel = -1; } - if (device->hidden->rawbuf != NULL) { + if (device->hidden->rawbuf) { SDL_aligned_free(device->hidden->rawbuf); device->hidden->rawbuf = NULL; } diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 0612d88089f73..4cf9a6cf0fd2c 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -135,7 +135,7 @@ static void *pulseaudio_handle = NULL; static int load_pulseaudio_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pulseaudio_handle, fn); - if (*addr == NULL) { + if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. return 0; } @@ -150,7 +150,7 @@ static int load_pulseaudio_sym(const char *fn, void **addr) static void UnloadPulseAudioLibrary(void) { - if (pulseaudio_handle != NULL) { + if (pulseaudio_handle) { SDL_UnloadObject(pulseaudio_handle); pulseaudio_handle = NULL; } @@ -159,9 +159,9 @@ static void UnloadPulseAudioLibrary(void) static int LoadPulseAudioLibrary(void) { int retval = 0; - if (pulseaudio_handle == NULL) { + if (!pulseaudio_handle) { pulseaudio_handle = SDL_LoadObject(pulseaudio_library); - if (pulseaudio_handle == NULL) { + if (!pulseaudio_handle) { retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { @@ -275,7 +275,7 @@ static const char *getAppName(void) } else { const char *verstr = PULSEAUDIO_pa_get_library_version(); retval = "SDL Application"; // the "oh well" default. - if (verstr != NULL) { + if (verstr) { int maj, min, patch; if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) { if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) { @@ -297,13 +297,13 @@ static void OperationStateChangeCallback(pa_operation *o, void *userdata) static void WaitForPulseOperation(pa_operation *o) { // This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. - SDL_assert(pulseaudio_threaded_mainloop != NULL); + SDL_assert(pulseaudio_threaded_mainloop); if (o) { // note that if PULSEAUDIO_pa_operation_set_state_callback == NULL, then `o` must have a callback that will signal pulseaudio_threaded_mainloop. // If not, on really old (earlier PulseAudio 4.0, from the year 2013!) installs, this call will block forever. // On more modern installs, we won't ever block forever, and maybe be more efficient, thanks to pa_operation_set_state_callback. // WARNING: at the time of this writing: the Steam Runtime is still on PulseAudio 1.1! - if (PULSEAUDIO_pa_operation_set_state_callback != NULL) { + if (PULSEAUDIO_pa_operation_set_state_callback) { PULSEAUDIO_pa_operation_set_state_callback(o, OperationStateChangeCallback, NULL); } while (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING) { @@ -315,7 +315,7 @@ static void WaitForPulseOperation(pa_operation *o) static void DisconnectFromPulseServer(void) { - if (pulseaudio_threaded_mainloop != NULL) { + if (pulseaudio_threaded_mainloop) { PULSEAUDIO_pa_threaded_mainloop_stop(pulseaudio_threaded_mainloop); } if (pulseaudio_context) { @@ -323,7 +323,7 @@ static void DisconnectFromPulseServer(void) PULSEAUDIO_pa_context_unref(pulseaudio_context); pulseaudio_context = NULL; } - if (pulseaudio_threaded_mainloop != NULL) { + if (pulseaudio_threaded_mainloop) { PULSEAUDIO_pa_threaded_mainloop_free(pulseaudio_threaded_mainloop); pulseaudio_threaded_mainloop = NULL; } @@ -339,8 +339,8 @@ static int ConnectToPulseServer(void) pa_mainloop_api *mainloop_api = NULL; int state = 0; - SDL_assert(pulseaudio_threaded_mainloop == NULL); - SDL_assert(pulseaudio_context == NULL); + SDL_assert(!pulseaudio_threaded_mainloop); + SDL_assert(!pulseaudio_context); // Set up a new main loop if (!(pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new())) { @@ -363,7 +363,7 @@ static int ConnectToPulseServer(void) SDL_assert(mainloop_api); // this never fails, right? pulseaudio_context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName()); - if (pulseaudio_context == NULL) { + if (!pulseaudio_context) { SDL_SetError("pa_context_new() failed"); goto failed; } @@ -480,7 +480,7 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; - if (h->capturebuf != NULL) { + if (h->capturebuf) { return 0; // there's still data available to read. } @@ -500,7 +500,7 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) size_t nbytes = 0; PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes); SDL_assert(nbytes > 0); - if (data == NULL) { // If NULL, then the buffer had a hole, ignore that + if (!data) { // If NULL, then the buffer had a hole, ignore that PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment. } else { // store this fragment's data for use with CaptureFromDevice @@ -521,7 +521,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i { struct SDL_PrivateAudioData *h = device->hidden; - if (h->capturebuf != NULL) { + if (h->capturebuf) { const int cpy = SDL_min(buflen, h->capturelen); if (cpy > 0) { //SDL_Log("PULSEAUDIO: fed %d captured bytes", cpy); @@ -549,7 +549,7 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - if (h->capturebuf != NULL) { + if (h->capturebuf) { PULSEAUDIO_pa_stream_drop(h->stream); h->capturebuf = NULL; h->capturelen = 0; @@ -578,7 +578,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); if (device->hidden->stream) { - if (device->hidden->capturebuf != NULL) { + if (device->hidden->capturebuf) { PULSEAUDIO_pa_stream_drop(device->hidden->stream); } PULSEAUDIO_pa_stream_disconnect(device->hidden->stream); @@ -609,12 +609,12 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) int format = PA_SAMPLE_INVALID; int retval = 0; - SDL_assert(pulseaudio_threaded_mainloop != NULL); - SDL_assert(pulseaudio_context != NULL); + SDL_assert(pulseaudio_threaded_mainloop); + SDL_assert(pulseaudio_context); // Initialize all variables that we clean on shutdown h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -663,7 +663,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer if (!iscapture) { h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (h->mixbuf == NULL) { + if (!h->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(h->mixbuf, device->silence_value, device->buffer_size); @@ -694,7 +694,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) &pacmap // channel map ); - if (h->stream == NULL) { + if (!h->stream) { retval = SDL_SetError("Could not set up PulseAudio stream"); } else { int rc; diff --git a/src/audio/qnx/SDL_qsa_audio.c b/src/audio/qnx/SDL_qsa_audio.c index e6de9e6f7a2e9..27e21d721f7ee 100644 --- a/src/audio/qnx/SDL_qsa_audio.c +++ b/src/audio/qnx/SDL_qsa_audio.c @@ -176,7 +176,7 @@ static Uint8 *QSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static void QSA_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { - if (device->hidden->audio_handle != NULL) { + if (device->hidden->audio_handle) { #if _NTO_VERSION < 710 // Finish playing available samples or cancel unread samples during capture snd_pcm_plugin_flush(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 8cca105d5b0fb..970e2e9078ff4 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -71,7 +71,7 @@ static void *sndio_handle = NULL; static int load_sndio_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(sndio_handle, fn); - if (*addr == NULL) { + if (!*addr) { return 0; // Don't call SDL_SetError(): SDL_LoadFunction already did. } @@ -110,7 +110,7 @@ static int load_sndio_syms(void) static void UnloadSNDIOLibrary(void) { - if (sndio_handle != NULL) { + if (sndio_handle) { SDL_UnloadObject(sndio_handle); sndio_handle = NULL; } @@ -119,9 +119,9 @@ static void UnloadSNDIOLibrary(void) static int LoadSNDIOLibrary(void) { int retval = 0; - if (sndio_handle == NULL) { + if (!sndio_handle) { sndio_handle = SDL_LoadObject(sndio_library); - if (sndio_handle == NULL) { + if (!sndio_handle) { retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { retval = load_sndio_syms(); @@ -213,7 +213,7 @@ static Uint8 *SNDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static void SNDIO_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { - if (device->hidden->dev != NULL) { + if (device->hidden->dev) { SNDIO_sio_stop(device->hidden->dev); SNDIO_sio_close(device->hidden->dev); } @@ -227,7 +227,7 @@ static void SNDIO_CloseDevice(SDL_AudioDevice *device) static int SNDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } @@ -235,14 +235,14 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) const char *audiodev = SDL_getenv("AUDIODEV"); // Capture devices must be non-blocking for SNDIO_FlushCapture - device->hidden->dev = SNDIO_sio_open(audiodev != NULL ? audiodev : SIO_DEVANY, + device->hidden->dev = SNDIO_sio_open(audiodev ? audiodev : SIO_DEVANY, device->iscapture ? SIO_REC : SIO_PLAY, device->iscapture); - if (device->hidden->dev == NULL) { + if (!device->hidden->dev) { return SDL_SetError("sio_open() failed"); } device->hidden->pfd = SDL_malloc(sizeof(struct pollfd) * SNDIO_sio_nfds(device->hidden->dev)); - if (device->hidden->pfd == NULL) { + if (!device->hidden->pfd) { return SDL_OutOfMemory(); } @@ -307,7 +307,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); - if (device->hidden->mixbuf == NULL) { + if (!device->hidden->mixbuf) { return SDL_OutOfMemory(); } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index 705d19ede13f7..7e7c6060820a2 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -63,7 +63,7 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *) SDL_malloc(sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } SDL_memset(device->hidden, 0, sizeof(*device->hidden)); @@ -95,7 +95,7 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) 64, so spec->size should be a multiple of 64 as well. */ mixlen = device->buffer_size * NUM_BUFFERS; device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen); - if (device->hidden->rawbuf == NULL) { + if (!device->hidden->rawbuf) { return SDL_SetError("Couldn't allocate mixing buffer"); } @@ -163,7 +163,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device) device->hidden->port = -1; } - if (!device->iscapture && device->hidden->rawbuf != NULL) { + if (!device->iscapture && device->hidden->rawbuf) { SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc() device->hidden->rawbuf = NULL; } diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index ffbeeec343c42..c7d251d6eb821 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -93,7 +93,7 @@ static void ManagementThreadMainloop(void) int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_on_result) { // We want to block for a result, but we are already running from the management thread! Just run the task now so we don't deadlock. - if ((wait_on_result != NULL) && (SDL_ThreadID() == SDL_GetThreadID(ManagementThread))) { + if ((wait_on_result) && (SDL_ThreadID() == SDL_GetThreadID(ManagementThread))) { *wait_on_result = task(userdata); return 0; // completed! } @@ -124,11 +124,11 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in // add to end of task list. ManagementThreadPendingTask *prev = NULL; - for (ManagementThreadPendingTask *i = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks); i != NULL; i = i->next) { + for (ManagementThreadPendingTask *i = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks); i; i = i->next) { prev = i; } - if (prev != NULL) { + if (prev) { prev->next = pending; } else { SDL_AtomicSetPtr((void **) &ManagementThreadPendingTasks, pending); @@ -413,7 +413,7 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) if (device->hidden->render) { if (WasapiFailed(device, IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer))) { - SDL_assert(buffer == NULL); + SDL_assert(!buffer); if (device->hidden->device_lost) { // just use an available buffer, we won't be playing it anyhow. *buffer_size = 0; // we'll recover during WaitDevice and try again. } @@ -425,7 +425,7 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static int WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { - if (device->hidden->render != NULL) { // definitely activated? + if (device->hidden->render) { // definitely activated? // WasapiFailed() will mark the device for reacquisition or removal elsewhere. WasapiFailed(device, IAudioRenderClient_ReleaseBuffer(device->hidden->render, device->sample_frames, 0)); } @@ -542,7 +542,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) const AUDCLNT_SHAREMODE sharemode = AUDCLNT_SHAREMODE_SHARED; IAudioClient *client = device->hidden->client; - SDL_assert(client != NULL); + SDL_assert(client); #if defined(__WINRT__) || defined(__GDK__) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP. device->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); @@ -550,7 +550,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) device->hidden->event = CreateEventW(NULL, 0, 0, NULL); #endif - if (device->hidden->event == NULL) { + if (!device->hidden->event) { return WIN_SetError("WASAPI can't create an event handle"); } @@ -561,7 +561,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) if (FAILED(ret)) { return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret); } - SDL_assert(waveformat != NULL); + SDL_assert(waveformat); device->hidden->waveformat = waveformat; SDL_AudioSpec newspec; @@ -642,7 +642,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't get capture client service", ret); } - SDL_assert(capture != NULL); + SDL_assert(capture); device->hidden->capture = capture; ret = IAudioClient_Start(client); if (FAILED(ret)) { @@ -657,7 +657,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't get render client service", ret); } - SDL_assert(render != NULL); + SDL_assert(render); device->hidden->render = render; ret = IAudioClient_Start(client); if (FAILED(ret)) { @@ -679,7 +679,7 @@ static int WASAPI_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); - if (device->hidden == NULL) { + if (!device->hidden) { return SDL_OutOfMemory(); } else if (ActivateWasapiDevice(device) < 0) { return -1; // already set error. diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index db8397c416675..25af3225cd530 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -164,11 +164,11 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device) IMMDevice_Release(immdevice); if (FAILED(ret)) { - SDL_assert(device->hidden->client == NULL); + SDL_assert(!device->hidden->client); return WIN_SetErrorFromHRESULT("WASAPI can't activate audio endpoint", ret); } - SDL_assert(device->hidden->client != NULL); + SDL_assert(device->hidden->client); if (WASAPI_PrepDevice(device) == -1) { // not async, fire it right away. return -1; } diff --git a/src/core/SDL_runapp.c b/src/core/SDL_runapp.c index 02e25c6948f0b..faa2a924bb83e 100644 --- a/src/core/SDL_runapp.c +++ b/src/core/SDL_runapp.c @@ -32,7 +32,7 @@ SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved) (void)reserved; - if(argv == NULL) + if(!argv) { argc = 0; /* make sure argv isn't NULL, in case some user code doesn't like that */ diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 8626a6b6f56f4..63bd79d6524c4 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -434,12 +434,12 @@ JNIEnv *Android_JNI_GetEnv(void) { /* Get JNIEnv from the Thread local storage */ JNIEnv *env = pthread_getspecific(mThreadKey); - if (env == NULL) { + if (!env) { /* If it fails, try to attach ! (e.g the thread isn't created with SDL_CreateThread() */ int status; /* There should be a JVM */ - if (mJavaVM == NULL) { + if (!mJavaVM) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM"); return NULL; } @@ -468,7 +468,7 @@ int Android_JNI_SetupThread(void) int status; /* There should be a JVM */ - if (mJavaVM == NULL) { + if (!mJavaVM) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM"); return 0; } @@ -494,7 +494,7 @@ static void Android_JNI_ThreadDestroyed(void *value) { /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */ JNIEnv *env = (JNIEnv *)value; - if (env != NULL) { + if (env) { (*mJavaVM)->DetachCurrentThread(mJavaVM); Android_JNI_SetEnv(NULL); } @@ -520,7 +520,7 @@ static void Android_JNI_CreateKey_once(void) static void register_methods(JNIEnv *env, const char *classname, JNINativeMethod *methods, int nb) { jclass clazz = (*env)->FindClass(env, classname); - if (clazz == NULL || (*env)->RegisterNatives(env, clazz, methods, nb) < 0) { + if (!clazz || (*env)->RegisterNatives(env, clazz, methods, nb) < 0) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed to register methods of %s", classname); return; } @@ -582,28 +582,28 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl /* Save JNIEnv of SDLActivity */ Android_JNI_SetEnv(env); - if (mJavaVM == NULL) { + if (!mJavaVM) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to found a JavaVM"); } /* Use a mutex to prevent concurrency issues between Java Activity and Native thread code, when using 'Android_Window'. * (Eg. Java sending Touch events, while native code is destroying the main SDL_Window. ) */ - if (Android_ActivityMutex == NULL) { + if (!Android_ActivityMutex) { Android_ActivityMutex = SDL_CreateMutex(); /* Could this be created twice if onCreate() is called a second time ? */ } - if (Android_ActivityMutex == NULL) { + if (!Android_ActivityMutex) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex"); } Android_PauseSem = SDL_CreateSemaphore(0); - if (Android_PauseSem == NULL) { + if (!Android_PauseSem) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_PauseSem semaphore"); } Android_ResumeSem = SDL_CreateSemaphore(0); - if (Android_ResumeSem == NULL) { + if (!Android_ResumeSem) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ResumeSem semaphore"); } @@ -1614,7 +1614,7 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device) __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output"); result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id); } - if (result == NULL) { + if (!result) { /* Error during audio initialization, error printed from Java */ return SDL_SetError("Java-side initialization failed"); } @@ -1675,7 +1675,7 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device) return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat); } - if (jbufobj == NULL) { + if (!jbufobj) { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer"); return SDL_OutOfMemory(); } @@ -1946,7 +1946,7 @@ static void Internal_Android_Create_AssetManager() javaAssetManagerRef = (*env)->NewGlobalRef(env, javaAssetManager); asset_manager = AAssetManager_fromJava(env, javaAssetManagerRef); - if (asset_manager == NULL) { + if (!asset_manager) { (*env)->DeleteGlobalRef(env, javaAssetManagerRef); Android_JNI_ExceptionOccurred(SDL_TRUE); } @@ -1970,16 +1970,16 @@ int Android_JNI_FileOpen(SDL_RWops *ctx, AAsset *asset = NULL; ctx->hidden.androidio.asset = NULL; - if (asset_manager == NULL) { + if (!asset_manager) { Internal_Android_Create_AssetManager(); } - if (asset_manager == NULL) { + if (!asset_manager) { return SDL_SetError("Couldn't create asset manager"); } asset = AAssetManager_open(asset_manager, fileName, AASSET_MODE_UNKNOWN); - if (asset == NULL) { + if (!asset) { return SDL_SetError("Couldn't open asset '%s'", fileName); } @@ -2051,7 +2051,7 @@ char *Android_JNI_GetClipboardText(void) (*env)->DeleteLocalRef(env, string); } - return (text == NULL) ? SDL_strdup("") : text; + return (!text) ? SDL_strdup("") : text; } SDL_bool Android_JNI_HasClipboardText(void) @@ -2371,7 +2371,7 @@ void *SDL_AndroidGetActivity(void) /* See SDL_system.h for caveats on using this function. */ JNIEnv *env = Android_JNI_GetEnv(); - if (env == NULL) { + if (!env) { return NULL; } @@ -2425,7 +2425,7 @@ const char *SDL_AndroidGetInternalStoragePath(void) { static char *s_AndroidInternalFilesPath = NULL; - if (s_AndroidInternalFilesPath == NULL) { + if (!s_AndroidInternalFilesPath) { struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); jmethodID mid; jobject context; @@ -2524,7 +2524,7 @@ const char *SDL_AndroidGetExternalStoragePath(void) { static char *s_AndroidExternalFilesPath = NULL; - if (s_AndroidExternalFilesPath == NULL) { + if (!s_AndroidExternalFilesPath) { struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); jmethodID mid; jobject context; @@ -2680,16 +2680,16 @@ int Android_JNI_GetLocale(char *buf, size_t buflen) /* Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED) */ Internal_Android_Destroy_AssetManager(); - if (asset_manager == NULL) { + if (!asset_manager) { Internal_Android_Create_AssetManager(); } - if (asset_manager == NULL) { + if (!asset_manager) { return -1; } cfg = AConfiguration_new(); - if (cfg == NULL) { + if (!cfg) { return -1; } diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c index e9129feeb8c4a..a89003ed2227b 100644 --- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -87,7 +87,7 @@ static void kbd_cleanup(void) { struct mouse_info mData; SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state; - if (kbd == NULL) { + if (!kbd) { return; } kbd_cleanup_state = NULL; @@ -178,7 +178,7 @@ static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd) { int tabidx; - if (kbd_cleanup_state != NULL) { + if (kbd_cleanup_state) { return; } kbd_cleanup_state = kbd; @@ -230,7 +230,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) SDL_zero(mData); mData.operation = MOUSE_HIDE; kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state)); - if (kbd == NULL) { + if (!kbd) { return NULL; } @@ -296,7 +296,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) { struct mouse_info mData; - if (kbd == NULL) { + if (!kbd) { return; } SDL_zero(mData); @@ -486,7 +486,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, unsigned int final_key_state; unsigned int map_from_key_sym; - if (kbd == NULL) { + if (!kbd) { return; } diff --git a/src/core/haiku/SDL_BeApp.cc b/src/core/haiku/SDL_BeApp.cc index 8403f9a18c6b8..7f62bc52e4c4a 100644 --- a/src/core/haiku/SDL_BeApp.cc +++ b/src/core/haiku/SDL_BeApp.cc @@ -108,13 +108,13 @@ static int StartBeLooper() { if (!be_app) { SDL_AppThread = SDL_CreateThreadInternal(StartBeApp, "SDLApplication", 0, NULL); - if (SDL_AppThread == NULL) { + if (!SDL_AppThread) { return SDL_SetError("Couldn't create BApplication thread"); } do { SDL_Delay(10); - } while ((be_app == NULL) || be_app->IsLaunching()); + } while ((!be_app) || be_app->IsLaunching()); } /* Change working directory to that of executable */ @@ -167,7 +167,7 @@ void SDL_QuitBeApp(void) SDL_Looper->Lock(); SDL_Looper->Quit(); SDL_Looper = NULL; - if (SDL_AppThread != NULL) { + if (SDL_AppThread) { if (be_app != NULL) { /* Not tested */ be_app->PostMessage(B_QUIT_REQUESTED); } diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index 14154319f1e28..900e1a1b248dc 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -96,7 +96,7 @@ static int LoadDBUSSyms(void) static void UnloadDBUSLibrary(void) { - if (dbus_handle != NULL) { + if (dbus_handle) { SDL_UnloadObject(dbus_handle); dbus_handle = NULL; } @@ -105,9 +105,9 @@ static void UnloadDBUSLibrary(void) static int LoadDBUSLibrary(void) { int retval = 0; - if (dbus_handle == NULL) { + if (!dbus_handle) { dbus_handle = SDL_LoadObject(dbus_library); - if (dbus_handle == NULL) { + if (!dbus_handle) { retval = -1; /* Don't call SDL_SetError(): SDL_LoadObject already did. */ } else { @@ -199,7 +199,7 @@ void SDL_DBus_Quit(void) SDL_DBusContext *SDL_DBus_GetContext(void) { - if (dbus_handle == NULL || !dbus.session_conn) { + if (!dbus_handle || !dbus.session_conn) { SDL_DBus_Init(); } @@ -360,7 +360,7 @@ SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char * void SDL_DBus_ScreensaverTickle(void) { - if (screensaver_cookie == 0 && inhibit_handle == NULL) { /* no need to tickle if we're inhibiting. */ + if (screensaver_cookie == 0 && !inhibit_handle) { /* no need to tickle if we're inhibiting. */ /* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */ SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID); SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID); @@ -428,7 +428,7 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) { const char *default_inhibit_reason = "Playing a game"; - if ((inhibit && (screensaver_cookie != 0 || inhibit_handle != NULL)) || (!inhibit && (screensaver_cookie == 0 && inhibit_handle == NULL))) { + if ((inhibit && (screensaver_cookie != 0 || inhibit_handle)) || (!inhibit && (screensaver_cookie == 0 && !inhibit_handle))) { return SDL_TRUE; } @@ -452,12 +452,12 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) const char *key = "reason"; const char *reply = NULL; const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME); - if (reason == NULL || !reason[0]) { + if (!reason || !reason[0]) { reason = default_inhibit_reason; } msg = dbus.message_new_method_call(bus_name, path, interface, "Inhibit"); - if (msg == NULL) { + if (!msg) { return SDL_FALSE; } @@ -496,10 +496,10 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) if (inhibit) { const char *app = SDL_GetHint(SDL_HINT_APP_NAME); const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME); - if (app == NULL || !app[0]) { + if (!app || !app[0]) { app = "My SDL application"; } - if (reason == NULL || !reason[0]) { + if (!reason || !reason[0]) { reason = default_inhibit_reason; } diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index 9ca3bdfaf7b7a..38f28602e9aa0 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -167,9 +167,9 @@ static void SDL_EVDEV_UpdateKeyboardMute(void) int SDL_EVDEV_Init(void) { - if (_this == NULL) { + if (!_this) { _this = (SDL_EVDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); - if (_this == NULL) { + if (!_this) { return SDL_OutOfMemory(); } @@ -231,7 +231,7 @@ int SDL_EVDEV_Init(void) void SDL_EVDEV_Quit(void) { - if (_this == NULL) { + if (!_this) { return; } @@ -244,14 +244,14 @@ void SDL_EVDEV_Quit(void) #endif /* SDL_USE_LIBUDEV */ /* Remove existing devices */ - while (_this->first != NULL) { + while (_this->first) { SDL_EVDEV_device_removed(_this->first->path); } SDL_EVDEV_kbd_quit(_this->kbd); - SDL_assert(_this->first == NULL); - SDL_assert(_this->last == NULL); + SDL_assert(!_this->first); + SDL_assert(!_this->last); SDL_assert(_this->num_devices == 0); SDL_free(_this); @@ -263,7 +263,7 @@ void SDL_EVDEV_Quit(void) static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class, const char *dev_path) { - if (dev_path == NULL) { + if (!dev_path) { return; } @@ -301,7 +301,7 @@ int SDL_EVDEV_GetDeviceCount(int device_class) SDL_evdevlist_item *item; int count = 0; - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { if ((item->udev_class & device_class) == device_class) { ++count; } @@ -331,7 +331,7 @@ void SDL_EVDEV_Poll(void) mouse = SDL_GetMouse(); - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { while ((len = read(item->fd, events, sizeof(events))) > 0) { len /= sizeof(events[0]); for (i = 0; i < len; ++i) { @@ -643,7 +643,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) } item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data)); - if (item->touchscreen_data == NULL) { + if (!item->touchscreen_data) { return SDL_OutOfMemory(); } @@ -654,7 +654,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) } item->touchscreen_data->name = SDL_strdup(name); - if (item->touchscreen_data->name == NULL) { + if (!item->touchscreen_data->name) { SDL_free(item->touchscreen_data); return SDL_OutOfMemory(); } @@ -709,7 +709,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) item->touchscreen_data->slots = SDL_calloc( item->touchscreen_data->max_slots, sizeof(*item->touchscreen_data->slots)); - if (item->touchscreen_data->slots == NULL) { + if (!item->touchscreen_data->slots) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return SDL_OutOfMemory(); @@ -770,7 +770,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) sizeof(*mt_req_values) * item->touchscreen_data->max_slots; mt_req_code = SDL_calloc(1, mt_req_size); - if (mt_req_code == NULL) { + if (!mt_req_code) { return; } @@ -875,14 +875,14 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) unsigned long relbit[NBITS(REL_MAX)] = { 0 }; /* Check to make sure it's not already in list. */ - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { if (SDL_strcmp(dev_path, item->path) == 0) { return -1; /* already have this one */ } } item = (SDL_evdevlist_item *)SDL_calloc(1, sizeof(SDL_evdevlist_item)); - if (item == NULL) { + if (!item) { return SDL_OutOfMemory(); } @@ -893,7 +893,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) } item->path = SDL_strdup(dev_path); - if (item->path == NULL) { + if (!item->path) { close(item->fd); SDL_free(item); return SDL_OutOfMemory(); @@ -928,7 +928,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) } } - if (_this->last == NULL) { + if (!_this->last) { _this->first = _this->last = item; } else { _this->last->next = item; @@ -947,10 +947,10 @@ static int SDL_EVDEV_device_removed(const char *dev_path) SDL_evdevlist_item *item; SDL_evdevlist_item *prev = NULL; - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { /* found it, remove it. */ if (SDL_strcmp(dev_path, item->path) == 0) { - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(_this->first == item); diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index 2fb3034a39cc2..cf768cdf74e4a 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -173,7 +173,7 @@ static int fatal_signals[] = { static void kbd_cleanup(void) { SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state; - if (kbd == NULL) { + if (!kbd) { return; } kbd_cleanup_state = NULL; @@ -258,7 +258,7 @@ static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd) { int tabidx; - if (kbd_cleanup_state != NULL) { + if (kbd_cleanup_state) { return; } kbd_cleanup_state = kbd; @@ -428,7 +428,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 }; kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd)); - if (kbd == NULL) { + if (!kbd) { return NULL; } @@ -464,7 +464,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) { - if (state == NULL) { + if (!state) { return; } @@ -892,7 +892,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode unsigned short *key_map; unsigned short keysym; - if (state == NULL) { + if (!state) { return; } @@ -900,7 +900,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode shift_final = (state->shift_state | state->slockstate) ^ state->lockstate; key_map = state->key_maps[shift_final]; - if (key_map == NULL) { + if (!key_map) { /* Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state */ state->shift_state = 0; state->slockstate = 0; diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index 0efd7dc5b6a17..64a200e973752 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -419,7 +419,7 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) } focused_win = SDL_GetKeyboardFocus(); - if (focused_win == NULL) { + if (!focused_win) { return; } diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 5997b046ddfa5..9b8214f73192e 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -112,7 +112,7 @@ static SDL_bool IBus_EnterVariant(DBusConnection *conn, DBusMessageIter *iter, S } dbus->message_iter_get_basic(inside, &struct_id); - if (struct_id == NULL || SDL_strncmp(struct_id, struct_id, id_size) != 0) { + if (!struct_id || SDL_strncmp(struct_id, struct_id, id_size) != 0) { return SDL_FALSE; } return SDL_TRUE; @@ -291,7 +291,7 @@ static char *IBus_ReadAddressFromFile(const char *file_path) FILE *addr_file; addr_file = fopen(file_path, "r"); - if (addr_file == NULL) { + if (!addr_file) { return NULL; } @@ -336,7 +336,7 @@ static char *IBus_GetDBusAddressFilename(void) } dbus = SDL_DBus_GetContext(); - if (dbus == NULL) { + if (!dbus) { return NULL; } @@ -350,7 +350,7 @@ static char *IBus_GetDBusAddressFilename(void) and look up the address from a filepath using all those bits, eek. */ disp_env = SDL_getenv("DISPLAY"); - if (disp_env == NULL || !*disp_env) { + if (!disp_env || !*disp_env) { display = SDL_strdup(":0.0"); } else { display = SDL_strdup(disp_env); @@ -360,7 +360,7 @@ static char *IBus_GetDBusAddressFilename(void) disp_num = SDL_strrchr(display, ':'); screen_num = SDL_strrchr(display, '.'); - if (disp_num == NULL) { + if (!disp_num) { SDL_free(display); return NULL; } @@ -374,7 +374,7 @@ static char *IBus_GetDBusAddressFilename(void) if (!*host) { const char *session = SDL_getenv("XDG_SESSION_TYPE"); - if (session != NULL && SDL_strcmp(session, "wayland") == 0) { + if (session && SDL_strcmp(session, "wayland") == 0) { host = "unix-wayland"; } else { host = "unix"; @@ -388,7 +388,7 @@ static char *IBus_GetDBusAddressFilename(void) SDL_strlcpy(config_dir, conf_env, sizeof(config_dir)); } else { const char *home_env = SDL_getenv("HOME"); - if (home_env == NULL || !*home_env) { + if (!home_env || !*home_env) { SDL_free(display); return NULL; } @@ -397,7 +397,7 @@ static char *IBus_GetDBusAddressFilename(void) key = SDL_DBus_GetLocalMachineId(); - if (key == NULL) { + if (!key) { SDL_free(display); return NULL; } @@ -458,7 +458,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) ibus_input_interface = IBUS_INPUT_INTERFACE; ibus_conn = dbus->connection_open_private(addr, NULL); - if (ibus_conn == NULL) { + if (!ibus_conn) { return SDL_FALSE; /* oh well. */ } @@ -498,7 +498,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) { - if (dbus == NULL) { + if (!dbus) { return SDL_FALSE; } @@ -518,7 +518,7 @@ static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) struct inotify_event *event = (struct inotify_event *)p; if (event->len > 0) { char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/'); - if (addr_file_no_path == NULL) { + if (!addr_file_no_path) { return SDL_FALSE; } @@ -555,12 +555,12 @@ SDL_bool SDL_IBus_Init(void) char *addr; char *addr_file_dir; - if (addr_file == NULL) { + if (!addr_file) { return SDL_FALSE; } addr = IBus_ReadAddressFromFile(addr_file); - if (addr == NULL) { + if (!addr) { SDL_free(addr_file); return SDL_FALSE; } @@ -646,7 +646,7 @@ static void IBus_SimpleMessage(const char *method) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); - if ((input_ctx_path != NULL) && (IBus_CheckConnection(dbus))) { + if ((input_ctx_path) && (IBus_CheckConnection(dbus))) { SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, method, DBUS_TYPE_INVALID); } } @@ -696,7 +696,7 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) } focused_win = SDL_GetKeyboardFocus(); - if (focused_win == NULL) { + if (!focused_win) { return; } diff --git a/src/core/linux/SDL_ime.c b/src/core/linux/SDL_ime.c index 45bc1c6c65f6b..1b9394e8896c4 100644 --- a/src/core/linux/SDL_ime.c +++ b/src/core/linux/SDL_ime.c @@ -56,9 +56,9 @@ static void InitIME(void) /* See if fcitx IME support is being requested */ #ifdef HAVE_FCITX - if (SDL_IME_Init_Real == NULL && + if (!SDL_IME_Init_Real && ((im_module && SDL_strcmp(im_module, "fcitx") == 0) || - (im_module == NULL && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) { + (!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) { SDL_IME_Init_Real = SDL_Fcitx_Init; SDL_IME_Quit_Real = SDL_Fcitx_Quit; SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus; @@ -71,7 +71,7 @@ static void InitIME(void) /* default to IBus */ #ifdef HAVE_IBUS_IBUS_H - if (SDL_IME_Init_Real == NULL) { + if (!SDL_IME_Init_Real) { SDL_IME_Init_Real = SDL_IBus_Init; SDL_IME_Quit_Real = SDL_IBus_Quit; SDL_IME_SetFocus_Real = SDL_IBus_SetFocus; diff --git a/src/core/linux/SDL_system_theme.c b/src/core/linux/SDL_system_theme.c index 89077a039a2de..3b6e44581f60c 100644 --- a/src/core/linux/SDL_system_theme.c +++ b/src/core/linux/SDL_system_theme.c @@ -115,12 +115,12 @@ SDL_bool SDL_SystemTheme_Init(void) system_theme_data.theme = SDL_SYSTEM_THEME_UNKNOWN; system_theme_data.dbus = dbus; - if (dbus == NULL) { + if (!dbus) { return SDL_FALSE; } msg = dbus->message_new_method_call(PORTAL_DESTINATION, PORTAL_PATH, PORTAL_INTERFACE, PORTAL_METHOD); - if (msg != NULL) { + if (msg) { if (dbus->message_append_args(msg, DBUS_TYPE_STRING, &namespace, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) { DBusMessage *reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, 300, NULL); if (reply) { diff --git a/src/core/linux/SDL_threadprio.c b/src/core/linux/SDL_threadprio.c index 23b4473346c6f..c5d28dc92085e 100644 --- a/src/core/linux/SDL_threadprio.c +++ b/src/core/linux/SDL_threadprio.c @@ -111,19 +111,19 @@ static void rtkit_initialize(void) dbus_conn = get_rtkit_dbus_connection(); /* Try getting minimum nice level: this is often greater than PRIO_MIN (-20). */ - if (dbus_conn == NULL || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MinNiceLevel", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MinNiceLevel", DBUS_TYPE_INT32, &rtkit_min_nice_level)) { rtkit_min_nice_level = -20; } /* Try getting maximum realtime priority: this can be less than the POSIX default (99). */ - if (dbus_conn == NULL || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MaxRealtimePriority", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MaxRealtimePriority", DBUS_TYPE_INT32, &rtkit_max_realtime_priority)) { rtkit_max_realtime_priority = 99; } /* Try getting maximum rttime allowed by rtkit: exceeding this value will result in SIGKILL */ - if (dbus_conn == NULL || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "RTTimeUSecMax", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "RTTimeUSecMax", DBUS_TYPE_INT64, &rtkit_max_rttime_usec)) { rtkit_max_rttime_usec = 200000; } @@ -202,7 +202,7 @@ static SDL_bool rtkit_setpriority_nice(pid_t thread, int nice_level) nice = rtkit_min_nice_level; } - if (dbus_conn == NULL || !SDL_DBus_CallMethodOnConnection(dbus_conn, + if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadHighPriorityWithPID", DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_INT32, &nice, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID)) { @@ -233,7 +233,7 @@ static SDL_bool rtkit_setpriority_realtime(pid_t thread, int rt_priority) // go through to determine whether it really needs to fail or not. rtkit_initialize_realtime_thread(); - if (dbus_conn == NULL || !SDL_DBus_CallMethodOnConnection(dbus_conn, + if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadRealtimeWithPID", DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_UINT32, &priority, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID)) { diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 9e72d79ed1cbf..a459489b2563e 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -47,7 +47,7 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev); static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(_this->udev_handle, fn); - if (*addr == NULL) { + if (!*addr) { /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ return SDL_FALSE; } @@ -96,7 +96,7 @@ static int SDL_UDEV_load_syms(void) static SDL_bool SDL_UDEV_hotplug_update_available(void) { - if (_this->udev_mon != NULL) { + if (_this->udev_mon) { const int fd = _this->syms.udev_monitor_get_fd(_this->udev_mon); if (SDL_IOReady(fd, SDL_IOR_READ, 0)) { return SDL_TRUE; @@ -109,9 +109,9 @@ int SDL_UDEV_Init(void) { int retval = 0; - if (_this == NULL) { + if (!_this) { _this = (SDL_UDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); - if (_this == NULL) { + if (!_this) { return SDL_OutOfMemory(); } @@ -126,13 +126,13 @@ int SDL_UDEV_Init(void) */ _this->udev = _this->syms.udev_new(); - if (_this->udev == NULL) { + if (!_this->udev) { SDL_UDEV_Quit(); return SDL_SetError("udev_new() failed"); } _this->udev_mon = _this->syms.udev_monitor_new_from_netlink(_this->udev, "udev"); - if (_this->udev_mon == NULL) { + if (!_this->udev_mon) { SDL_UDEV_Quit(); return SDL_SetError("udev_monitor_new_from_netlink() failed"); } @@ -152,7 +152,7 @@ int SDL_UDEV_Init(void) void SDL_UDEV_Quit(void) { - if (_this == NULL) { + if (!_this) { return; } @@ -160,17 +160,17 @@ void SDL_UDEV_Quit(void) if (_this->ref_count < 1) { - if (_this->udev_mon != NULL) { + if (_this->udev_mon) { _this->syms.udev_monitor_unref(_this->udev_mon); _this->udev_mon = NULL; } - if (_this->udev != NULL) { + if (_this->udev) { _this->syms.udev_unref(_this->udev); _this->udev = NULL; } /* Remove existing devices */ - while (_this->first != NULL) { + while (_this->first) { SDL_UDEV_CallbackList *item = _this->first; _this->first = _this->first->next; SDL_free(item); @@ -188,12 +188,12 @@ int SDL_UDEV_Scan(void) struct udev_list_entry *devs = NULL; struct udev_list_entry *item = NULL; - if (_this == NULL) { + if (!_this) { return 0; } enumerate = _this->syms.udev_enumerate_new(_this->udev); - if (enumerate == NULL) { + if (!enumerate) { SDL_UDEV_Quit(); return SDL_SetError("udev_enumerate_new() failed"); } @@ -206,7 +206,7 @@ int SDL_UDEV_Scan(void) for (item = devs; item; item = _this->syms.udev_list_entry_get_next(item)) { const char *path = _this->syms.udev_list_entry_get_name(item); struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path); - if (dev != NULL) { + if (dev) { device_event(SDL_UDEV_DEVICEADDED, dev); _this->syms.udev_device_unref(dev); } @@ -223,12 +223,12 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 struct udev_list_entry *item = NULL; SDL_bool found = SDL_FALSE; - if (_this == NULL) { + if (!_this) { return SDL_FALSE; } enumerate = _this->syms.udev_enumerate_new(_this->udev); - if (enumerate == NULL) { + if (!enumerate) { SDL_SetError("udev_enumerate_new() failed"); return SDL_FALSE; } @@ -238,7 +238,7 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 for (item = devs; item && !found; item = _this->syms.udev_list_entry_get_next(item)) { const char *path = _this->syms.udev_list_entry_get_name(item); struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path); - if (dev != NULL) { + if (dev) { const char *val = NULL; const char *existing_path; @@ -247,17 +247,17 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 found = SDL_TRUE; val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID"); - if (val != NULL) { + if (val) { *vendor = (Uint16)SDL_strtol(val, NULL, 16); } val = _this->syms.udev_device_get_property_value(dev, "ID_MODEL_ID"); - if (val != NULL) { + if (val) { *product = (Uint16)SDL_strtol(val, NULL, 16); } val = _this->syms.udev_device_get_property_value(dev, "ID_REVISION"); - if (val != NULL) { + if (val) { *version = (Uint16)SDL_strtol(val, NULL, 16); } } @@ -271,11 +271,11 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 void SDL_UDEV_UnloadLibrary(void) { - if (_this == NULL) { + if (!_this) { return; } - if (_this->udev_handle != NULL) { + if (_this->udev_handle) { SDL_UnloadObject(_this->udev_handle); _this->udev_handle = NULL; } @@ -285,7 +285,7 @@ int SDL_UDEV_LoadLibrary(void) { int retval = 0, i; - if (_this == NULL) { + if (!_this) { return SDL_SetError("UDEV not initialized"); } @@ -296,9 +296,9 @@ int SDL_UDEV_LoadLibrary(void) #ifdef SDL_UDEV_DYNAMIC /* Check for the build environment's libudev first */ - if (_this->udev_handle == NULL) { + if (!_this->udev_handle) { _this->udev_handle = SDL_LoadObject(SDL_UDEV_DYNAMIC); - if (_this->udev_handle != NULL) { + if (_this->udev_handle) { retval = SDL_UDEV_load_syms(); if (retval < 0) { SDL_UDEV_UnloadLibrary(); @@ -307,10 +307,10 @@ int SDL_UDEV_LoadLibrary(void) } #endif - if (_this->udev_handle == NULL) { + if (!_this->udev_handle) { for (i = 0; i < SDL_arraysize(SDL_UDEV_LIBS); i++) { _this->udev_handle = SDL_LoadObject(SDL_UDEV_LIBS[i]); - if (_this->udev_handle != NULL) { + if (_this->udev_handle) { retval = SDL_UDEV_load_syms(); if (retval < 0) { SDL_UDEV_UnloadLibrary(); @@ -320,7 +320,7 @@ int SDL_UDEV_LoadLibrary(void) } } - if (_this->udev_handle == NULL) { + if (!_this->udev_handle) { retval = -1; /* Don't call SDL_SetError(): SDL_LoadObject already did. */ } @@ -339,7 +339,7 @@ static void get_caps(struct udev_device *dev, struct udev_device *pdev, const ch SDL_memset(bitmask, 0, bitmask_len * sizeof(*bitmask)); value = _this->syms.udev_device_get_sysattr_value(pdev, attr); - if (value == NULL) { + if (!value) { return; } @@ -374,7 +374,7 @@ static int guess_device_class(struct udev_device *dev) while (pdev && !_this->syms.udev_device_get_sysattr_value(pdev, "capabilities/ev")) { pdev = _this->syms.udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); } - if (pdev == NULL) { + if (!pdev) { return 0; } @@ -400,7 +400,7 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) SDL_UDEV_CallbackList *item; path = _this->syms.udev_device_get_devnode(dev); - if (path == NULL) { + if (!path) { return; } @@ -411,23 +411,23 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) /* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */ val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"); - if (val != NULL && SDL_strcmp(val, "1") == 0) { + if (val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_JOYSTICK; } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER"); if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) && - val != NULL && SDL_strcmp(val, "1") == 0) { + val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_JOYSTICK; } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE"); - if (val != NULL && SDL_strcmp(val, "1") == 0) { + if (val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_MOUSE; } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"); - if (val != NULL && SDL_strcmp(val, "1") == 0) { + if (val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; } @@ -438,19 +438,19 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) Ref: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c#n183 */ val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEY"); - if (val != NULL && SDL_strcmp(val, "1") == 0) { + if (val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_HAS_KEYS; } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"); - if (val != NULL && SDL_strcmp(val, "1") == 0) { + if (val && SDL_strcmp(val, "1") == 0) { devclass |= SDL_UDEV_DEVICE_KEYBOARD; } if (devclass == 0) { /* Fall back to old style input classes */ val = _this->syms.udev_device_get_property_value(dev, "ID_CLASS"); - if (val != NULL) { + if (val) { if (SDL_strcmp(val, "joystick") == 0) { devclass = SDL_UDEV_DEVICE_JOYSTICK; } else if (SDL_strcmp(val, "mouse") == 0) { @@ -470,7 +470,7 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) } /* Process callbacks */ - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { item->callback(type, devclass, path); } } @@ -480,13 +480,13 @@ void SDL_UDEV_Poll(void) struct udev_device *dev = NULL; const char *action = NULL; - if (_this == NULL) { + if (!_this) { return; } while (SDL_UDEV_hotplug_update_available()) { dev = _this->syms.udev_monitor_receive_device(_this->udev_mon); - if (dev == NULL) { + if (!dev) { break; } action = _this->syms.udev_device_get_action(dev); @@ -507,13 +507,13 @@ int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) { SDL_UDEV_CallbackList *item; item = (SDL_UDEV_CallbackList *)SDL_calloc(1, sizeof(SDL_UDEV_CallbackList)); - if (item == NULL) { + if (!item) { return SDL_OutOfMemory(); } item->callback = cb; - if (_this->last == NULL) { + if (!_this->last) { _this->first = _this->last = item; } else { _this->last->next = item; @@ -528,14 +528,14 @@ void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb) SDL_UDEV_CallbackList *item; SDL_UDEV_CallbackList *prev = NULL; - if (_this == NULL) { + if (!_this) { return; } - for (item = _this->first; item != NULL; item = item->next) { + for (item = _this->first; item; item = item->next) { /* found it, remove it. */ if (item->callback == cb) { - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(_this->first == item); diff --git a/src/core/ngage/SDL_ngage_runapp.cpp b/src/core/ngage/SDL_ngage_runapp.cpp index 6c3e4b04d7c41..b2eca9889b791 100644 --- a/src/core/ngage/SDL_ngage_runapp.cpp +++ b/src/core/ngage/SDL_ngage_runapp.cpp @@ -57,7 +57,7 @@ SDL_RunApp(int argc_, char* argv_[], SDL_main_func mainFunction, void * reserved newHeap = User::ChunkHeap(NULL, heapSize, heapSize, KMinHeapGrowBy); - if (newHeap == NULL) { + if (!newHeap) { ret = 3; goto cleanup; } else { diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c index f54f1d3951dd7..a92a0484c3d3b 100644 --- a/src/core/openbsd/SDL_wscons_kbd.c +++ b/src/core/openbsd/SDL_wscons_kbd.c @@ -419,7 +419,7 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) #endif SDL_WSCONS_input_data *input = (SDL_WSCONS_input_data *)SDL_calloc(1, sizeof(SDL_WSCONS_input_data)); - if (input == NULL) { + if (!input) { return input; } input->fd = open(dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); @@ -429,7 +429,7 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) return NULL; } input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES); - if (input->keymap.map == NULL) { + if (!input->keymap.map) { SDL_free(input); return NULL; } @@ -579,7 +579,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input) keysym_t *group; keysym_t ksym, result; - if (input == NULL) { + if (!input) { return; } if ((n = read(input->fd, events, sizeof(events))) > 0) { @@ -923,7 +923,7 @@ void SDL_WSCONS_PumpEvents() for (i = 0; i < 4; i++) { updateKeyboard(inputs[i]); } - if (mouseInputData != NULL) { + if (mouseInputData) { updateMouse(mouseInputData); } } diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c index c3378153c8e23..88855e469443c 100644 --- a/src/core/openbsd/SDL_wscons_mouse.c +++ b/src/core/openbsd/SDL_wscons_mouse.c @@ -41,7 +41,7 @@ SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse() #endif SDL_WSCONS_mouse_input_data *mouseInputData = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data)); - if (mouseInputData == NULL) { + if (!mouseInputData) { return NULL; } mouseInputData->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC); @@ -125,7 +125,7 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData) void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *inputData) { - if (inputData == NULL) { + if (!inputData) { return; } close(inputData->fd); diff --git a/src/core/windows/SDL_hid.c b/src/core/windows/SDL_hid.c index 3129ac27d5f38..541f6490faa2d 100644 --- a/src/core/windows/SDL_hid.c +++ b/src/core/windows/SDL_hid.c @@ -58,9 +58,9 @@ int WIN_LoadHIDDLL(void) SDL_HidP_GetValueCaps = (HidP_GetValueCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetValueCaps"); SDL_HidP_MaxDataListLength = (HidP_MaxDataListLength_t)GetProcAddress(s_pHIDDLL, "HidP_MaxDataListLength"); SDL_HidP_GetData = (HidP_GetData_t)GetProcAddress(s_pHIDDLL, "HidP_GetData"); - if (SDL_HidD_GetManufacturerString == NULL || SDL_HidD_GetProductString == NULL || - SDL_HidP_GetCaps == NULL || SDL_HidP_GetButtonCaps == NULL || - SDL_HidP_GetValueCaps == NULL || SDL_HidP_MaxDataListLength == NULL || SDL_HidP_GetData == NULL) { + if (!SDL_HidD_GetManufacturerString || !SDL_HidD_GetProductString || + !SDL_HidP_GetCaps || !SDL_HidP_GetButtonCaps || + !SDL_HidP_GetValueCaps || !SDL_HidP_MaxDataListLength || !SDL_HidP_GetData) { WIN_UnloadHIDDLL(); return -1; } diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 629f4a181c02e..e2d1266efe89f 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -342,8 +342,8 @@ int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool i { const Uint64 timeout = SDL_GetTicks() + 8000; /* intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. */ - SDL_assert(device != NULL); - SDL_assert(immdevice != NULL); + SDL_assert(device); + SDL_assert(immdevice); LPCWSTR devid = SDL_IMMDevice_GetDevID(device); SDL_assert(devid != NULL); diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index 389862708bb33..39f48f9d9c057 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -283,7 +283,7 @@ char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) } strw = (WCHAR *)SDL_malloc(len + sizeof(WCHAR)); - if (strw == NULL) { + if (!strw) { RegCloseKey(hkey); return WIN_StringToUTF8(name); /* oh well. */ } @@ -388,7 +388,7 @@ DECLSPEC int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_fu (void)_argc; (void)_argv; (void)reserved; argvw = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argvw == NULL) { + if (!argvw) { return OutOfMemory(); } @@ -399,13 +399,13 @@ DECLSPEC int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_fu /* Parse it into argv and argc */ argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv)); - if (argv == NULL) { + if (!argv) { return OutOfMemory(); } for (i = 0; i < argc; ++i) { DWORD len; char *arg = WIN_StringToUTF8W(argvw[i]); - if (arg == NULL) { + if (!arg) { return OutOfMemory(); } len = (DWORD)SDL_strlen(arg); diff --git a/src/core/windows/SDL_xinput.c b/src/core/windows/SDL_xinput.c index 01418d9f3a9ab..8a410e783a016 100644 --- a/src/core/windows/SDL_xinput.c +++ b/src/core/windows/SDL_xinput.c @@ -106,13 +106,13 @@ int WIN_LoadXInputDLL(void) /* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */ SDL_XInputGetState = (XInputGetState_t)GetProcAddress(s_pXInputDLL, (LPCSTR)100); - if (SDL_XInputGetState == NULL) { + if (!SDL_XInputGetState) { SDL_XInputGetState = (XInputGetState_t)GetProcAddress(s_pXInputDLL, "XInputGetState"); } SDL_XInputSetState = (XInputSetState_t)GetProcAddress(s_pXInputDLL, "XInputSetState"); SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress(s_pXInputDLL, "XInputGetCapabilities"); SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress(s_pXInputDLL, "XInputGetBatteryInformation"); - if (SDL_XInputGetState == NULL || SDL_XInputSetState == NULL || SDL_XInputGetCapabilities == NULL) { + if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) { WIN_UnloadXInputDLL(); return -1; } diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index 3bd87ccd67d5f..167e5a9a0be4b 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -343,7 +343,7 @@ void SDL_WinRTApp::Run() // representation of command line arguments. int argc = 1; char **argv = (char **)SDL_malloc(2 * sizeof(*argv)); - if (argv == NULL) { + if (!argv) { return; } argv[0] = SDL_strdup("WinRTApp"); diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 833a98072d898..c865aac715ff6 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -418,7 +418,7 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) void *retval = NULL; if (lib) { retval = (void *) GetProcAddress(lib, sym); - if (retval == NULL) { + if (!retval) { FreeLibrary(lib); } } @@ -431,9 +431,9 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) { void *lib = dlopen(fname, RTLD_NOW | RTLD_LOCAL); void *retval = NULL; - if (lib != NULL) { + if (lib) { retval = dlsym(lib, sym); - if (retval == NULL) { + if (!retval) { dlclose(lib); } } diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index 2e1a2ceaf78ca..d7b620a56a7a2 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -28,7 +28,7 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, { int posted; - if (display == NULL || display->id == 0) { + if (!display || display->id == 0) { return 0; } switch (displayevent) { diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index c1f27bc466456..6bb763e463367 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -778,7 +778,7 @@ int SDL_SetKeyboardFocus(SDL_Window *window) } } - if (keyboard->focus && window == NULL) { + if (keyboard->focus && !window) { /* We won't get anymore keyboard messages, so reset keyboard state */ SDL_ResetKeyboard(); } @@ -787,7 +787,7 @@ int SDL_SetKeyboardFocus(SDL_Window *window) if (keyboard->focus && keyboard->focus != window) { /* new window shouldn't think it has mouse captured. */ - SDL_assert(window == NULL || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)); + SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)); /* old window must lose an existing mouse capture. */ if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) { @@ -1199,7 +1199,7 @@ const char *SDL_GetScancodeName(SDL_Scancode scancode) } name = SDL_scancode_names[scancode]; - if (name != NULL) { + if (name) { return name; } @@ -1210,7 +1210,7 @@ SDL_Scancode SDL_GetScancodeFromName(const char *name) { int i; - if (name == NULL || !*name) { + if (!name || !*name) { SDL_InvalidParamError("name"); return SDL_SCANCODE_UNKNOWN; } @@ -1270,7 +1270,7 @@ SDL_Keycode SDL_GetKeyFromName(const char *name) SDL_Keycode key; /* Check input */ - if (name == NULL) { + if (!name) { return SDLK_UNKNOWN; } diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index fc38e682a2304..cd4e6a71952e1 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -476,7 +476,7 @@ int SDL_SetMouseSystemScale(int num_values, const float *values) } v = (float *)SDL_realloc(mouse->system_scale_values, num_values * sizeof(*values)); - if (v == NULL) { + if (!v) { return SDL_OutOfMemory(); } SDL_memcpy(v, values, num_values * sizeof(*values)); @@ -704,7 +704,7 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button) if (button >= mouse->num_clickstates) { int i, count = button + 1; SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate)); - if (clickstate == NULL) { + if (!clickstate) { return NULL; } mouse->clickstate = clickstate; @@ -726,7 +726,7 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ SDL_MouseInputSource *source; source = GetMouseInputSource(mouse, mouseID); - if (source == NULL) { + if (!source) { return 0; } buttonstate = source->buttonstate; @@ -982,10 +982,10 @@ Uint32 SDL_GetGlobalMouseState(float *x, float *y) float tmpx, tmpy; /* make sure these are never NULL for the backend implementations... */ - if (x == NULL) { + if (!x) { x = &tmpx; } - if (y == NULL) { + if (!y) { y = &tmpy; } @@ -1001,11 +1001,11 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool { SDL_Mouse *mouse = SDL_GetMouse(); - if (window == NULL) { + if (!window) { window = mouse->focus; } - if (window == NULL) { + if (!window) { return; } @@ -1231,7 +1231,7 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, /* Create the surface from a bitmap */ surface = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_ARGB8888); - if (surface == NULL) { + if (!surface) { return NULL; } for (y = 0; y < h; ++y) { @@ -1264,7 +1264,7 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) SDL_Surface *temp = NULL; SDL_Cursor *cursor; - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("surface"); return NULL; } @@ -1278,7 +1278,7 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) { temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888); - if (temp == NULL) { + if (!temp) { return NULL; } surface = temp; @@ -1344,7 +1344,7 @@ int SDL_SetCursor(SDL_Cursor *cursor) break; } } - if (found == NULL) { + if (!found) { return SDL_SetError("Cursor not associated with the current mouse"); } } @@ -1373,7 +1373,7 @@ SDL_Cursor *SDL_GetCursor(void) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return NULL; } return mouse->cur_cursor; @@ -1383,7 +1383,7 @@ SDL_Cursor *SDL_GetDefaultCursor(void) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return NULL; } return mouse->def_cursor; @@ -1394,7 +1394,7 @@ void SDL_DestroyCursor(SDL_Cursor *cursor) SDL_Mouse *mouse = SDL_GetMouse(); SDL_Cursor *curr, *prev; - if (cursor == NULL) { + if (!cursor) { return; } diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index d989a25e521f8..9671f49b46bf5 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -137,7 +137,7 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID) SDL_Finger *SDL_GetTouchFinger(SDL_TouchID touchID, int index) { SDL_Touch *touch = SDL_GetTouch(touchID); - if (touch == NULL) { + if (!touch) { return NULL; } if (index < 0 || index >= touch->num_fingers) { @@ -160,7 +160,7 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name /* Add the touch to the list of touch */ touchDevices = (SDL_Touch **)SDL_realloc(SDL_touchDevices, (SDL_num_touch + 1) * sizeof(*touchDevices)); - if (touchDevices == NULL) { + if (!touchDevices) { return SDL_OutOfMemory(); } @@ -193,7 +193,7 @@ static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float if (touch->num_fingers == touch->max_fingers) { SDL_Finger **new_fingers; new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers + 1) * sizeof(*touch->fingers)); - if (new_fingers == NULL) { + if (!new_fingers) { return SDL_OutOfMemory(); } touch->fingers = new_fingers; @@ -235,7 +235,7 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W SDL_Mouse *mouse; SDL_Touch *touch = SDL_GetTouch(id); - if (touch == NULL) { + if (!touch) { return -1; } @@ -329,7 +329,7 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W posted = (SDL_PushEvent(&event) > 0); } } else { - if (finger == NULL) { + if (!finger) { /* This finger is already up */ return 0; } @@ -366,7 +366,7 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, float xrel, yrel, prel; touch = SDL_GetTouch(id); - if (touch == NULL) { + if (!touch) { return -1; } @@ -409,7 +409,7 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, } finger = SDL_GetFinger(touch, fingerid); - if (finger == NULL) { + if (!finger) { return SDL_SendTouch(timestamp, id, fingerid, window, SDL_TRUE, x, y, pressure); } @@ -461,7 +461,7 @@ void SDL_DelTouch(SDL_TouchID id) index = SDL_GetTouchIndex(id); touch = SDL_GetTouch(id); - if (touch == NULL) { + if (!touch) { return; } diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 8273f82d09e99..5a4a235d55d32 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -43,7 +43,7 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, { int posted; - if (window == NULL) { + if (!window) { return 0; } if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) { @@ -222,11 +222,11 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, break; } - if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && window->parent == NULL) { + if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !window->parent) { int toplevel_count = 0; SDL_Window *n; - for (n = SDL_GetVideoDevice()->windows; n != NULL; n = n->next) { - if (n->parent == NULL) { + for (n = SDL_GetVideoDevice()->windows; n; n = n->next) { + if (!n->parent) { ++toplevel_count; } } diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 3bfb969b47b60..a671c76f29607 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -389,7 +389,7 @@ static SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose) SDL_RWops *rwops = NULL; rwops = SDL_CreateRW(); - if (rwops != NULL) { + if (rwops) { rwops->seek = stdio_seek; rwops->read = stdio_read; rwops->write = stdio_write; @@ -462,7 +462,7 @@ static size_t SDLCALL mem_write(SDL_RWops *context, const void *ptr, size_t size SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) { SDL_RWops *rwops = NULL; - if (file == NULL || !*file || mode == NULL || !*mode) { + if (!file || !*file || !mode || !*mode) { SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); return NULL; } @@ -495,7 +495,7 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) /* Try to open the file from the asset system */ rwops = SDL_CreateRW(); - if (rwops == NULL) { + if (!rwops) { return NULL; /* SDL_SetError already setup by SDL_CreateRW() */ } @@ -512,7 +512,7 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) #elif defined(__WIN32__) || defined(__GDK__) || defined(__WINRT__) rwops = SDL_CreateRW(); - if (rwops == NULL) { + if (!rwops) { return NULL; /* SDL_SetError already setup by SDL_CreateRW() */ } @@ -538,7 +538,7 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) #else FILE *fp = fopen(file, mode); #endif - if (fp == NULL) { + if (!fp) { SDL_SetError("Couldn't open %s", file); } else { rwops = SDL_RWFromFP(fp, SDL_TRUE); @@ -555,7 +555,7 @@ SDL_RWops *SDL_RWFromMem(void *mem, size_t size) { SDL_RWops *rwops = NULL; - if (mem == NULL) { + if (!mem) { SDL_InvalidParamError("mem"); return NULL; } @@ -565,7 +565,7 @@ SDL_RWops *SDL_RWFromMem(void *mem, size_t size) } rwops = SDL_CreateRW(); - if (rwops != NULL) { + if (rwops) { rwops->size = mem_size; rwops->seek = mem_seek; rwops->read = mem_read; @@ -582,7 +582,7 @@ SDL_RWops *SDL_RWFromConstMem(const void *mem, size_t size) { SDL_RWops *rwops = NULL; - if (mem == NULL) { + if (!mem) { SDL_InvalidParamError("mem"); return NULL; } @@ -592,7 +592,7 @@ SDL_RWops *SDL_RWFromConstMem(const void *mem, size_t size) } rwops = SDL_CreateRW(); - if (rwops != NULL) { + if (rwops) { rwops->size = mem_size; rwops->seek = mem_seek; rwops->read = mem_read; @@ -609,7 +609,7 @@ SDL_RWops *SDL_CreateRW(void) SDL_RWops *context; context = (SDL_RWops *)SDL_calloc(1, sizeof(*context)); - if (context == NULL) { + if (!context) { SDL_OutOfMemory(); } else { context->type = SDL_RWOPS_UNKNOWN; @@ -632,7 +632,7 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc) char *data = NULL, *newdata; SDL_bool loading_chunks = SDL_FALSE; - if (src == NULL) { + if (!src) { SDL_InvalidParamError("src"); return NULL; } @@ -662,7 +662,7 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc) } else { newdata = SDL_realloc(data, (size_t)(size + 1)); } - if (newdata == NULL) { + if (!newdata) { SDL_free(data); data = NULL; SDL_OutOfMemory(); diff --git a/src/file/n3ds/SDL_rwopsromfs.c b/src/file/n3ds/SDL_rwopsromfs.c index acb8701a22e27..a1bde54948023 100644 --- a/src/file/n3ds/SDL_rwopsromfs.c +++ b/src/file/n3ds/SDL_rwopsromfs.c @@ -65,7 +65,7 @@ static FILE *TryOpenFile(const char *file, const char *mode) FILE *fp = NULL; fp = TryOpenInRomfs(file, mode); - if (fp == NULL) { + if (!fp) { fp = fopen(file, mode); } diff --git a/src/filesystem/android/SDL_sysfilesystem.c b/src/filesystem/android/SDL_sysfilesystem.c index d14f78921300b..a287b005ec30d 100644 --- a/src/filesystem/android/SDL_sysfilesystem.c +++ b/src/filesystem/android/SDL_sysfilesystem.c @@ -40,7 +40,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) if (path) { size_t pathlen = SDL_strlen(path) + 2; char *fullpath = (char *)SDL_malloc(pathlen); - if (fullpath == NULL) { + if (!fullpath) { SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c index 389eff087adf1..5c87840b3d3ba 100644 --- a/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -42,17 +42,17 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *ptr = NULL; size_t len = 0; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp index 517524bdb2be9..3bbfca311b80e 100644 --- a/src/filesystem/gdk/SDL_sysfilesystem.cpp +++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp @@ -44,7 +44,7 @@ SDL_GetBasePath(void) while (SDL_TRUE) { void *ptr = SDL_realloc(path, buflen * sizeof(CHAR)); - if (ptr == NULL) { + if (!ptr) { SDL_free(path); SDL_OutOfMemory(); return NULL; @@ -90,13 +90,13 @@ SDL_GetPrefPath(const char *org, const char *app) HRESULT result; const char *csid = SDL_GetHint("SDL_GDK_SERVICE_CONFIGURATION_ID"); - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } /* This should be set before calling SDL_GetPrefPath! */ - if (csid == NULL) { + if (!csid) { SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Set SDL_GDK_SERVICE_CONFIGURATION_ID before calling SDL_GetPrefPath!"); return SDL_strdup("T:\\"); } diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index 466a2576a851e..a70e297bd94cc 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -47,11 +47,11 @@ char *SDL_GetBasePath(void) rc = path.GetParent(&path); /* chop filename, keep directory. */ SDL_assert(rc == B_OK); const char *str = path.Path(); - SDL_assert(str != NULL); + SDL_assert(str); const size_t len = SDL_strlen(str); char *retval = (char *) SDL_malloc(len + 2); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -70,11 +70,11 @@ char *SDL_GetPrefPath(const char *org, const char *app) const char *append = "/config/settings/"; size_t len = SDL_strlen(home); - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } @@ -83,7 +83,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; char *retval = (char *) SDL_malloc(len); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); } else { if (*org) { diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c index 7bde83102763b..00ac71fc85726 100644 --- a/src/filesystem/n3ds/SDL_sysfilesystem.c +++ b/src/filesystem/n3ds/SDL_sysfilesystem.c @@ -41,13 +41,13 @@ char *SDL_GetBasePath(void) char *SDL_GetPrefPath(const char *org, const char *app) { char *pref_path = NULL; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } pref_path = MakePrefPath(app); - if (pref_path == NULL) { + if (!pref_path) { return NULL; } diff --git a/src/filesystem/ps2/SDL_sysfilesystem.c b/src/filesystem/ps2/SDL_sysfilesystem.c index b52fdea35724a..e81460a245a00 100644 --- a/src/filesystem/ps2/SDL_sysfilesystem.c +++ b/src/filesystem/ps2/SDL_sysfilesystem.c @@ -79,11 +79,11 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *retval = NULL; size_t len; char *base = SDL_GetBasePath(); - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } diff --git a/src/filesystem/psp/SDL_sysfilesystem.c b/src/filesystem/psp/SDL_sysfilesystem.c index 239e67436743f..f262af55fb0d4 100644 --- a/src/filesystem/psp/SDL_sysfilesystem.c +++ b/src/filesystem/psp/SDL_sysfilesystem.c @@ -47,11 +47,11 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *retval = NULL; size_t len; char *base = SDL_GetBasePath(); - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c index 17d6625b711b9..842d62e38fc6c 100644 --- a/src/filesystem/riscos/SDL_sysfilesystem.c +++ b/src/filesystem/riscos/SDL_sysfilesystem.c @@ -34,21 +34,21 @@ static char *SDL_unixify_std(const char *ro_path, char *buffer, size_t buf_len, { const char *const in_buf = buffer; /* = NULL if we allocate the buffer. */ - if (buffer == NULL) { + if (!buffer) { /* This matches the logic in __unixify, with an additional byte for the * extra path separator. */ buf_len = SDL_strlen(ro_path) + 14 + 1; buffer = SDL_malloc(buf_len); - if (buffer == NULL) { + if (!buffer) { SDL_OutOfMemory(); return NULL; } } if (!__unixify_std(ro_path, buffer, buf_len, filetype)) { - if (in_buf == NULL) { + if (!in_buf) { SDL_free(buffer); } @@ -88,7 +88,7 @@ static char *canonicalisePath(const char *path, const char *pathVar) regs.r[5] = 1 - regs.r[5]; buf = SDL_malloc(regs.r[5]); - if (buf == NULL) { + if (!buf) { SDL_OutOfMemory(); return NULL; } @@ -117,7 +117,7 @@ static _kernel_oserror *createDirectoryRecursive(char *path) *ptr = '\0'; error = _kernel_swi(OS_File, ®s, ®s); *ptr = '.'; - if (error != NULL) { + if (error) { return error; } } @@ -137,13 +137,13 @@ char *SDL_GetBasePath(void) } canon = canonicalisePath((const char *)regs.r[0], "Run$Path"); - if (canon == NULL) { + if (!canon) { return NULL; } /* chop off filename. */ ptr = SDL_strrchr(canon, '.'); - if (ptr != NULL) { + if (ptr) { *ptr = '\0'; } @@ -158,22 +158,22 @@ char *SDL_GetPrefPath(const char *org, const char *app) size_t len; _kernel_oserror *error; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } canon = canonicalisePath("", "Run$Path"); - if (canon == NULL) { + if (!canon) { return NULL; } len = SDL_strlen(canon) + SDL_strlen(org) + SDL_strlen(app) + 4; dir = (char *)SDL_malloc(len); - if (dir == NULL) { + if (!dir) { SDL_OutOfMemory(); SDL_free(canon); return NULL; @@ -188,7 +188,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) SDL_free(canon); error = createDirectoryRecursive(dir); - if (error != NULL) { + if (error) { SDL_SetError("Couldn't create directory: %s", error->errmess); SDL_free(dir); return NULL; diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index 88a3a35375ce3..d75dd5066b1fc 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -47,7 +47,7 @@ static char *readSymLink(const char *path) while (1) { char *ptr = (char *)SDL_realloc(retval, (size_t)len); - if (ptr == NULL) { + if (!ptr) { SDL_OutOfMemory(); break; } @@ -78,18 +78,18 @@ static char *search_path_for_binary(const char *bin) char *start = envr; char *ptr; - if (envr == NULL) { + if (!envr) { SDL_SetError("No $PATH set"); return NULL; } envr = SDL_strdup(envr); - if (envr == NULL) { + if (!envr) { SDL_OutOfMemory(); return NULL; } - SDL_assert(bin != NULL); + SDL_assert(bin); alloc_size = SDL_strlen(bin) + SDL_strlen(envr) + 2; exe = (char *)SDL_malloc(alloc_size); @@ -110,7 +110,7 @@ static char *search_path_for_binary(const char *bin) } } start = ptr + 1; /* start points to beginning of next element. */ - } while (ptr != NULL); + } while (ptr); SDL_free(envr); SDL_free(exe); @@ -130,7 +130,7 @@ char *SDL_GetBasePath(void) const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; if (sysctl(mib, SDL_arraysize(mib), fullpath, &buflen, NULL, 0) != -1) { retval = SDL_strdup(fullpath); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -144,13 +144,13 @@ char *SDL_GetBasePath(void) if (sysctl(mib, 4, NULL, &len, NULL, 0) != -1) { char *exe, *pwddst; char *realpathbuf = (char *)SDL_malloc(PATH_MAX + 1); - if (realpathbuf == NULL) { + if (!realpathbuf) { SDL_OutOfMemory(); return NULL; } cmdline = SDL_malloc(len); - if (cmdline == NULL) { + if (!cmdline) { SDL_free(realpathbuf); SDL_OutOfMemory(); return NULL; @@ -172,7 +172,7 @@ char *SDL_GetBasePath(void) } if (exe) { - if (pwddst == NULL) { + if (!pwddst) { if (realpath(exe, realpathbuf) != NULL) { retval = realpathbuf; } @@ -188,7 +188,7 @@ char *SDL_GetBasePath(void) } } - if (retval == NULL) { + if (!retval) { SDL_free(realpathbuf); } @@ -197,7 +197,7 @@ char *SDL_GetBasePath(void) #endif /* is a Linux-style /proc filesystem available? */ - if (retval == NULL && (access("/proc", F_OK) == 0)) { + if (!retval && (access("/proc", F_OK) == 0)) { /* !!! FIXME: after 2.0.6 ships, let's delete this code and just use the /proc/%llu version. There's no reason to have two copies of this plus all the #ifdefs. --ryan. */ @@ -209,7 +209,7 @@ char *SDL_GetBasePath(void) retval = readSymLink("/proc/self/path/a.out"); #else retval = readSymLink("/proc/self/exe"); /* linux. */ - if (retval == NULL) { + if (!retval) { /* older kernels don't have /proc/self ... try PID version... */ char path[64]; const int rc = SDL_snprintf(path, sizeof(path), @@ -225,9 +225,9 @@ char *SDL_GetBasePath(void) #ifdef __SOLARIS__ /* try this as a fallback if /proc didn't pan out */ if (!retval) { const char *path = getexecname(); - if ((path != NULL) && (path[0] == '/')) { /* must be absolute path... */ + if ((path) && (path[0] == '/')) { /* must be absolute path... */ retval = SDL_strdup(path); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -237,9 +237,9 @@ char *SDL_GetBasePath(void) /* If we had access to argv[0] here, we could check it for a path, or troll through $PATH looking for it, too. */ - if (retval != NULL) { /* chop off filename. */ + if (retval) { /* chop off filename. */ char *ptr = SDL_strrchr(retval, '/'); - if (ptr != NULL) { + if (ptr) { *(ptr + 1) = '\0'; } else { /* shouldn't happen, but just in case... */ SDL_free(retval); @@ -247,10 +247,10 @@ char *SDL_GetBasePath(void) } } - if (retval != NULL) { + if (retval) { /* try to shrink buffer... */ char *ptr = (char *)SDL_realloc(retval, SDL_strlen(retval) + 1); - if (ptr != NULL) { + if (ptr) { retval = ptr; /* oh well if it failed. */ } } @@ -273,18 +273,18 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *ptr = NULL; size_t len = 0; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } - if (envr == NULL) { + if (!envr) { /* You end up with "$HOME/.local/share/Game Name 2" */ envr = SDL_getenv("HOME"); - if (envr == NULL) { + if (!envr) { /* we could take heroic measures with /etc/passwd, but oh well. */ SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set"); return NULL; @@ -301,7 +301,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -372,15 +372,15 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa home_dir = SDL_getenv ("HOME"); - if (home_dir == NULL) + if (!home_dir) goto error; config_home = SDL_getenv ("XDG_CONFIG_HOME"); - if (config_home == NULL || config_home[0] == 0) + if (!config_home || config_home[0] == 0) { l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1; config_file = (char*) SDL_malloc (l); - if (config_file == NULL) + if (!config_file) goto error; SDL_strlcpy (config_file, home_dir, l); @@ -390,7 +390,7 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa { l = SDL_strlen (config_home) + SDL_strlen ("/user-dirs.dirs") + 1; config_file = (char*) SDL_malloc (l); - if (config_file == NULL) + if (!config_file) goto error; SDL_strlcpy (config_file, config_home, l); @@ -399,7 +399,7 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa file = fopen (config_file, "r"); SDL_free (config_file); - if (file == NULL) + if (!file) goto error; user_dir = NULL; @@ -452,7 +452,7 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa { l = SDL_strlen (home_dir) + 1 + SDL_strlen (p) + 1; user_dir = (char*) SDL_malloc (l); - if (user_dir == NULL) + if (!user_dir) goto error2; SDL_strlcpy (user_dir, home_dir, l); @@ -461,7 +461,7 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa else { user_dir = (char*) SDL_malloc (SDL_strlen (p) + 1); - if (user_dir == NULL) + if (!user_dir) goto error2; *user_dir = 0; @@ -493,12 +493,12 @@ static char *xdg_user_dir_lookup (const char *type) char *dir, *home_dir, *user_dir; dir = xdg_user_dir_lookup_with_fallback(type, NULL); - if (dir != NULL) + if (dir) return dir; home_dir = SDL_getenv("HOME"); - if (home_dir == NULL) + if (!home_dir) return NULL; /* Special case desktop for historical compatibility */ @@ -506,7 +506,7 @@ static char *xdg_user_dir_lookup (const char *type) { user_dir = (char*) SDL_malloc(SDL_strlen(home_dir) + SDL_strlen("/Desktop") + 1); - if (user_dir == NULL) + if (!user_dir) return NULL; strcpy(user_dir, home_dir); diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c index 836416abfddaf..e06664908737a 100644 --- a/src/filesystem/vita/SDL_sysfilesystem.c +++ b/src/filesystem/vita/SDL_sysfilesystem.c @@ -48,11 +48,11 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *ptr = NULL; size_t len = 0; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } @@ -60,7 +60,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) len += SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c index 3027fb00e2b0a..d31193af202c1 100644 --- a/src/filesystem/windows/SDL_sysfilesystem.c +++ b/src/filesystem/windows/SDL_sysfilesystem.c @@ -51,7 +51,7 @@ char *SDL_GetBasePath(void) while (SDL_TRUE) { void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR)); - if (ptr == NULL) { + if (!ptr) { SDL_free(path); SDL_OutOfMemory(); return NULL; @@ -108,11 +108,11 @@ char *SDL_GetPrefPath(const char *org, const char *app) size_t new_wpath_len = 0; BOOL api_result = FALSE; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } @@ -122,13 +122,13 @@ char *SDL_GetPrefPath(const char *org, const char *app) } worg = WIN_UTF8ToStringW(org); - if (worg == NULL) { + if (!worg) { SDL_OutOfMemory(); return NULL; } wapp = WIN_UTF8ToStringW(app); - if (wapp == NULL) { + if (!wapp) { SDL_free(worg); SDL_OutOfMemory(); return NULL; diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index a5e85b4a9541b..d442d26033c73 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -106,7 +106,7 @@ SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType) } const wchar_t *ucs2Path = SDL_WinRTGetFSPathUNICODE(pathType); - if (ucs2Path == NULL) { + if (!ucs2Path) { return NULL; } @@ -123,14 +123,14 @@ SDL_GetBasePath(void) size_t destPathLen; char *destPath = NULL; - if (srcPath == NULL) { + if (!srcPath) { SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError()); return NULL; } destPathLen = SDL_strlen(srcPath) + 2; destPath = (char *)SDL_malloc(destPathLen); - if (destPath == NULL) { + if (!destPath) { SDL_OutOfMemory(); return NULL; } @@ -156,16 +156,16 @@ SDL_GetPrefPath(const char *org, const char *app) size_t new_wpath_len = 0; BOOL api_result = FALSE; - if (app == NULL) { + if (!app) { SDL_InvalidParamError("app"); return NULL; } - if (org == NULL) { + if (!org) { org = ""; } srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER); - if (srcPath == NULL) { + if (!srcPath) { SDL_SetError("Unable to find a source path"); return NULL; } @@ -177,13 +177,13 @@ SDL_GetPrefPath(const char *org, const char *app) SDL_wcslcpy(path, srcPath, SDL_arraysize(path)); worg = WIN_UTF8ToString(org); - if (worg == NULL) { + if (!worg) { SDL_OutOfMemory(); return NULL; } wapp = WIN_UTF8ToString(app); - if (wapp == NULL) { + if (!wapp) { SDL_free(worg); SDL_OutOfMemory(); return NULL; diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index fbd7762827cb1..ad70f274a1c7a 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -55,7 +55,7 @@ static int ValidHaptic(SDL_Haptic *haptic) SDL_Haptic *hapticlist; valid = 0; - if (haptic != NULL) { + if (haptic) { hapticlist = SDL_haptics; while (hapticlist) { if (hapticlist == haptic) { @@ -124,7 +124,7 @@ SDL_Haptic *SDL_HapticOpen(int device_index) /* Create the haptic device */ haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); - if (haptic == NULL) { + if (!haptic) { SDL_OutOfMemory(); return NULL; } @@ -296,7 +296,7 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) /* Create the haptic device */ haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); - if (haptic == NULL) { + if (!haptic) { SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; @@ -609,7 +609,7 @@ int SDL_HapticSetGain(SDL_Haptic *haptic, int gain) /* We use the envvar to get the maximum gain. */ env = SDL_getenv("SDL_HAPTIC_GAIN_MAX"); - if (env != NULL) { + if (env) { max_gain = SDL_atoi(env); /* Check for sanity. */ diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index f65a26eff318a..65e7b39201c4a 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -59,7 +59,7 @@ static SDL_hapticlist_item *HapticByOrder(int index) return NULL; } while (index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); --index; item = item->next; } @@ -69,7 +69,7 @@ static SDL_hapticlist_item *HapticByOrder(int index) static SDL_hapticlist_item *HapticByDevId(int device_id) { SDL_hapticlist_item *item; - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (device_id == item->device_id) { /*SDL_Log("=+=+=+=+=+= HapticByDevId id [%d]", device_id);*/ return item; @@ -81,7 +81,7 @@ static SDL_hapticlist_item *HapticByDevId(int device_id) const char *SDL_SYS_HapticName(int index) { SDL_hapticlist_item *item = HapticByOrder(index); - if (item == NULL) { + if (!item) { SDL_SetError("No such device"); return NULL; } @@ -90,11 +90,11 @@ const char *SDL_SYS_HapticName(int index) static SDL_hapticlist_item *OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item *item) { - if (item == NULL) { + if (!item) { SDL_SetError("No such device"); return NULL; } - if (item->haptic != NULL) { + if (item->haptic) { SDL_SetError("Haptic already opened"); return NULL; } @@ -106,7 +106,7 @@ static SDL_hapticlist_item *OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item * haptic->neffects = 1; haptic->nplaying = haptic->neffects; haptic->effects = (struct haptic_effect *)SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (haptic->effects == NULL) { + if (!haptic->effects) { SDL_OutOfMemory(); return NULL; } @@ -138,7 +138,7 @@ int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) { SDL_hapticlist_item *item; item = HapticByDevId(((joystick_hwdata *)joystick->hwdata)->device_id); - return (item != NULL) ? 1 : 0; + return (item) ? 1 : 0; } int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) @@ -246,18 +246,18 @@ int Android_AddHaptic(int device_id, const char *name) { SDL_hapticlist_item *item; item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); - if (item == NULL) { + if (!item) { return -1; } item->device_id = device_id; item->name = SDL_strdup(name); - if (item->name == NULL) { + if (!item->name) { SDL_free(item); return -1; } - if (SDL_hapticlist_tail == NULL) { + if (!SDL_hapticlist_tail) { SDL_hapticlist = SDL_hapticlist_tail = item; } else { SDL_hapticlist_tail->next = item; @@ -273,12 +273,12 @@ int Android_RemoveHaptic(int device_id) SDL_hapticlist_item *item; SDL_hapticlist_item *prev = NULL; - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (device_id == item->device_id) { const int retval = item->haptic ? item->haptic->index : -1; - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_hapticlist == item); diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index d9e59048296b8..9d50ac643ab78 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -154,7 +154,7 @@ int SDL_SYS_HapticInit(void) /* Get HID devices. */ match = IOServiceMatching(kIOHIDDeviceKey); - if (match == NULL) { + if (!match) { return SDL_SetError("Haptic: Failed to get IOServiceMatching."); } @@ -193,7 +193,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); --device_index; item = item->next; } @@ -226,7 +226,7 @@ int MacHaptic_MaybeAddDevice(io_object_t device) } item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); - if (item == NULL) { + if (!item) { return SDL_SetError("Could not allocate haptic storage"); } @@ -262,7 +262,7 @@ int MacHaptic_MaybeAddDevice(io_object_t device) CFRelease(hidProperties); } - if (SDL_hapticlist_tail == NULL) { + if (!SDL_hapticlist_tail) { SDL_hapticlist = SDL_hapticlist_tail = item; } else { SDL_hapticlist_tail->next = item; @@ -284,12 +284,12 @@ int MacHaptic_MaybeRemoveDevice(io_object_t device) return -1; /* not initialized. ignore this. */ } - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (IOObjectIsEqualTo((io_object_t)item->dev, device)) { const int retval = item->haptic ? item->haptic->index : -1; - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_hapticlist == item); @@ -475,7 +475,7 @@ static int SDL_SYS_HapticOpenFromService(SDL_Haptic *haptic, io_service_t servic /* Allocate the hwdata */ haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata)); - if (haptic->hwdata == NULL) { + if (!haptic->hwdata) { SDL_OutOfMemory(); goto creat_err; } @@ -512,7 +512,7 @@ static int SDL_SYS_HapticOpenFromService(SDL_Haptic *haptic, io_service_t servic /* Allocate effects memory. */ haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (haptic->effects == NULL) { + if (!haptic->effects) { SDL_OutOfMemory(); goto open_err; } @@ -526,7 +526,7 @@ static int SDL_SYS_HapticOpenFromService(SDL_Haptic *haptic, io_service_t servic open_err: FFReleaseDevice(haptic->hwdata->device); creat_err: - if (haptic->hwdata != NULL) { + if (haptic->hwdata) { SDL_free(haptic->hwdata); haptic->hwdata = NULL; } @@ -699,7 +699,7 @@ static int SDL_SYS_SetDirection(FFEFFECT *effect, SDL_HapticDirection *dir, int /* Has axes. */ rglDir = SDL_malloc(sizeof(LONG) * naxes); - if (rglDir == NULL) { + if (!rglDir) { return SDL_OutOfMemory(); } SDL_memset(rglDir, 0, sizeof(LONG) * naxes); @@ -772,7 +772,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe /* Envelope. */ envelope = SDL_malloc(sizeof(FFENVELOPE)); - if (envelope == NULL) { + if (!envelope) { return SDL_OutOfMemory(); } SDL_memset(envelope, 0, sizeof(FFENVELOPE)); @@ -787,7 +787,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe } if (dest->cAxes > 0) { axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); - if (axes == NULL) { + if (!axes) { return SDL_OutOfMemory(); } axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */ @@ -805,7 +805,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; constant = SDL_malloc(sizeof(FFCONSTANTFORCE)); - if (constant == NULL) { + if (!constant) { return SDL_OutOfMemory(); } SDL_memset(constant, 0, sizeof(FFCONSTANTFORCE)); @@ -847,7 +847,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; periodic = SDL_malloc(sizeof(FFPERIODIC)); - if (periodic == NULL) { + if (!periodic) { return SDL_OutOfMemory(); } SDL_memset(periodic, 0, sizeof(FFPERIODIC)); @@ -892,7 +892,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe hap_condition = &src->condition; if (dest->cAxes > 0) { condition = SDL_malloc(sizeof(FFCONDITION) * dest->cAxes); - if (condition == NULL) { + if (!condition) { return SDL_OutOfMemory(); } SDL_memset(condition, 0, sizeof(FFCONDITION)); @@ -935,7 +935,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_RAMP: hap_ramp = &src->ramp; ramp = SDL_malloc(sizeof(FFRAMPFORCE)); - if (ramp == NULL) { + if (!ramp) { return SDL_OutOfMemory(); } SDL_memset(ramp, 0, sizeof(FFRAMPFORCE)); @@ -973,7 +973,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_CUSTOM: hap_custom = &src->custom; custom = SDL_malloc(sizeof(FFCUSTOMFORCE)); - if (custom == NULL) { + if (!custom) { return SDL_OutOfMemory(); } SDL_memset(custom, 0, sizeof(FFCUSTOMFORCE)); @@ -1033,7 +1033,7 @@ static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT *effect, int type) effect->lpEnvelope = NULL; SDL_free(effect->rgdwAxes); effect->rgdwAxes = NULL; - if (effect->lpvTypeSpecificParams != NULL) { + if (effect->lpvTypeSpecificParams) { if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */ custom = (FFCUSTOMFORCE *)effect->lpvTypeSpecificParams; SDL_free(custom->rglForceData); @@ -1108,14 +1108,14 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* Alloc the effect. */ effect->hweffect = (struct haptic_hweffect *) SDL_malloc(sizeof(struct haptic_hweffect)); - if (effect->hweffect == NULL) { + if (!effect->hweffect) { SDL_OutOfMemory(); goto err_hweffect; } /* Get the type. */ type = SDL_SYS_HapticEffectType(base->type); - if (type == NULL) { + if (!type) { goto err_hweffect; } diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index a32e391f60679..d1375c18069fe 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -188,7 +188,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); --device_index; item = item->next; } @@ -199,7 +199,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) #ifdef SDL_USE_LIBUDEV static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) { - if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { + if (!devpath || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { return; } @@ -225,7 +225,7 @@ static int MaybeAddDevice(const char *path) int success; SDL_hapticlist_item *item; - if (path == NULL) { + if (!path) { return -1; } @@ -235,7 +235,7 @@ static int MaybeAddDevice(const char *path) } /* check for duplicates */ - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (item->dev_num == sb.st_rdev) { return -1; /* duplicate. */ } @@ -259,12 +259,12 @@ static int MaybeAddDevice(const char *path) } item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); - if (item == NULL) { + if (!item) { return -1; } item->fname = SDL_strdup(path); - if (item->fname == NULL) { + if (!item->fname) { SDL_free(item); return -1; } @@ -272,7 +272,7 @@ static int MaybeAddDevice(const char *path) item->dev_num = sb.st_rdev; /* TODO: should we add instance IDs? */ - if (SDL_hapticlist_tail == NULL) { + if (!SDL_hapticlist_tail) { SDL_hapticlist = SDL_hapticlist_tail = item; } else { SDL_hapticlist_tail->next = item; @@ -292,16 +292,16 @@ static int MaybeRemoveDevice(const char *path) SDL_hapticlist_item *item; SDL_hapticlist_item *prev = NULL; - if (path == NULL) { + if (!path) { return -1; } - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (SDL_strcmp(path, item->fname) == 0) { const int retval = item->haptic ? item->haptic->index : -1; - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_hapticlist == item); @@ -358,7 +358,7 @@ const char *SDL_SYS_HapticName(int index) if (fd >= 0) { name = SDL_SYS_HapticNameFromFD(fd); - if (name == NULL) { + if (!name) { /* No name found, return device character device */ name = item->fname; } @@ -376,7 +376,7 @@ static int SDL_SYS_HapticOpenFromFD(SDL_Haptic *haptic, int fd) /* Allocate the hwdata */ haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata)); - if (haptic->hwdata == NULL) { + if (!haptic->hwdata) { SDL_OutOfMemory(); goto open_err; } @@ -396,7 +396,7 @@ static int SDL_SYS_HapticOpenFromFD(SDL_Haptic *haptic, int fd) haptic->nplaying = haptic->neffects; /* Linux makes no distinction. */ haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (haptic->effects == NULL) { + if (!haptic->effects) { SDL_OutOfMemory(); goto open_err; } @@ -409,7 +409,7 @@ static int SDL_SYS_HapticOpenFromFD(SDL_Haptic *haptic, int fd) /* Error handling */ open_err: close(fd); - if (haptic->hwdata != NULL) { + if (haptic->hwdata) { SDL_free(haptic->hwdata); haptic->hwdata = NULL; } @@ -904,7 +904,7 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* Allocate the hardware effect */ effect->hweffect = (struct haptic_hweffect *) SDL_malloc(sizeof(struct haptic_hweffect)); - if (effect->hweffect == NULL) { + if (!effect->hweffect) { return SDL_OutOfMemory(); } diff --git a/src/haptic/windows/SDL_dinputhaptic.c b/src/haptic/windows/SDL_dinputhaptic.c index 20901a1654104..a1225dd6704f0 100644 --- a/src/haptic/windows/SDL_dinputhaptic.c +++ b/src/haptic/windows/SDL_dinputhaptic.c @@ -92,7 +92,7 @@ int SDL_DINPUT_HapticInit(void) /* Because we used CoCreateInstance, we need to Initialize it, first. */ instance = GetModuleHandle(NULL); - if (instance == NULL) { + if (!instance) { SDL_SYS_HapticQuit(); return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError()); @@ -133,7 +133,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance) DIDEVCAPS capabilities; SDL_hapticlist_item *item = NULL; - if (dinput == NULL) { + if (!dinput) { return -1; /* not initialized. We'll pick these up on enumeration if we init later. */ } @@ -166,7 +166,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance) } item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); - if (item == NULL) { + if (!item) { return SDL_OutOfMemory(); } @@ -188,11 +188,11 @@ int SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance) SDL_hapticlist_item *item; SDL_hapticlist_item *prev = NULL; - if (dinput == NULL) { + if (!dinput) { return -1; /* not initialized, ignore this. */ } - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) { /* found it, remove it. */ return SDL_SYS_RemoveHapticDevice(prev, item); @@ -287,7 +287,7 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI /* Allocate the hwdata */ haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata)); - if (haptic->hwdata == NULL) { + if (!haptic->hwdata) { return SDL_OutOfMemory(); } SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); @@ -401,7 +401,7 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI /* Prepare effects memory. */ haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (haptic->effects == NULL) { + if (!haptic->effects) { SDL_OutOfMemory(); goto acquire_err; } @@ -474,7 +474,7 @@ int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick } /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */ - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (!item->bXInputHaptic && WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) { haptic->index = index; return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE); @@ -540,7 +540,7 @@ static int SDL_SYS_SetDirection(DIEFFECT *effect, SDL_HapticDirection *dir, int /* Has axes. */ rglDir = SDL_malloc(sizeof(LONG) * naxes); - if (rglDir == NULL) { + if (!rglDir) { return SDL_OutOfMemory(); } SDL_memset(rglDir, 0, sizeof(LONG) * naxes); @@ -614,7 +614,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, /* Envelope. */ envelope = SDL_malloc(sizeof(DIENVELOPE)); - if (envelope == NULL) { + if (!envelope) { return SDL_OutOfMemory(); } SDL_memset(envelope, 0, sizeof(DIENVELOPE)); @@ -629,7 +629,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, } if (dest->cAxes > 0) { axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); - if (axes == NULL) { + if (!axes) { return SDL_OutOfMemory(); } axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */ @@ -647,7 +647,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; constant = SDL_malloc(sizeof(DICONSTANTFORCE)); - if (constant == NULL) { + if (!constant) { return SDL_OutOfMemory(); } SDL_memset(constant, 0, sizeof(DICONSTANTFORCE)); @@ -689,7 +689,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; periodic = SDL_malloc(sizeof(DIPERIODIC)); - if (periodic == NULL) { + if (!periodic) { return SDL_OutOfMemory(); } SDL_memset(periodic, 0, sizeof(DIPERIODIC)); @@ -733,7 +733,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_FRICTION: hap_condition = &src->condition; condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes); - if (condition == NULL) { + if (!condition) { return SDL_OutOfMemory(); } SDL_memset(condition, 0, sizeof(DICONDITION)); @@ -774,7 +774,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_RAMP: hap_ramp = &src->ramp; ramp = SDL_malloc(sizeof(DIRAMPFORCE)); - if (ramp == NULL) { + if (!ramp) { return SDL_OutOfMemory(); } SDL_memset(ramp, 0, sizeof(DIRAMPFORCE)); @@ -812,7 +812,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_CUSTOM: hap_custom = &src->custom; custom = SDL_malloc(sizeof(DICUSTOMFORCE)); - if (custom == NULL) { + if (!custom) { return SDL_OutOfMemory(); } SDL_memset(custom, 0, sizeof(DICUSTOMFORCE)); @@ -871,7 +871,7 @@ static void SDL_SYS_HapticFreeDIEFFECT(DIEFFECT *effect, int type) effect->lpEnvelope = NULL; SDL_free(effect->rgdwAxes); effect->rgdwAxes = NULL; - if (effect->lpvTypeSpecificParams != NULL) { + if (effect->lpvTypeSpecificParams) { if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */ custom = (DICUSTOMFORCE *)effect->lpvTypeSpecificParams; SDL_free(custom->rglForceData); @@ -937,7 +937,7 @@ int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, HRESULT ret; REFGUID type = SDL_SYS_HapticEffectType(base); - if (type == NULL) { + if (!type) { return SDL_SetError("Haptic: Unknown effect type."); } diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c index 1a2d5d638a24e..a203f3e28d341 100644 --- a/src/haptic/windows/SDL_windowshaptic.c +++ b/src/haptic/windows/SDL_windowshaptic.c @@ -75,7 +75,7 @@ int SDL_SYS_HapticInit(void) int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item) { - if (SDL_hapticlist_tail == NULL) { + if (!SDL_hapticlist_tail) { SDL_hapticlist = SDL_hapticlist_tail = item; } else { SDL_hapticlist_tail->next = item; @@ -91,7 +91,7 @@ int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item) int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item) { const int retval = item->haptic ? item->haptic->index : -1; - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_hapticlist == item); @@ -120,7 +120,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); --device_index; item = item->next; } @@ -159,7 +159,7 @@ int SDL_SYS_HapticMouse(void) int index = 0; /* Grab the first mouse haptic device we find. */ - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) { return index; } @@ -293,7 +293,7 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* Alloc the effect. */ effect->hweffect = (struct haptic_hweffect *) SDL_malloc(sizeof(struct haptic_hweffect)); - if (effect->hweffect == NULL) { + if (!effect->hweffect) { SDL_OutOfMemory(); return -1; } diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index d4add0da6dc9a..961f294079a27 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -79,7 +79,7 @@ int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) } item = (SDL_hapticlist_item *)SDL_malloc(sizeof(SDL_hapticlist_item)); - if (item == NULL) { + if (!item) { return SDL_OutOfMemory(); } @@ -114,7 +114,7 @@ int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid) return -1; } - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (item->bXInputHaptic && item->userid == userid) { /* found it, remove it. */ return SDL_SYS_RemoveHapticDevice(prev, item); @@ -173,7 +173,7 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us /* Prepare effects memory. */ haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (haptic->effects == NULL) { + if (!haptic->effects) { return SDL_OutOfMemory(); } /* Clear the memory */ @@ -181,7 +181,7 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us sizeof(struct haptic_effect) * haptic->neffects); haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata)); - if (haptic->hwdata == NULL) { + if (!haptic->hwdata) { SDL_free(haptic->effects); haptic->effects = NULL; return SDL_OutOfMemory(); @@ -192,7 +192,7 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us haptic->hwdata->userid = userid; haptic->hwdata->mutex = SDL_CreateMutex(); - if (haptic->hwdata->mutex == NULL) { + if (!haptic->hwdata->mutex) { SDL_free(haptic->effects); SDL_free(haptic->hwdata); haptic->effects = NULL; @@ -202,7 +202,7 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us (void)SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%d", userid); haptic->hwdata->thread = SDL_CreateThreadInternal(SDL_RunXInputHaptic, threadName, 64 * 1024, haptic->hwdata); - if (haptic->hwdata->thread == NULL) { + if (!haptic->hwdata->thread) { SDL_DestroyMutex(haptic->hwdata->mutex); SDL_free(haptic->effects); SDL_free(haptic->hwdata); @@ -229,7 +229,7 @@ int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick Uint8 index = 0; /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */ - for (item = SDL_hapticlist; item != NULL; item = item->next) { + for (item = SDL_hapticlist; item; item = item->next) { if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) { haptic->index = index; return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid); diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 1af2159a5d53e..7bba99801086a 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -197,7 +197,7 @@ static void HandleJoystickAxis(Uint64 timestamp, SDL_Gamepad *gamepad, int axis, } } - if (last_match && (match == NULL || !HasSameOutput(last_match, match))) { + if (last_match && (!match || !HasSameOutput(last_match, match))) { /* Clear the last input that this axis generated */ ResetOutput(timestamp, gamepad, last_match); } @@ -987,7 +987,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromString(const char *str) { int i; - if (str == NULL || str[0] == '\0') { + if (!str || str[0] == '\0') { return SDL_GAMEPAD_TYPE_UNKNOWN; } @@ -1031,7 +1031,7 @@ SDL_GamepadAxis SDL_GetGamepadAxisFromString(const char *str) { int i; - if (str == NULL || str[0] == '\0') { + if (!str || str[0] == '\0') { return SDL_GAMEPAD_AXIS_INVALID; } @@ -1090,7 +1090,7 @@ SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str) { int i; - if (str == NULL || str[0] == '\0') { + if (!str || str[0] == '\0') { return SDL_GAMEPAD_BUTTON_INVALID; } @@ -1269,7 +1269,7 @@ static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t gamepad->name = pGamepadMapping->name; gamepad->num_bindings = 0; gamepad->mapping = pGamepadMapping; - if (gamepad->joystick->naxes != 0 && gamepad->last_match_axis != NULL) { + if (gamepad->joystick->naxes != 0 && gamepad->last_match_axis) { SDL_memset(gamepad->last_match_axis, 0, gamepad->joystick->naxes * sizeof(*gamepad->last_match_axis)); } @@ -1298,7 +1298,7 @@ static char *SDL_PrivateGetGamepadGUIDFromMappingString(const char *pMapping) const char *pFirstComma = SDL_strchr(pMapping, ','); if (pFirstComma) { char *pchGUID = SDL_malloc(pFirstComma - pMapping + 1); - if (pchGUID == NULL) { + if (!pchGUID) { SDL_OutOfMemory(); return NULL; } @@ -1337,17 +1337,17 @@ static char *SDL_PrivateGetGamepadNameFromMappingString(const char *pMapping) char *pchName; pFirstComma = SDL_strchr(pMapping, ','); - if (pFirstComma == NULL) { + if (!pFirstComma) { return NULL; } pSecondComma = SDL_strchr(pFirstComma + 1, ','); - if (pSecondComma == NULL) { + if (!pSecondComma) { return NULL; } pchName = SDL_malloc(pSecondComma - pFirstComma); - if (pchName == NULL) { + if (!pchName) { SDL_OutOfMemory(); return NULL; } @@ -1366,12 +1366,12 @@ static char *SDL_PrivateGetGamepadMappingFromMappingString(const char *pMapping) size_t length; pFirstComma = SDL_strchr(pMapping, ','); - if (pFirstComma == NULL) { + if (!pFirstComma) { return NULL; } pSecondComma = SDL_strchr(pFirstComma + 1, ','); - if (pSecondComma == NULL) { + if (!pSecondComma) { return NULL; } @@ -1405,13 +1405,13 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co SDL_AssertJoysticksLocked(); pchName = SDL_PrivateGetGamepadNameFromMappingString(mappingString); - if (pchName == NULL) { + if (!pchName) { SDL_SetError("Couldn't parse name from %s", mappingString); return NULL; } pchMapping = SDL_PrivateGetGamepadMappingFromMappingString(mappingString); - if (pchMapping == NULL) { + if (!pchMapping) { SDL_free(pchName); SDL_SetError("Couldn't parse %s", mappingString); return NULL; @@ -1481,7 +1481,7 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co AddMappingChangeTracking(pGamepadMapping); } else { pGamepadMapping = SDL_malloc(sizeof(*pGamepadMapping)); - if (pGamepadMapping == NULL) { + if (!pGamepadMapping) { PopMappingChangeTracking(); SDL_free(pchName); SDL_free(pchMapping); @@ -1532,7 +1532,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForNameAndGUID(const char * mapping = SDL_PrivateGetGamepadMappingForGUID(guid, SDL_FALSE); #ifdef __LINUX__ - if (mapping == NULL && name) { + if (!mapping && name) { if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) { /* The Linux driver xpad.c maps the wireless dpad to buttons */ SDL_bool existing; @@ -1543,7 +1543,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForNameAndGUID(const char * } #endif /* __LINUX__ */ - if (mapping == NULL) { + if (!mapping) { mapping = s_pDefaultMapping; } return mapping; @@ -1641,7 +1641,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id name = SDL_GetJoystickInstanceName(instance_id); guid = SDL_GetJoystickInstanceGUID(instance_id); mapping = SDL_PrivateGetGamepadMappingForNameAndGUID(name, guid); - if (mapping == NULL) { + if (!mapping) { SDL_GamepadMapping raw_map; SDL_zero(raw_map); @@ -1665,7 +1665,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) size_t platform_len; buf = (char *)SDL_LoadFile_RW(src, &db_size, freesrc); - if (buf == NULL) { + if (!buf) { return SDL_SetError("Could not allocate space to read DB into memory"); } line = buf; @@ -1676,7 +1676,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) while (line < buf + db_size) { line_end = SDL_strchr(line, '\n'); - if (line_end != NULL) { + if (line_end) { *line_end = '\0'; } else { line_end = buf + db_size; @@ -1684,10 +1684,10 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) /* Extract and verify the platform */ tmp = SDL_strstr(line, SDL_GAMEPAD_PLATFORM_FIELD); - if (tmp != NULL) { + if (tmp) { tmp += SDL_GAMEPAD_PLATFORM_FIELD_SIZE; comma = SDL_strchr(tmp, ','); - if (comma != NULL) { + if (comma) { platform_len = comma - tmp + 1; if (platform_len + 1 < SDL_arraysize(line_platform)) { SDL_strlcpy(line_platform, tmp, platform_len); @@ -1751,7 +1751,7 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa SDL_AssertJoysticksLocked(); - if (mappingString == NULL) { + if (!mappingString) { return SDL_InvalidParamError("mappingString"); } @@ -1759,7 +1759,7 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa const char *tmp; tmp = SDL_strstr(mappingString, SDL_GAMEPAD_HINT_FIELD); - if (tmp != NULL) { + if (tmp) { SDL_bool default_value, value, negate; int len; char hint[128]; @@ -1801,14 +1801,14 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa const char *tmp; tmp = SDL_strstr(mappingString, SDL_GAMEPAD_SDKGE_FIELD); - if (tmp != NULL) { + if (tmp) { tmp += SDL_GAMEPAD_SDKGE_FIELD_SIZE; if (!(SDL_GetAndroidSDKVersion() >= SDL_atoi(tmp))) { return SDL_SetError("SDK version %d < minimum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); } } tmp = SDL_strstr(mappingString, SDL_GAMEPAD_SDKLE_FIELD); - if (tmp != NULL) { + if (tmp) { tmp += SDL_GAMEPAD_SDKLE_FIELD_SIZE; if (!(SDL_GetAndroidSDKVersion() <= SDL_atoi(tmp))) { return SDL_SetError("SDK version %d > maximum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); @@ -1818,7 +1818,7 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa #endif pchGUID = SDL_PrivateGetGamepadGUIDFromMappingString(mappingString); - if (pchGUID == NULL) { + if (!pchGUID) { return SDL_SetError("Couldn't parse GUID from %s", mappingString); } if (!SDL_strcasecmp(pchGUID, "default")) { @@ -1830,7 +1830,7 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa SDL_free(pchGUID); pGamepadMapping = SDL_PrivateAddMappingForGUID(jGUID, mappingString, &existing, priority); - if (pGamepadMapping == NULL) { + if (!pGamepadMapping) { return -1; } @@ -1914,7 +1914,7 @@ static char *CreateMappingString(GamepadMapping_t *mapping, SDL_JoystickGUID gui } pMappingString = SDL_malloc(needed); - if (pMappingString == NULL) { + if (!pMappingString) { SDL_OutOfMemory(); return NULL; } @@ -1965,7 +1965,7 @@ char *SDL_GetGamepadMappingForIndex(int mapping_index) } SDL_UnlockJoysticks(); - if (retval == NULL) { + if (!retval) { SDL_SetError("Mapping not available"); } return retval; @@ -2179,7 +2179,7 @@ const char *SDL_GetGamepadInstanceName(SDL_JoystickID instance_id) SDL_LockJoysticks(); { GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); - if (mapping != NULL) { + if (mapping) { if (SDL_strcmp(mapping->name, "*") == 0) { retval = SDL_GetJoystickInstanceName(instance_id); } else { @@ -2229,14 +2229,14 @@ SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id) SDL_LockJoysticks(); { GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); - if (mapping != NULL) { + if (mapping) { char *type_string, *comma; type_string = SDL_strstr(mapping->mapping, SDL_GAMEPAD_TYPE_FIELD); - if (type_string != NULL) { + if (type_string) { type_string += SDL_GAMEPAD_TYPE_FIELD_SIZE; comma = SDL_strchr(type_string, ','); - if (comma != NULL) { + if (comma) { *comma = '\0'; type = SDL_GetGamepadTypeFromString(type_string); *comma = ','; @@ -2265,7 +2265,7 @@ char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id) SDL_LockJoysticks(); { GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); - if (mapping != NULL) { + if (mapping) { SDL_JoystickGUID guid; char pchGUID[33]; size_t needed; @@ -2274,7 +2274,7 @@ char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id) /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; retval = (char *)SDL_malloc(needed); - if (retval != NULL) { + if (retval) { (void)SDL_snprintf(retval, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); } else { SDL_OutOfMemory(); @@ -2409,7 +2409,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) gamepadlist = SDL_gamepads; /* If the gamepad is already open, return it */ - while (gamepadlist != NULL) { + while (gamepadlist) { if (instance_id == gamepadlist->joystick->instance_id) { gamepad = gamepadlist; ++gamepad->ref_count; @@ -2421,7 +2421,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) /* Find a gamepad mapping */ pSupportedGamepad = SDL_PrivateGetGamepadMapping(instance_id); - if (pSupportedGamepad == NULL) { + if (!pSupportedGamepad) { SDL_SetError("Couldn't find mapping for device (%" SDL_PRIu32 ")", instance_id); SDL_UnlockJoysticks(); return NULL; @@ -2429,7 +2429,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) /* Create and initialize the gamepad */ gamepad = (SDL_Gamepad *)SDL_calloc(1, sizeof(*gamepad)); - if (gamepad == NULL) { + if (!gamepad) { SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; @@ -2437,7 +2437,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) gamepad->magic = &gamepad_magic; gamepad->joystick = SDL_OpenJoystick(instance_id); - if (gamepad->joystick == NULL) { + if (!gamepad->joystick) { SDL_free(gamepad); SDL_UnlockJoysticks(); return NULL; @@ -2923,7 +2923,7 @@ SDL_JoystickID SDL_GetGamepadInstanceID(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return 0; } return SDL_GetJoystickInstanceID(joystick); @@ -2967,7 +2967,7 @@ const char *SDL_GetGamepadPath(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return NULL; } return SDL_GetJoystickPath(joystick); @@ -2992,7 +2992,7 @@ SDL_GamepadType SDL_GetRealGamepadType(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_GAMEPAD_TYPE_UNKNOWN; } return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickGUID(joystick), SDL_GetJoystickName(joystick)); @@ -3002,7 +3002,7 @@ int SDL_GetGamepadPlayerIndex(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return -1; } return SDL_GetJoystickPlayerIndex(joystick); @@ -3015,7 +3015,7 @@ int SDL_SetGamepadPlayerIndex(SDL_Gamepad *gamepad, int player_index) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { /* SDL_SetError() will have been called already by SDL_GetGamepadJoystick() */ return -1; } @@ -3026,7 +3026,7 @@ Uint16 SDL_GetGamepadVendor(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return 0; } return SDL_GetJoystickVendor(joystick); @@ -3036,7 +3036,7 @@ Uint16 SDL_GetGamepadProduct(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return 0; } return SDL_GetJoystickProduct(joystick); @@ -3046,7 +3046,7 @@ Uint16 SDL_GetGamepadProductVersion(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return 0; } return SDL_GetJoystickProductVersion(joystick); @@ -3056,7 +3056,7 @@ Uint16 SDL_GetGamepadFirmwareVersion(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return 0; } return SDL_GetJoystickFirmwareVersion(joystick); @@ -3066,7 +3066,7 @@ const char * SDL_GetGamepadSerial(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return NULL; } return SDL_GetJoystickSerial(joystick); @@ -3076,7 +3076,7 @@ SDL_JoystickPowerLevel SDL_GetGamepadPowerLevel(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_JOYSTICK_POWER_UNKNOWN; } return SDL_GetJoystickPowerLevel(joystick); @@ -3090,7 +3090,7 @@ SDL_bool SDL_GamepadConnected(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_FALSE; } return SDL_JoystickConnected(joystick); @@ -3196,7 +3196,7 @@ int SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_frequency_rumble, Uint16 { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return -1; } return SDL_RumbleJoystick(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms); @@ -3206,7 +3206,7 @@ int SDL_RumbleGamepadTriggers(SDL_Gamepad *gamepad, Uint16 left_rumble, Uint16 r { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return -1; } return SDL_RumbleJoystickTriggers(joystick, left_rumble, right_rumble, duration_ms); @@ -3216,7 +3216,7 @@ SDL_bool SDL_GamepadHasLED(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_FALSE; } return SDL_JoystickHasLED(joystick); @@ -3226,7 +3226,7 @@ SDL_bool SDL_GamepadHasRumble(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_FALSE; } return SDL_JoystickHasRumble(joystick); @@ -3236,7 +3236,7 @@ SDL_bool SDL_GamepadHasRumbleTriggers(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return SDL_FALSE; } return SDL_JoystickHasRumbleTriggers(joystick); @@ -3246,7 +3246,7 @@ int SDL_SetGamepadLED(SDL_Gamepad *gamepad, Uint8 red, Uint8 green, Uint8 blue) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return -1; } return SDL_SetJoystickLED(joystick, red, green, blue); @@ -3256,7 +3256,7 @@ int SDL_SendGamepadEffect(SDL_Gamepad *gamepad, const void *data, int size) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - if (joystick == NULL) { + if (!joystick) { return -1; } return SDL_SendJoystickEffect(joystick, data, size); @@ -3268,7 +3268,7 @@ void SDL_CloseGamepad(SDL_Gamepad *gamepad) SDL_LockJoysticks(); - if (gamepad == NULL || gamepad->magic != &gamepad_magic) { + if (!gamepad || gamepad->magic != &gamepad_magic) { SDL_UnlockJoysticks(); return; } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 062d0626af98d..3d030e179bfa7 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -269,7 +269,7 @@ static SDL_bool SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID if (player_index >= SDL_joystick_player_count) { SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1) * sizeof(*SDL_joystick_players)); - if (new_players == NULL) { + if (!new_players) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -447,7 +447,7 @@ const char *SDL_GetJoystickInstancePath(SDL_JoystickID instance_id) SDL_UnlockJoysticks(); /* FIXME: Really we should reference count this path so it doesn't go away after unlock */ - if (path == NULL) { + if (!path) { SDL_Unsupported(); } return path; @@ -754,7 +754,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) /* Create and initialize the joystick */ joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1); - if (joystick == NULL) { + if (!joystick) { SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; @@ -2145,10 +2145,10 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n return SDL_strdup(custom_name); } - if (vendor_name == NULL) { + if (!vendor_name) { vendor_name = ""; } - if (product_name == NULL) { + if (!product_name) { product_name = ""; } @@ -2191,7 +2191,7 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n default: len = (6 + 1 + 6 + 1); name = (char *)SDL_malloc(len); - if (name != NULL) { + if (name) { (void)SDL_snprintf(name, len, "0x%.4x/0x%.4x", vendor, product); } break; @@ -2200,7 +2200,7 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n name = SDL_strdup("Controller"); } - if (name == NULL) { + if (!name) { return NULL; } @@ -2264,7 +2264,7 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc SDL_zero(guid); - if (name == NULL) { + if (!name) { name = ""; } @@ -3367,7 +3367,7 @@ void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) spot = (char *)hint; } - if (spot == NULL) { + if (!spot) { return; } @@ -3375,7 +3375,7 @@ void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) entry = (Uint16)SDL_strtol(spot, &spot, 0); entry <<= 16; spot = SDL_strstr(spot, "0x"); - if (spot == NULL) { + if (!spot) { break; } entry |= (Uint16)SDL_strtol(spot, &spot, 0); @@ -3383,7 +3383,7 @@ void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) if (list->num_entries == list->max_entries) { int max_entries = list->max_entries + 16; Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries)); - if (entries == NULL) { + if (!entries) { /* Out of memory, go with what we have already */ break; } diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 0b635ba5c2664..7333b18d8437a 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -319,7 +319,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v } } - if (JoystickByDeviceId(device_id) != NULL || name == NULL) { + if (JoystickByDeviceId(device_id) != NULL || !name) { goto done; } @@ -353,7 +353,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v } item = (SDL_joylist_item *)SDL_malloc(sizeof(SDL_joylist_item)); - if (item == NULL) { + if (!item) { goto done; } @@ -361,7 +361,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v item->guid = guid; item->device_id = device_id; item->name = SDL_CreateJoystickName(vendor_id, product_id, NULL, name); - if (item->name == NULL) { + if (!item->name) { SDL_free(item); goto done; } @@ -379,7 +379,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v item->naxes = naxes; item->nhats = nhats; item->device_instance = SDL_GetNextObjectID(); - if (SDL_joylist_tail == NULL) { + if (!SDL_joylist_tail) { SDL_joylist = SDL_joylist_tail = item; } else { SDL_joylist_tail->next = item; @@ -412,7 +412,7 @@ int Android_RemoveJoystick(int device_id) SDL_LockJoysticks(); /* Don't call JoystickByDeviceId here or there'll be an infinite loop! */ - while (item != NULL) { + while (item) { if (item->device_id == device_id) { break; } @@ -420,7 +420,7 @@ int Android_RemoveJoystick(int device_id) item = item->next; } - if (item == NULL) { + if (!item) { goto done; } @@ -428,7 +428,7 @@ int Android_RemoveJoystick(int device_id) item->joystick->hwdata = NULL; } - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_joylist == item); @@ -499,7 +499,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); device_index--; item = item->next; } @@ -511,7 +511,7 @@ static SDL_joylist_item *JoystickByDeviceId(int device_id) { SDL_joylist_item *item = SDL_joylist; - while (item != NULL) { + while (item) { if (item->device_id == device_id) { return item; } @@ -521,7 +521,7 @@ static SDL_joylist_item *JoystickByDeviceId(int device_id) /* Joystick not found, try adding it */ ANDROID_JoystickDetect(); - while (item != NULL) { + while (item) { if (item->device_id == device_id) { return item; } @@ -564,11 +564,11 @@ static int ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index) { SDL_joylist_item *item = GetJoystickByDevIndex(device_index); - if (item == NULL) { + if (!item) { return SDL_SetError("No such device"); } - if (item->joystick != NULL) { + if (item->joystick) { return SDL_SetError("Joystick already opened"); } @@ -616,7 +616,7 @@ static void ANDROID_JoystickUpdate(SDL_Joystick *joystick) { SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata; - if (item == NULL) { + if (!item) { return; } diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 176e5eebd6ad0..f764d16f63c56 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -268,7 +268,7 @@ CreateHwData(const char *path) hw = (struct joystick_hwdata *) SDL_calloc(1, sizeof(struct joystick_hwdata)); - if (hw == NULL) { + if (!hw) { close(fd); SDL_OutOfMemory(); return NULL; @@ -291,7 +291,7 @@ CreateHwData(const char *path) } } hw->repdesc = hid_get_report_desc(fd); - if (hw->repdesc == NULL) { + if (!hw->repdesc) { SDL_SetError("%s: USB_GET_REPORT_DESC: %s", path, strerror(errno)); goto usberr; @@ -318,7 +318,7 @@ CreateHwData(const char *path) #else hdata = hid_start_parse(hw->repdesc, 1 << hid_input); #endif - if (hdata == NULL) { + if (!hdata) { SDL_SetError("%s: Cannot start HID parser", path); goto usberr; } @@ -398,7 +398,7 @@ static int MaybeAddDevice(const char *path) SDL_joylist_item *item; struct joystick_hwdata *hw; - if (path == NULL) { + if (!path) { return -1; } @@ -407,14 +407,14 @@ static int MaybeAddDevice(const char *path) } /* Check to make sure it's not already in list. */ - for (item = SDL_joylist; item != NULL; item = item->next) { + for (item = SDL_joylist; item; item = item->next) { if (sb.st_rdev == item->devnum) { return -1; /* already have this one */ } } hw = CreateHwData(path); - if (hw == NULL) { + if (!hw) { return -1; } @@ -444,14 +444,14 @@ static int MaybeAddDevice(const char *path) } #endif /* USB_GET_DEVICEINFO */ } - if (name == NULL) { + if (!name) { name = SDL_strdup(path); guid = SDL_CreateJoystickGUIDForName(name); } FreeHwData(hw); item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); - if (item == NULL) { + if (!item) { SDL_free(name); return -1; } @@ -461,13 +461,13 @@ static int MaybeAddDevice(const char *path) item->name = name; item->guid = guid; - if ((item->path == NULL) || (item->name == NULL)) { + if ((!item->path) || (!item->name)) { FreeJoylistItem(item); return -1; } item->device_instance = SDL_GetNextObjectID(); - if (SDL_joylist_tail == NULL) { + if (!SDL_joylist_tail) { SDL_joylist = SDL_joylist_tail = item; } else { SDL_joylist_tail->next = item; @@ -526,7 +526,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); device_index--; item = item->next; } @@ -583,12 +583,12 @@ static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index) SDL_joylist_item *item = GetJoystickByDevIndex(device_index); struct joystick_hwdata *hw; - if (item == NULL) { + if (!item) { return SDL_SetError("No such device"); } hw = CreateHwData(item->path); - if (hw == NULL) { + if (!hw) { return -1; } @@ -664,7 +664,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) #else hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); #endif - if (hdata == NULL) { + if (!hdata) { /*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/ continue; } @@ -793,7 +793,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind) r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + r->size); #endif - if (r->buf == NULL) { + if (!r->buf) { return SDL_OutOfMemory(); } } else { diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 92650b7d48f64..288909504779a 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -40,7 +40,7 @@ static recDevice *gpDeviceList = NULL; void FreeRumbleEffectData(FFEFFECT *effect) { - if (effect == NULL) { + if (!effect) { return; } SDL_free(effect->rgdwAxes); @@ -56,7 +56,7 @@ FFEFFECT *CreateRumbleEffectData(Sint16 magnitude) /* Create the effect */ effect = (FFEFFECT *)SDL_calloc(1, sizeof(*effect)); - if (effect == NULL) { + if (!effect) { return NULL; } effect->dwSize = sizeof(*effect); @@ -80,7 +80,7 @@ FFEFFECT *CreateRumbleEffectData(Sint16 magnitude) effect->dwFlags |= FFEFF_CARTESIAN; periodic = (FFPERIODIC *)SDL_calloc(1, sizeof(*periodic)); - if (periodic == NULL) { + if (!periodic) { FreeRumbleEffectData(effect); return NULL; } @@ -506,7 +506,7 @@ static SDL_bool JoystickAlreadyKnown(IOHIDDeviceRef ioHIDDeviceObject) } #endif - for (i = gpDeviceList; i != NULL; i = i->pNext) { + for (i = gpDeviceList; i; i = i->pNext) { if (i->deviceRef == ioHIDDeviceObject) { return SDL_TRUE; } @@ -528,7 +528,7 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender } device = (recDevice *)SDL_calloc(1, sizeof(recDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return; } @@ -561,13 +561,13 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender } /* Add device to the end of the list */ - if (gpDeviceList == NULL) { + if (!gpDeviceList) { gpDeviceList = device; } else { recDevice *curdevice; curdevice = gpDeviceList; - while (curdevice->pNext != NULL) { + while (curdevice->pNext) { curdevice = curdevice->pNext; } curdevice->pNext = device; @@ -851,7 +851,7 @@ static int DARWIN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_ru /* Scale and average the two rumble strengths */ Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2); - if (device == NULL) { + if (!device) { return SDL_SetError("Rumble failed, device disconnected"); } @@ -892,7 +892,7 @@ static Uint32 DARWIN_JoystickGetCapabilities(SDL_Joystick *joystick) recDevice *device = joystick->hwdata; Uint32 result = 0; - if (device == NULL) { + if (!device) { return 0; } @@ -926,7 +926,7 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick) int i, goodRead = SDL_FALSE; Uint64 timestamp = SDL_GetTicksNS(); - if (device == NULL) { + if (!device) { return; } diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index dbce1337513d9..abf074d9b99e0 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -45,7 +45,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep } item = (SDL_joylist_item *)SDL_malloc(sizeof(SDL_joylist_item)); - if (item == NULL) { + if (!item) { return 1; } @@ -53,13 +53,13 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep item->index = gamepadEvent->index; item->name = SDL_CreateJoystickName(0, 0, NULL, gamepadEvent->id); - if (item->name == NULL) { + if (!item->name) { SDL_free(item); return 1; } item->mapping = SDL_strdup(gamepadEvent->mapping); - if (item->mapping == NULL) { + if (!item->mapping) { SDL_free(item->name); SDL_free(item); return 1; @@ -80,7 +80,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep item->digitalButton[i] = gamepadEvent->digitalButton[i]; } - if (SDL_joylist_tail == NULL) { + if (!SDL_joylist_tail) { SDL_joylist = SDL_joylist_tail = item; } else { SDL_joylist_tail->next = item; @@ -106,7 +106,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa SDL_joylist_item *item = SDL_joylist; SDL_joylist_item *prev = NULL; - while (item != NULL) { + while (item) { if (item->index == gamepadEvent->index) { break; } @@ -114,7 +114,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa item = item->next; } - if (item == NULL) { + if (!item) { return 1; } @@ -122,7 +122,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa item->joystick->hwdata = NULL; } - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_joylist == item); @@ -240,7 +240,7 @@ static SDL_joylist_item *JoystickByIndex(int index) return NULL; } - while (item != NULL) { + while (item) { if (item->index == index) { break; } @@ -292,11 +292,11 @@ static int EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index) { SDL_joylist_item *item = JoystickByDeviceIndex(device_index); - if (item == NULL) { + if (!item) { return SDL_SetError("No such device"); } - if (item->joystick != NULL) { + if (item->joystick) { return SDL_SetError("Joystick already opened"); } diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index c108e5cc02549..182f00b1be427 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -135,7 +135,7 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) #endif ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -245,7 +245,7 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device } joystick = SDL_GetJoystickFromInstanceID(ctx->joysticks[i]); - if (joystick == NULL) { + if (!joystick) { /* Hasn't been opened yet, skip */ return; } @@ -322,7 +322,7 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device joystick = SDL_GetJoystickFromInstanceID(ctx->joysticks[i]); /* Hasn't been opened yet, skip */ - if (joystick == NULL) { + if (!joystick) { continue; } } else { diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index f0f1923c5ca24..d4ee4ada86b58 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -72,7 +72,7 @@ static SDL_bool HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverLuna_Context *ctx; ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -393,7 +393,7 @@ static SDL_bool HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_LUNA_PROTOCOL HIDAPI_DumpPacket("Amazon Luna packet: size = %d", data, size); #endif - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index a84dd4b47414b..da309f7eff84b 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -134,7 +134,7 @@ static SDL_bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device) } ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -215,7 +215,7 @@ static void HIDAPI_DriverPS3_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL { SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; - if (ctx == NULL) { + if (!ctx) { return; } @@ -491,7 +491,7 @@ static SDL_bool HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_PS3_PROTOCOL HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); #endif - if (joystick == NULL) { + if (!joystick) { continue; } @@ -604,7 +604,7 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverPS3_Context *ctx; ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -932,7 +932,7 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_UpdateDevice(SDL_HIDAPI_Device *devic #ifdef DEBUG_PS3_PROTOCOL HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); #endif - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 1fb377bfa3918..d43e35604ddae 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -275,7 +275,7 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) SDL_JoystickType joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD; ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -1207,7 +1207,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) ++packet_count; ctx->last_packet = now; - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index f4b628a18c78a..35712a47dd69f 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -373,7 +373,7 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) SDL_JoystickType joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD; ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -1476,7 +1476,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) ++packet_count; ctx->last_packet = now; - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index 4035b45fe7eed..b29088cd1baf3 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -214,7 +214,7 @@ int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const } request = (SDL_HIDAPI_RumbleRequest *)SDL_calloc(1, sizeof(*request)); - if (request == NULL) { + if (!request) { SDL_HIDAPI_UnlockRumble(); return SDL_OutOfMemory(); } diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 25f81a3d1c98f..77b16da4929dd 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -114,7 +114,7 @@ static SDL_bool HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverShield_Context *ctx; ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -489,7 +489,7 @@ static SDL_bool HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) /* Byte 0 is HID report ID */ switch (data[0]) { case k_ShieldReportIdControllerState: - if (joystick == NULL) { + if (!joystick) { break; } if (size == 16) { @@ -499,7 +499,7 @@ static SDL_bool HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) } break; case k_ShieldReportIdControllerTouch: - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverShield_HandleTouchPacketV103(joystick, ctx, data, size); diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 9d7bb0bcfc7e3..d2d4fcc0e5113 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -69,7 +69,7 @@ static SDL_bool HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverStadia_Context *ctx; ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -285,7 +285,7 @@ static SDL_bool HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_STADIA_PROTOCOL HIDAPI_DumpPacket("Google Stadia packet: size = %d", data, size); #endif - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index d01d56420d3e1..0576a4496e013 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -973,7 +973,7 @@ static SDL_bool HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverSteam_Context *ctx; ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -1105,7 +1105,7 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) break; } - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index f5b0f185580a0..124bb5f5c0cf6 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -438,7 +438,7 @@ static SDL_bool WriteSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommand SwitchSubcommandInputPacket_t *reply = NULL; int nTries; - for (nTries = 1; reply == NULL && nTries <= ctx->m_nMaxWriteAttempts; ++nTries) { + for (nTries = 1; !reply && nTries <= ctx->m_nMaxWriteAttempts; ++nTries) { SwitchSubcommandOutputPacket_t commandPacket; ConstructSubcommand(ctx, ucCommandID, pBuf, ucLen, &commandPacket); @@ -462,7 +462,7 @@ static SDL_bool WriteProprietary(SDL_DriverSwitch_Context *ctx, ESwitchProprieta for (nTries = 1; nTries <= ctx->m_nMaxWriteAttempts; ++nTries) { SwitchProprietaryOutputPacket_t packet; - if ((pBuf == NULL && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) { + if ((!pBuf && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) { return SDL_FALSE; } @@ -1272,7 +1272,7 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverSwitch_Context *ctx; ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -2203,7 +2203,7 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) ++packet_count; ctx->m_ulLastInput = now; - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 037cf0252b55c..836f54dcd9eed 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -231,7 +231,7 @@ static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs exp int nRead = 0; while ((nRead = ReadInput(ctx)) != -1) { if (nRead > 0) { - if (ctx->m_rgucReadBuffer[0] == expectedID && (isMine == NULL || isMine(ctx->m_rgucReadBuffer))) { + if (ctx->m_rgucReadBuffer[0] == expectedID && (!isMine || isMine(ctx->m_rgucReadBuffer))) { return SDL_TRUE; } } else { @@ -725,7 +725,7 @@ static SDL_bool HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverWii_Context *ctx; ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index cefde2b8d8536..c83cc3dcd066f 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -139,7 +139,7 @@ static SDL_bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverXbox360_Context *ctx; ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -329,7 +329,7 @@ static SDL_bool HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_XBOX_PROTOCOL HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size); #endif - if (joystick == NULL) { + if (!joystick) { continue; } diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 30db93a2c8697..04e8010ae91b7 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -131,7 +131,7 @@ static SDL_bool HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) HIDAPI_SetDeviceName(device, "Xbox 360 Wireless Controller"); ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -158,7 +158,7 @@ static void HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device { SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context; - if (ctx == NULL) { + if (!ctx) { return; } diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index dc86c0718f7a4..b1a1af2085295 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -359,7 +359,7 @@ static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverXboxOne_Context *ctx; ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -1401,7 +1401,7 @@ static SDL_bool HIDAPI_GIP_DispatchPacket(SDL_Joystick *joystick, SDL_DriverXbox /* Ignore this packet */ break; case GIP_CMD_VIRTUAL_KEY: - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverXboxOne_HandleModePacket(joystick, ctx, data, size); @@ -1436,13 +1436,13 @@ static SDL_bool HIDAPI_GIP_DispatchPacket(SDL_Joystick *joystick, SDL_DriverXbox #endif break; } - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverXboxOne_HandleStatePacket(joystick, ctx, data, size); break; case GIP_CMD_UNMAPPED_STATE: - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverXboxOne_HandleUnmappedStatePacket(joystick, ctx, data, size); @@ -1568,7 +1568,7 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device) if (device->is_bluetooth) { switch (data[0]) { case 0x01: - if (joystick == NULL) { + if (!joystick) { break; } if (size >= 16) { @@ -1580,13 +1580,13 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device) } break; case 0x02: - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, ctx, data, size); break; case 0x04: - if (joystick == NULL) { + if (!joystick) { break; } HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, ctx, data, size); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 39cadbaf83e26..01e44286407af 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -99,7 +99,7 @@ static char *HIDAPI_ConvertString(const wchar_t *wide_string) if (wide_string) { string = SDL_iconv_string("UTF-8", "WCHAR_T", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t)); - if (string == NULL) { + if (!string) { switch (sizeof(wchar_t)) { case 2: string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t)); @@ -608,7 +608,7 @@ static int HIDAPI_JoystickInit(void) static SDL_bool HIDAPI_AddJoystickInstanceToDevice(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID) { SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1) * sizeof(*device->joysticks)); - if (joysticks == NULL) { + if (!joysticks) { return SDL_FALSE; } @@ -730,7 +730,7 @@ SDL_bool HIDAPI_HasConnectedUSBDevice(const char *serial) SDL_AssertJoysticksLocked(); - if (serial == NULL) { + if (!serial) { return SDL_FALSE; } @@ -756,7 +756,7 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial) SDL_AssertJoysticksLocked(); - if (serial == NULL) { + if (!serial) { return; } @@ -866,7 +866,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf } device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device)); - if (device == NULL) { + if (!device) { return NULL; } device->magic = &SDL_HIDAPI_device_magic; @@ -950,7 +950,9 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf } #ifdef DEBUG_HIDAPI - SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); + SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, + device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, + device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); #endif return device; @@ -964,7 +966,9 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device) SDL_AssertJoysticksLocked(); #ifdef DEBUG_HIDAPI - SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); + SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, + device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, + device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); #endif for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) { @@ -1038,7 +1042,7 @@ static SDL_bool HIDAPI_CreateCombinedJoyCons(void) if (joycons[0] && joycons[1]) { SDL_hid_device_info info; SDL_HIDAPI_Device **children = (SDL_HIDAPI_Device **)SDL_malloc(2 * sizeof(SDL_HIDAPI_Device *)); - if (children == NULL) { + if (!children) { return SDL_FALSE; } children[0] = joycons[0]; @@ -1423,13 +1427,13 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_AssertJoysticksLocked(); - if (device == NULL || !device->driver) { + if (!device || !device->driver) { /* This should never happen - validated before being called */ return SDL_SetError("Couldn't find HIDAPI device at index %d\n", device_index); } hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata)); - if (hwdata == NULL) { + if (!hwdata) { return SDL_OutOfMemory(); } hwdata->device = device; diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 9d776f5435ecf..0430a7380cfc2 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -286,7 +286,7 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick } name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string); - if (name == NULL) { + if (!name) { return 0; } @@ -335,7 +335,7 @@ static int IsSensor(const char *path, int fd) #ifdef SDL_USE_LIBUDEV static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) { - if (devpath == NULL) { + if (!devpath) { return; } @@ -393,7 +393,7 @@ static void MaybeAddDevice(const char *path) SDL_joylist_item *item; SDL_sensorlist_item *item_sensor; - if (path == NULL) { + if (!path) { return; } @@ -404,12 +404,12 @@ static void MaybeAddDevice(const char *path) SDL_LockJoysticks(); /* Check to make sure it's not already in list. */ - for (item = SDL_joylist; item != NULL; item = item->next) { + for (item = SDL_joylist; item; item = item->next) { if (sb.st_rdev == item->devnum) { goto done; /* already have this one */ } } - for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) { + for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) { if (sb.st_rdev == item_sensor->devnum) { goto done; /* already have this one */ } @@ -430,7 +430,7 @@ static void MaybeAddDevice(const char *path) #endif close(fd); item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); - if (item == NULL) { + if (!item) { SDL_free(name); goto done; } @@ -440,13 +440,13 @@ static void MaybeAddDevice(const char *path) item->name = name; item->guid = guid; - if ((item->path == NULL) || (item->name == NULL)) { + if ((!item->path) || (!item->name)) { FreeJoylistItem(item); goto done; } item->device_instance = SDL_GetNextObjectID(); - if (SDL_joylist_tail == NULL) { + if (!SDL_joylist_tail) { SDL_joylist = SDL_joylist_tail = item; } else { SDL_joylist_tail->next = item; @@ -466,13 +466,13 @@ static void MaybeAddDevice(const char *path) #endif close(fd); item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item)); - if (item_sensor == NULL) { + if (!item_sensor) { goto done; } item_sensor->devnum = sb.st_rdev; item_sensor->path = SDL_strdup(path); - if (item_sensor->path == NULL) { + if (!item_sensor->path) { FreeSensorlistItem(item_sensor); goto done; } @@ -495,7 +495,7 @@ static void RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev) item->hwdata->item = NULL; } - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_joylist == item); @@ -521,7 +521,7 @@ static void RemoveSensorlistItem(SDL_sensorlist_item *item, SDL_sensorlist_item item->hwdata->item_sensor = NULL; } - if (prev != NULL) { + if (prev) { prev->next = item->next; } else { SDL_assert(SDL_sensorlist == item); @@ -540,12 +540,12 @@ static void MaybeRemoveDevice(const char *path) SDL_sensorlist_item *item_sensor; SDL_sensorlist_item *prev_sensor = NULL; - if (path == NULL) { + if (!path) { return; } SDL_LockJoysticks(); - for (item = SDL_joylist; item != NULL; item = item->next) { + for (item = SDL_joylist; item; item = item->next) { /* found it, remove it. */ if (SDL_strcmp(path, item->path) == 0) { RemoveJoylistItem(item, prev); @@ -553,7 +553,7 @@ static void MaybeRemoveDevice(const char *path) } prev = item; } - for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) { + for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) { /* found it, remove it. */ if (SDL_strcmp(path, item_sensor->path) == 0) { RemoveSensorlistItem(item_sensor, prev_sensor); @@ -575,11 +575,11 @@ static void HandlePendingRemovals(void) SDL_AssertJoysticksLocked(); item = SDL_joylist; - while (item != NULL) { + while (item) { if (item->hwdata && item->hwdata->gone) { RemoveJoylistItem(item, prev); - if (prev != NULL) { + if (prev) { item = prev->next; } else { item = SDL_joylist; @@ -591,11 +591,11 @@ static void HandlePendingRemovals(void) } item_sensor = SDL_sensorlist; - while (item_sensor != NULL) { + while (item_sensor) { if (item_sensor->hwdata && item_sensor->hwdata->sensor_gone) { RemoveSensorlistItem(item_sensor, prev_sensor); - if (prev_sensor != NULL) { + if (prev_sensor) { item_sensor = prev_sensor->next; } else { item_sensor = SDL_sensorlist; @@ -612,7 +612,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG SDL_joylist_item *item; item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); - if (item == NULL) { + if (!item) { return SDL_FALSE; } @@ -621,14 +621,14 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG item->guid = guid; item->m_bSteamController = SDL_TRUE; - if ((item->path == NULL) || (item->name == NULL)) { + if ((!item->path) || (!item->name)) { FreeJoylistItem(item); return SDL_FALSE; } *device_instance = item->device_instance = SDL_GetNextObjectID(); SDL_LockJoysticks(); - if (SDL_joylist_tail == NULL) { + if (!SDL_joylist_tail) { SDL_joylist = SDL_joylist_tail = item; } else { SDL_joylist_tail->next = item; @@ -650,7 +650,7 @@ static void SteamControllerDisconnectedCallback(SDL_JoystickID device_instance) SDL_joylist_item *prev = NULL; SDL_LockJoysticks(); - for (item = SDL_joylist; item != NULL; item = item->next) { + for (item = SDL_joylist; item; item = item->next) { /* found it, remove it. */ if (item->device_instance == device_instance) { RemoveJoylistItem(item, prev); @@ -895,13 +895,13 @@ static int LINUX_JoystickInit(void) enumeration_method = ENUMERATION_UNSET; /* First see if the user specified one or more joysticks to use */ - if (devices != NULL) { + if (devices) { char *envcopy, *envpath, *delim; envcopy = SDL_strdup(devices); envpath = envcopy; - while (envpath != NULL) { + while (envpath) { delim = SDL_strchr(envpath, ':'); - if (delim != NULL) { + if (delim) { *delim++ = '\0'; } MaybeAddDevice(envpath); @@ -1001,7 +1001,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) item = SDL_joylist; while (device_index > 0) { - SDL_assert(item != NULL); + SDL_assert(item); device_index--; item = item->next; } @@ -1048,7 +1048,7 @@ static int allocate_hatdata(SDL_Joystick *joystick) joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(joystick->nhats * sizeof(struct hwdata_hat)); - if (joystick->hwdata->hats == NULL) { + if (!joystick->hwdata->hats) { return -1; } for (i = 0; i < joystick->nhats; ++i) { @@ -1067,7 +1067,7 @@ static SDL_bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct * other continuous analog axis, so we have to guess. */ /* If both axes are missing, they're not anything. */ - if (absinfo_x == NULL && absinfo_y == NULL) { + if (!absinfo_x && !absinfo_y) { return SDL_FALSE; } @@ -1077,12 +1077,12 @@ static SDL_bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct } /* If both axes have ranges constrained between -1 and 1, they're definitely digital. */ - if ((absinfo_x == NULL || (absinfo_x->minimum == -1 && absinfo_x->maximum == 1)) && (absinfo_y == NULL || (absinfo_y->minimum == -1 && absinfo_y->maximum == 1))) { + if ((!absinfo_x || (absinfo_x->minimum == -1 && absinfo_x->maximum == 1)) && (!absinfo_y || (absinfo_y->minimum == -1 && absinfo_y->maximum == 1))) { return SDL_TRUE; } /* If both axes lack fuzz, flat, and resolution values, they're probably digital. */ - if ((absinfo_x == NULL || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) && (absinfo_y == NULL || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution))) { + if ((!absinfo_x || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) && (!absinfo_y || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution))) { return SDL_TRUE; } @@ -1369,14 +1369,14 @@ static int PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item, return SDL_SetError("Unable to open %s", item->path); } /* If opening sensor fail, continue with buttons and axes only */ - if (item_sensor != NULL) { + if (item_sensor) { fd_sensor = open(item_sensor->path, O_RDONLY | O_CLOEXEC, 0); } joystick->hwdata->fd = fd; joystick->hwdata->fd_sensor = fd_sensor; joystick->hwdata->fname = SDL_strdup(item->path); - if (joystick->hwdata->fname == NULL) { + if (!joystick->hwdata->fname) { close(fd); if (fd_sensor >= 0) { close(fd_sensor); @@ -1404,7 +1404,7 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item) SDL_AssertJoysticksLocked(); - if (item == NULL || SDL_sensorlist == NULL) { + if (!item || !SDL_sensorlist) { return NULL; } @@ -1421,10 +1421,10 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item) SDL_Log("Joystick UNIQ: %s\n", uniq_item); #endif /* DEBUG_INPUT_EVENTS */ - for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) { + for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) { char uniq_sensor[128]; int fd_sensor = -1; - if (item_sensor->hwdata != NULL) { + if (item_sensor->hwdata) { /* already associated with another joystick */ continue; } @@ -1463,14 +1463,14 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_AssertJoysticksLocked(); item = GetJoystickByDevIndex(device_index); - if (item == NULL) { + if (!item) { return SDL_SetError("No such device"); } joystick->instance_id = item->device_instance; joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); - if (joystick->hwdata == NULL) { + if (!joystick->hwdata) { return SDL_OutOfMemory(); } @@ -1481,10 +1481,10 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) return -1; /* SDL_SetError will already have been called */ } - SDL_assert(item->hwdata == NULL); - SDL_assert(!item_sensor || item_sensor->hwdata == NULL); + SDL_assert(!item->hwdata); + SDL_assert(!item_sensor || !item_sensor->hwdata); item->hwdata = joystick->hwdata; - if (item_sensor != NULL) { + if (item_sensor) { item_sensor->hwdata = joystick->hwdata; } @@ -1589,7 +1589,7 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab } if (enabled) { - if (joystick->hwdata->item_sensor == NULL) { + if (!joystick->hwdata->item_sensor) { return SDL_SetError("Sensors unplugged."); } joystick->hwdata->fd_sensor = open(joystick->hwdata->item_sensor->path, O_RDONLY | O_CLOEXEC, 0); @@ -2146,7 +2146,7 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap /* We temporarily open the device to check how it's configured. Make a fake SDL_Joystick object to do so. */ joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1); - if (joystick == NULL) { + if (!joystick) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -2155,7 +2155,7 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); - if (joystick->hwdata == NULL) { + if (!joystick->hwdata) { SDL_free(joystick); SDL_OutOfMemory(); return SDL_FALSE; diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 29ec65f98b0da..d8ce2f8315041 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -66,7 +66,7 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata) SDL_AssertJoysticksLocked(); - if (hwdata == NULL) { + if (!hwdata) { return; } @@ -114,7 +114,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des SDL_AssertJoysticksLocked(); - if (desc == NULL) { + if (!desc) { return SDL_InvalidParamError("desc"); } if (desc->version != SDL_VIRTUAL_JOYSTICK_DESC_VERSION) { @@ -123,7 +123,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des } hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); - if (hwdata == NULL) { + if (!hwdata) { VIRTUAL_FreeHWData(hwdata); return SDL_OutOfMemory(); } @@ -257,7 +257,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des int SDL_JoystickDetachVirtualInner(SDL_JoystickID instance_id) { joystick_hwdata *hwdata = VIRTUAL_HWDataForInstance(instance_id); - if (hwdata == NULL) { + if (!hwdata) { return SDL_SetError("Virtual joystick data not found"); } VIRTUAL_FreeHWData(hwdata); @@ -271,7 +271,7 @@ int SDL_SetJoystickVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 val SDL_AssertJoysticksLocked(); - if (joystick == NULL || !joystick->hwdata) { + if (!joystick || !joystick->hwdata) { SDL_UnlockJoysticks(); return SDL_SetError("Invalid joystick"); } @@ -293,7 +293,7 @@ int SDL_SetJoystickVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8 SDL_AssertJoysticksLocked(); - if (joystick == NULL || !joystick->hwdata) { + if (!joystick || !joystick->hwdata) { SDL_UnlockJoysticks(); return SDL_SetError("Invalid joystick"); } @@ -315,7 +315,7 @@ int SDL_SetJoystickVirtualHatInner(SDL_Joystick *joystick, int hat, Uint8 value) SDL_AssertJoysticksLocked(); - if (joystick == NULL || !joystick->hwdata) { + if (!joystick || !joystick->hwdata) { SDL_UnlockJoysticks(); return SDL_SetError("Invalid joystick"); } @@ -356,7 +356,7 @@ static void VIRTUAL_JoystickDetect(void) static const char *VIRTUAL_JoystickGetDeviceName(int device_index) { joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); - if (hwdata == NULL) { + if (!hwdata) { return NULL; } return hwdata->name; @@ -384,7 +384,7 @@ static void VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_in static SDL_JoystickGUID VIRTUAL_JoystickGetDeviceGUID(int device_index) { joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); - if (hwdata == NULL) { + if (!hwdata) { SDL_JoystickGUID guid; SDL_zero(guid); return guid; @@ -395,7 +395,7 @@ static SDL_JoystickGUID VIRTUAL_JoystickGetDeviceGUID(int device_index) static SDL_JoystickID VIRTUAL_JoystickGetDeviceInstanceID(int device_index) { joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); - if (hwdata == NULL) { + if (!hwdata) { return 0; } return hwdata->instance_id; @@ -408,7 +408,7 @@ static int VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_AssertJoysticksLocked(); hwdata = VIRTUAL_HWDataForIndex(device_index); - if (hwdata == NULL) { + if (!hwdata) { return SDL_SetError("No such device"); } joystick->instance_id = hwdata->instance_id; @@ -535,7 +535,7 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick) SDL_AssertJoysticksLocked(); - if (joystick == NULL) { + if (!joystick) { return; } if (!joystick->hwdata) { diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index b6868891a9fa1..ef57755b576a7 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -271,7 +271,7 @@ static SDL_bool QueryDeviceName(LPDIRECTINPUTDEVICE8 device, char **device_name) { DIPROPSTRING dipstr; - if (!device || device_name == NULL) { + if (!device || !device_name) { return SDL_FALSE; } @@ -293,7 +293,7 @@ static SDL_bool QueryDevicePath(LPDIRECTINPUTDEVICE8 device, char **device_path) { DIPROPGUIDANDPATH dippath; - if (!device || device_path == NULL) { + if (!device || !device_path) { return SDL_FALSE; } @@ -318,7 +318,7 @@ static SDL_bool QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16 *vendor_id, { DIPROPDWORD dipdw; - if (!device || vendor_id == NULL || product_id == NULL) { + if (!device || !vendor_id || !product_id) { return SDL_FALSE; } @@ -340,7 +340,7 @@ static SDL_bool QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16 *vendor_id, void FreeRumbleEffectData(DIEFFECT *effect) { - if (effect == NULL) { + if (!effect) { return; } SDL_free(effect->rgdwAxes); @@ -356,7 +356,7 @@ DIEFFECT *CreateRumbleEffectData(Sint16 magnitude) /* Create the effect */ effect = (DIEFFECT *)SDL_calloc(1, sizeof(*effect)); - if (effect == NULL) { + if (!effect) { return NULL; } effect->dwSize = sizeof(*effect); @@ -380,7 +380,7 @@ DIEFFECT *CreateRumbleEffectData(Sint16 magnitude) effect->dwFlags |= DIEFF_CARTESIAN; periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(*periodic)); - if (periodic == NULL) { + if (!periodic) { FreeRumbleEffectData(effect); return NULL; } @@ -420,7 +420,7 @@ int SDL_DINPUT_JoystickInit(void) /* Because we used CoCreateInstance, we need to Initialize it, first. */ instance = GetModuleHandle(NULL); - if (instance == NULL) { + if (!instance) { IDirectInput8_Release(dinput); dinput = NULL; return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError()); @@ -543,7 +543,7 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext) { - if (dinput == NULL) { + if (!dinput) { return; } @@ -595,7 +595,7 @@ SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor_id, Uint16 product_id, Uint16 { Joystick_PresentData data; - if (dinput == NULL) { + if (!dinput) { return SDL_FALSE; } diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 2d8d1aa860c8a..e9f8636d6c166 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -472,7 +472,7 @@ static const IID IID_IEventHandler_Gamepad = { 0x8a7639ee, 0x624a, 0x501a, { 0xb static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This, REFIID riid, void **ppvObject) { - if (ppvObject == NULL) { + if (!ppvObject) { return E_INVALIDARG; } @@ -622,7 +622,7 @@ static int RAWINPUT_UpdateWindowsGamingInput() return SDL_OutOfMemory(); } gamepad_state = SDL_calloc(1, sizeof(*gamepad_state)); - if (gamepad_state == NULL) { + if (!gamepad_state) { return SDL_OutOfMemory(); } wgi_state.per_gamepad[wgi_state.per_gamepad_count - 1] = gamepad_state; @@ -1224,7 +1224,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ULONG i; ctx = (RAWINPUT_DeviceContext *)SDL_calloc(1, sizeof(RAWINPUT_DeviceContext)); - if (ctx == NULL) { + if (!ctx) { return SDL_OutOfMemory(); } joystick->hwdata = ctx; @@ -1237,7 +1237,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT xinput_device_change = SDL_TRUE; ctx->xinput_enabled = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, SDL_TRUE); - if (ctx->xinput_enabled && (WIN_LoadXInputDLL() < 0 || XINPUTGETSTATE == NULL)) { + if (ctx->xinput_enabled && (WIN_LoadXInputDLL() < 0 || !XINPUTGETSTATE)) { ctx->xinput_enabled = SDL_FALSE; } ctx->xinput_slot = XUSER_INDEX_ANY; @@ -1423,7 +1423,7 @@ static int RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_ if (!rumbled && ctx->xinput_correlated) { XINPUT_VIBRATION XVibration; - if (XINPUTSETSTATE == NULL) { + if (!XINPUTSETSTATE) { return SDL_Unsupported(); } diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index d939ea6cc5459..5f4ddab209f83 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -127,7 +127,7 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) } raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count); - if (raw_devices == NULL) { + if (!raw_devices) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -349,7 +349,7 @@ typedef struct RawGameControllerDelegate static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, REFIID riid, void **ppvObject) { - if (ppvObject == NULL) { + if (!ppvObject) { return E_INVALIDARG; } @@ -439,7 +439,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde } __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2); } - if (name == NULL) { + if (!name) { name = SDL_strdup(""); } @@ -719,7 +719,7 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index) boolean wireless = SDL_FALSE; hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata)); - if (hwdata == NULL) { + if (!hwdata) { return SDL_OutOfMemory(); } joystick->hwdata = hwdata; diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index a329ebfb281cc..bb95a53aca52e 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -176,7 +176,7 @@ static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID static void SDL_CleanupDeviceNotificationFunc(void) { if (cfgmgr32_lib_handle) { - if (s_DeviceNotificationFuncHandle != NULL && CM_Unregister_Notification != NULL) { + if (s_DeviceNotificationFuncHandle != NULL && CM_Unregister_Notification) { CM_Unregister_Notification(s_DeviceNotificationFuncHandle); s_DeviceNotificationFuncHandle = NULL; } @@ -294,7 +294,7 @@ static int SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data) } data->messageWindow = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); - if (data->messageWindow == NULL) { + if (!data->messageWindow) { WIN_SetError("Failed to create message window for joystick autodetect"); SDL_CleanupDeviceNotification(data); return -1; @@ -404,18 +404,18 @@ static int SDLCALL SDL_JoystickThread(void *_data) static int SDL_StartJoystickThread(void) { s_mutexJoyStickEnum = SDL_CreateMutex(); - if (s_mutexJoyStickEnum == NULL) { + if (!s_mutexJoyStickEnum) { return -1; } s_condJoystickThread = SDL_CreateCondition(); - if (s_condJoystickThread == NULL) { + if (!s_condJoystickThread) { return -1; } s_bJoystickThreadQuit = SDL_FALSE; s_joystickThread = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL); - if (s_joystickThread == NULL) { + if (!s_joystickThread) { return -1; } return 0; @@ -423,7 +423,7 @@ static int SDL_StartJoystickThread(void) static void SDL_StopJoystickThread(void) { - if (s_joystickThread == NULL) { + if (!s_joystickThread) { return; } @@ -672,7 +672,7 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->instance_id = device->nInstanceID; joystick->hwdata = (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata)); - if (joystick->hwdata == NULL) { + if (!joystick->hwdata) { return SDL_OutOfMemory(); } SDL_zerop(joystick->hwdata); diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 253e7e1086825..2c5668d7ec0d6 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -128,7 +128,7 @@ static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 * } devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count); - if (devices == NULL) { + if (!devices) { return; } @@ -275,7 +275,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC } pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData)); - if (pNewJoystick == NULL) { + if (!pNewJoystick) { return; /* better luck next time? */ } diff --git a/src/loadso/dlopen/SDL_sysloadso.c b/src/loadso/dlopen/SDL_sysloadso.c index 43ec162b0c3a7..a8f8849d9aea3 100644 --- a/src/loadso/dlopen/SDL_sysloadso.c +++ b/src/loadso/dlopen/SDL_sysloadso.c @@ -46,7 +46,7 @@ void *SDL_LoadObject(const char *sofile) handle = dlopen(sofile, RTLD_NOW | RTLD_LOCAL); loaderror = dlerror(); - if (handle == NULL) { + if (!handle) { SDL_SetError("Failed loading %s: %s", sofile, loaderror); } return handle; @@ -55,7 +55,7 @@ void *SDL_LoadObject(const char *sofile) SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) { void *symbol = dlsym(handle, name); - if (symbol == NULL) { + if (!symbol) { /* prepend an underscore for platforms that need that. */ SDL_bool isstack; size_t len = SDL_strlen(name) + 1; @@ -64,7 +64,7 @@ SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) SDL_memcpy(&_name[1], name, len); symbol = dlsym(handle, _name); SDL_small_free(_name, isstack); - if (symbol == NULL) { + if (!symbol) { SDL_SetError("Failed loading %s: %s", name, (const char *)dlerror()); } @@ -74,7 +74,7 @@ SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) void SDL_UnloadObject(void *handle) { - if (handle != NULL) { + if (handle) { dlclose(handle); } } diff --git a/src/loadso/windows/SDL_sysloadso.c b/src/loadso/windows/SDL_sysloadso.c index 94198f16cd0af..5eebf216890c8 100644 --- a/src/loadso/windows/SDL_sysloadso.c +++ b/src/loadso/windows/SDL_sysloadso.c @@ -32,7 +32,7 @@ void *SDL_LoadObject(const char *sofile) void *handle; LPTSTR tstr; - if (sofile == NULL) { + if (!sofile) { SDL_InvalidParamError("sofile"); return NULL; } @@ -49,7 +49,7 @@ void *SDL_LoadObject(const char *sofile) SDL_free(tstr); /* Generate an error message if all loads failed */ - if (handle == NULL) { + if (!handle) { char errbuf[512]; SDL_strlcpy(errbuf, "Failed loading ", SDL_arraysize(errbuf)); SDL_strlcat(errbuf, sofile, SDL_arraysize(errbuf)); @@ -61,7 +61,7 @@ void *SDL_LoadObject(const char *sofile) SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) { void *symbol = (void *)GetProcAddress((HMODULE)handle, name); - if (symbol == NULL) { + if (!symbol) { char errbuf[512]; SDL_strlcpy(errbuf, "Failed loading ", SDL_arraysize(errbuf)); SDL_strlcat(errbuf, name, SDL_arraysize(errbuf)); @@ -72,7 +72,7 @@ SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) void SDL_UnloadObject(void *handle) { - if (handle != NULL) { + if (handle) { FreeLibrary((HMODULE)handle); } } diff --git a/src/locale/SDL_locale.c b/src/locale/SDL_locale.c index 46a5a5db40fac..363d0dd86377d 100644 --- a/src/locale/SDL_locale.c +++ b/src/locale/SDL_locale.c @@ -31,7 +31,7 @@ static SDL_Locale *build_locales_from_csv_string(char *csv) SDL_Locale *loc; SDL_Locale *retval; - if (csv == NULL || !csv[0]) { + if (!csv || !csv[0]) { return NULL; /* nothing to report */ } @@ -47,7 +47,7 @@ static SDL_Locale *build_locales_from_csv_string(char *csv) alloclen = slen + (num_locales * sizeof(SDL_Locale)); loc = retval = (SDL_Locale *)SDL_calloc(1, alloclen); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; /* oh well */ } diff --git a/src/locale/unix/SDL_syslocale.c b/src/locale/unix/SDL_syslocale.c index cf48be9674c3e..bf10e3b196be7 100644 --- a/src/locale/unix/SDL_syslocale.c +++ b/src/locale/unix/SDL_syslocale.c @@ -27,12 +27,12 @@ static void normalize_locale_str(char *dst, char *str, size_t buflen) char *ptr; ptr = SDL_strchr(str, '.'); /* chop off encoding if specified. */ - if (ptr != NULL) { + if (ptr) { *ptr = '\0'; } ptr = SDL_strchr(str, '@'); /* chop off extra bits if specified. */ - if (ptr != NULL) { + if (ptr) { *ptr = '\0'; } @@ -71,7 +71,7 @@ int SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) SDL_assert(buflen > 0); tmp = SDL_small_alloc(char, buflen, &isstack); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } diff --git a/src/locale/windows/SDL_syslocale.c b/src/locale/windows/SDL_syslocale.c index 60dc98eb45f58..634e8370a98bc 100644 --- a/src/locale/windows/SDL_syslocale.c +++ b/src/locale/windows/SDL_syslocale.c @@ -61,11 +61,11 @@ static int SDL_SYS_GetPreferredLocales_vista(char *buf, size_t buflen) ULONG wbuflen = 0; SDL_bool isstack; - SDL_assert(pGetUserPreferredUILanguages != NULL); + SDL_assert(pGetUserPreferredUILanguages); pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numlangs, NULL, &wbuflen); wbuf = SDL_small_alloc(WCHAR, wbuflen, &isstack); - if (wbuf == NULL) { + if (!wbuf) { return SDL_OutOfMemory(); } @@ -102,7 +102,7 @@ int SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) } } - if (pGetUserPreferredUILanguages == NULL) { + if (!pGetUserPreferredUILanguages) { SDL_SYS_GetPreferredLocales_winxp(buf, buflen); /* this is always available */ } else { SDL_SYS_GetPreferredLocales_vista(buf, buflen); /* available on Vista and later. */ diff --git a/src/misc/SDL_url.c b/src/misc/SDL_url.c index a79a109eae7ef..aa58b536e4dab 100644 --- a/src/misc/SDL_url.c +++ b/src/misc/SDL_url.c @@ -24,7 +24,7 @@ int SDL_OpenURL(const char *url) { - if (url == NULL) { + if (!url) { return SDL_InvalidParamError("url"); } return SDL_SYS_OpenURL(url); diff --git a/src/misc/windows/SDL_sysurl.c b/src/misc/windows/SDL_sysurl.c index 03ac819f8b2c6..bb89d55f6632b 100644 --- a/src/misc/windows/SDL_sysurl.c +++ b/src/misc/windows/SDL_sysurl.c @@ -45,7 +45,7 @@ int SDL_SYS_OpenURL(const char *url) } wurl = WIN_UTF8ToStringW(url); - if (wurl == NULL) { + if (!wurl) { WIN_CoUninitialize(); return SDL_OutOfMemory(); } diff --git a/src/power/SDL_power.c b/src/power/SDL_power.c index 8676a316dd146..61921703b24fd 100644 --- a/src/power/SDL_power.c +++ b/src/power/SDL_power.c @@ -94,10 +94,10 @@ SDL_PowerState SDL_GetPowerInfo(int *seconds, int *percent) int _seconds, _percent; /* Make these never NULL for platform-specific implementations. */ - if (seconds == NULL) { + if (!seconds) { seconds = &_seconds; } - if (percent == NULL) { + if (!percent) { percent = &_percent; } diff --git a/src/power/linux/SDL_syspower.c b/src/power/linux/SDL_syspower.c index 53fb6f53baa1f..410dc6b002809 100644 --- a/src/power/linux/SDL_syspower.c +++ b/src/power/linux/SDL_syspower.c @@ -45,7 +45,7 @@ static int open_power_file(const char *base, const char *node, const char *key) int fd; const size_t pathlen = SDL_strlen(base) + SDL_strlen(node) + SDL_strlen(key) + 3; char *path = SDL_stack_alloc(char, pathlen); - if (path == NULL) { + if (!path) { return -1; /* oh well. */ } @@ -241,7 +241,7 @@ SDL_bool SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState *state, int *seconds, i *state = SDL_POWERSTATE_UNKNOWN; dirp = opendir(proc_acpi_battery_path); - if (dirp == NULL) { + if (!dirp) { return SDL_FALSE; /* can't use this interface. */ } else { while ((dent = readdir(dirp)) != NULL) { @@ -253,7 +253,7 @@ SDL_bool SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState *state, int *seconds, i } dirp = opendir(proc_acpi_ac_adapter_path); - if (dirp == NULL) { + if (!dirp) { return SDL_FALSE; /* can't use this interface. */ } else { while ((dent = readdir(dirp)) != NULL) { @@ -424,7 +424,7 @@ SDL_bool SDL_GetPowerInfo_Linux_sys_class_power_supply(SDL_PowerState *state, in DIR *dirp; dirp = opendir(base); - if (dirp == NULL) { + if (!dirp) { return SDL_FALSE; } @@ -623,7 +623,7 @@ SDL_bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *state, in char **paths = NULL; int i, numpaths = 0; - if (dbus == NULL || !SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "EnumerateDevices", + if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "EnumerateDevices", DBUS_TYPE_INVALID, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &numpaths, DBUS_TYPE_INVALID)) { return SDL_FALSE; /* try a different approach than UPower. */ diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 1d55c87b72b31..8bf12cc8396a5 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -229,9 +229,9 @@ static int FlushRenderCommands(SDL_Renderer *renderer) { int retval; - SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL)); + SDL_assert((!renderer->render_commands) == (!renderer->render_commands_tail)); - if (renderer->render_commands == NULL) { /* nothing to do! */ + if (!renderer->render_commands) { /* nothing to do! */ SDL_assert(renderer->vertex_data_used == 0); return 0; } @@ -241,7 +241,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer) retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used); /* Move the whole render command queue to the unused pool so we can reuse them next time. */ - if (renderer->render_commands_tail != NULL) { + if (renderer->render_commands_tail) { renderer->render_commands_tail->next = renderer->render_commands_pool; renderer->render_commands_pool = renderer->render_commands; renderer->render_commands_tail = NULL; @@ -293,7 +293,7 @@ void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, ptr = SDL_realloc(renderer->vertex_data, newsize); - if (ptr == NULL) { + if (!ptr) { SDL_OutOfMemory(); return NULL; } @@ -316,19 +316,19 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) /* !!! FIXME: are there threading limitations in SDL's render API? If not, we need to mutex this. */ retval = renderer->render_commands_pool; - if (retval != NULL) { + if (retval) { renderer->render_commands_pool = retval->next; retval->next = NULL; } else { retval = SDL_calloc(1, sizeof(*retval)); - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } } - SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL)); - if (renderer->render_commands_tail != NULL) { + SDL_assert((!renderer->render_commands) == (!renderer->render_commands_tail)); + if (renderer->render_commands_tail) { renderer->render_commands_tail->next = retval; } else { renderer->render_commands = retval; @@ -364,7 +364,7 @@ static int QueueCmdSetViewport(SDL_Renderer *renderer) if (!renderer->viewport_queued || SDL_memcmp(&viewport, &renderer->last_queued_viewport, sizeof(viewport)) != 0) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); - if (cmd != NULL) { + if (cmd) { cmd->command = SDL_RENDERCMD_SETVIEWPORT; cmd->data.viewport.first = 0; /* render backend will fill this in. */ SDL_copyp(&cmd->data.viewport.rect, &viewport); @@ -396,7 +396,7 @@ static int QueueCmdSetClipRect(SDL_Renderer *renderer) renderer->view->clipping_enabled != renderer->last_queued_cliprect_enabled || SDL_memcmp(&clip_rect, &renderer->last_queued_cliprect, sizeof(clip_rect)) != 0) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); - if (cmd != NULL) { + if (cmd) { cmd->command = SDL_RENDERCMD_SETCLIPRECT; cmd->data.cliprect.enabled = renderer->view->clipping_enabled; SDL_copyp(&cmd->data.cliprect.rect, &clip_rect); @@ -419,7 +419,7 @@ static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_Color *col) SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); retval = -1; - if (cmd != NULL) { + if (cmd) { cmd->command = SDL_RENDERCMD_SETDRAWCOLOR; cmd->data.color.first = 0; /* render backend will fill this in. */ cmd->data.color.r = col->r; @@ -441,7 +441,7 @@ static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_Color *col) static int QueueCmdClear(SDL_Renderer *renderer) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); - if (cmd == NULL) { + if (!cmd) { return -1; } @@ -484,7 +484,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren if (retval == 0) { cmd = AllocateRenderCommand(renderer); - if (cmd != NULL) { + if (cmd) { cmd->command = cmdtype; cmd->data.draw.first = 0; /* render backend will fill this in. */ cmd->data.draw.count = 0; /* render backend will fill this in. */ @@ -503,7 +503,7 @@ static int QueueCmdDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, { SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_DRAW_POINTS, NULL); int retval = -1; - if (cmd != NULL) { + if (cmd) { retval = renderer->QueueDrawPoints(renderer, cmd, points, count); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; @@ -516,7 +516,7 @@ static int QueueCmdDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, c { SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_DRAW_LINES, NULL); int retval = -1; - if (cmd != NULL) { + if (cmd) { retval = renderer->QueueDrawLines(renderer, cmd, points, count); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; @@ -529,11 +529,11 @@ static int QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, con { SDL_RenderCommand *cmd; int retval = -1; - const int use_rendergeometry = (renderer->QueueFillRects == NULL); + const int use_rendergeometry = (!renderer->QueueFillRects); cmd = PrepQueueCmdDraw(renderer, (use_rendergeometry ? SDL_RENDERCMD_GEOMETRY : SDL_RENDERCMD_FILL_RECTS), NULL); - if (cmd != NULL) { + if (cmd) { if (use_rendergeometry) { SDL_bool isstack1; SDL_bool isstack2; @@ -603,7 +603,7 @@ static int QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_ { SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY, texture); int retval = -1; - if (cmd != NULL) { + if (cmd) { retval = renderer->QueueCopy(renderer, cmd, texture, srcrect, dstrect); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; @@ -618,7 +618,7 @@ static int QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, { SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY_EX, texture); int retval = -1; - if (cmd != NULL) { + if (cmd) { retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip, scale_x, scale_y); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; @@ -638,7 +638,7 @@ static int QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, SDL_RenderCommand *cmd; int retval = -1; cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); - if (cmd != NULL) { + if (cmd) { retval = renderer->QueueGeometry(renderer, cmd, texture, xy, xy_stride, color, color_stride, uv, uv_stride, @@ -751,13 +751,13 @@ static SDL_INLINE void VerifyDrawQueueFunctions(const SDL_Renderer *renderer) { /* all of these functions are required to be implemented, even as no-ops, so we don't have to check that they aren't NULL over and over. */ - SDL_assert(renderer->QueueSetViewport != NULL); - SDL_assert(renderer->QueueSetDrawColor != NULL); - SDL_assert(renderer->QueueDrawPoints != NULL); - SDL_assert(renderer->QueueDrawLines != NULL || renderer->QueueGeometry != NULL); - SDL_assert(renderer->QueueFillRects != NULL || renderer->QueueGeometry != NULL); - SDL_assert(renderer->QueueCopy != NULL || renderer->QueueGeometry != NULL); - SDL_assert(renderer->RunCommandQueue != NULL); + SDL_assert(renderer->QueueSetViewport); + SDL_assert(renderer->QueueSetDrawColor); + SDL_assert(renderer->QueueDrawPoints); + SDL_assert(renderer->QueueDrawLines || renderer->QueueGeometry); + SDL_assert(renderer->QueueFillRects || renderer->QueueGeometry); + SDL_assert(renderer->QueueCopy || renderer->QueueGeometry); + SDL_assert(renderer->RunCommandQueue); } static SDL_RenderLineMethod SDL_GetRenderLineMethod(void) @@ -817,7 +817,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl Android_ActivityMutex_Lock_Running(); #endif - if (window == NULL) { + if (!window) { SDL_InvalidParamError("window"); goto error; } @@ -871,7 +871,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl } } - if (renderer == NULL) { + if (!renderer) { SDL_SetError("Couldn't find matching render driver"); goto error; } @@ -1105,7 +1105,7 @@ static SDL_ScaleMode SDL_GetScaleMode(void) { const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); - if (hint == NULL || SDL_strcasecmp(hint, "nearest") == 0) { + if (!hint || SDL_strcasecmp(hint, "nearest") == 0) { return SDL_SCALEMODE_NEAREST; } else if (SDL_strcasecmp(hint, "linear") == 0) { return SDL_SCALEMODE_LINEAR; @@ -1146,7 +1146,7 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access return NULL; } texture = (SDL_Texture *)SDL_calloc(1, sizeof(*texture)); - if (texture == NULL) { + if (!texture) { SDL_OutOfMemory(); return NULL; } @@ -1243,7 +1243,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s CHECK_RENDERER_MAGIC(renderer, NULL); - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("SDL_CreateTextureFromSurface(): surface"); return NULL; } @@ -1307,7 +1307,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, surface->w, surface->h); - if (texture == NULL) { + if (!texture) { return NULL; } @@ -1339,7 +1339,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s /* Set up a destination surface for the texture update */ dst_fmt = SDL_CreatePixelFormat(format); - if (dst_fmt == NULL) { + if (!dst_fmt) { SDL_DestroyTexture(texture); return NULL; } @@ -1541,7 +1541,7 @@ static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, const size_t alloclen = (size_t)rect->h * temp_pitch; if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, @@ -1581,7 +1581,7 @@ static int SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect, const size_t alloclen = (size_t)rect->h * temp_pitch; if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } SDL_ConvertPixels(rect->w, rect->h, @@ -1600,7 +1600,7 @@ int SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pi CHECK_TEXTURE_MAGIC(texture, -1); - if (pixels == NULL) { + if (!pixels) { return SDL_InvalidParamError("pixels"); } if (!pitch) { @@ -1674,7 +1674,7 @@ static int SDL_UpdateTextureYUVPlanar(SDL_Texture *texture, const SDL_Rect *rect const size_t alloclen = (size_t)rect->h * temp_pitch; if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, @@ -1724,7 +1724,7 @@ static int SDL_UpdateTextureNVPlanar(SDL_Texture *texture, const SDL_Rect *rect, const size_t alloclen = (size_t)rect->h * temp_pitch; if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, @@ -1749,19 +1749,19 @@ int SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect, CHECK_TEXTURE_MAGIC(texture, -1); - if (Yplane == NULL) { + if (!Yplane) { return SDL_InvalidParamError("Yplane"); } if (!Ypitch) { return SDL_InvalidParamError("Ypitch"); } - if (Uplane == NULL) { + if (!Uplane) { return SDL_InvalidParamError("Uplane"); } if (!Upitch) { return SDL_InvalidParamError("Upitch"); } - if (Vplane == NULL) { + if (!Vplane) { return SDL_InvalidParamError("Vplane"); } if (!Vpitch) { @@ -1815,13 +1815,13 @@ int SDL_UpdateNVTexture(SDL_Texture *texture, const SDL_Rect *rect, CHECK_TEXTURE_MAGIC(texture, -1); - if (Yplane == NULL) { + if (!Yplane) { return SDL_InvalidParamError("Yplane"); } if (!Ypitch) { return SDL_InvalidParamError("Ypitch"); } - if (UVplane == NULL) { + if (!UVplane) { return SDL_InvalidParamError("UVplane"); } if (!UVpitch) { @@ -1894,7 +1894,7 @@ int SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, i return SDL_SetError("SDL_LockTexture(): texture must be streaming"); } - if (rect == NULL) { + if (!rect) { full_rect.x = 0; full_rect.y = 0; full_rect.w = texture->w; @@ -1929,7 +1929,7 @@ int SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Sur int pitch = 0; /* fix static analysis */ int ret; - if (texture == NULL || surface == NULL) { + if (!texture || !surface) { return -1; } @@ -1947,7 +1947,7 @@ int SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Sur } texture->locked_surface = SDL_CreateSurfaceFrom(pixels, real_rect.w, real_rect.h, pitch, texture->format); - if (texture->locked_surface == NULL) { + if (!texture->locked_surface) { SDL_UnlockTexture(texture); return -1; } @@ -2074,7 +2074,7 @@ static int SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *text int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { - if (texture == NULL && renderer->logical_target) { + if (!texture && renderer->logical_target) { return SDL_SetRenderTargetInternal(renderer, renderer->logical_target); } else { return SDL_SetRenderTargetInternal(renderer, texture); @@ -2304,7 +2304,7 @@ static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) static void SDL_RenderLogicalPresentation(SDL_Renderer *renderer) { - SDL_assert(renderer->target == NULL); + SDL_assert(!renderer->target); SDL_SetRenderViewport(renderer, NULL); SDL_SetRenderClipRect(renderer, NULL); SDL_SetRenderScale(renderer, 1.0f, 1.0f); @@ -2673,7 +2673,7 @@ static int RenderPointsWithRects(SDL_Renderer *renderer, const SDL_FPoint *fpoin } frects = SDL_small_alloc(SDL_FRect, count, &isstack); - if (frects == NULL) { + if (!frects) { return SDL_OutOfMemory(); } @@ -2697,7 +2697,7 @@ int SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count CHECK_RENDERER_MAGIC(renderer, -1); - if (points == NULL) { + if (!points) { return SDL_InvalidParamError("SDL_RenderPoints(): points"); } if (count < 1) { @@ -2784,7 +2784,7 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i } points = SDL_small_alloc(SDL_FPoint, numpixels, &isstack); - if (points == NULL) { + if (!points) { return SDL_OutOfMemory(); } for (i = 0; i < numpixels; ++i) { @@ -2827,7 +2827,7 @@ static int RenderLinesWithRectsF(SDL_Renderer *renderer, SDL_bool draw_last = SDL_FALSE; frects = SDL_small_alloc(SDL_FRect, count - 1, &isstack); - if (frects == NULL) { + if (!frects) { return SDL_OutOfMemory(); } @@ -2893,7 +2893,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) CHECK_RENDERER_MAGIC(renderer, -1); - if (points == NULL) { + if (!points) { return SDL_InvalidParamError("SDL_RenderLines(): points"); } if (count < 2) { @@ -3046,7 +3046,7 @@ int SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect) CHECK_RENDERER_MAGIC(renderer, -1); /* If 'rect' == NULL, then outline the whole surface */ - if (rect == NULL) { + if (!rect) { GetRenderViewportSize(renderer, &frect); rect = &frect; } @@ -3070,7 +3070,7 @@ int SDL_RenderRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count) CHECK_RENDERER_MAGIC(renderer, -1); - if (rects == NULL) { + if (!rects) { return SDL_InvalidParamError("SDL_RenderRects(): rects"); } if (count < 1) { @@ -3099,7 +3099,7 @@ int SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect) CHECK_RENDERER_MAGIC(renderer, -1); /* If 'rect' == NULL, then fill the whole surface */ - if (rect == NULL) { + if (!rect) { GetRenderViewportSize(renderer, &frect); rect = &frect; } @@ -3115,7 +3115,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun CHECK_RENDERER_MAGIC(renderer, -1); - if (rects == NULL) { + if (!rects) { return SDL_InvalidParamError("SDL_RenderFillRects(): rects"); } if (count < 1) { @@ -3130,7 +3130,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun #endif frects = SDL_small_alloc(SDL_FRect, count, &isstack); - if (frects == NULL) { + if (!frects) { return SDL_OutOfMemory(); } for (i = 0; i < count; ++i) { @@ -3168,7 +3168,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR } #endif - use_rendergeometry = (renderer->QueueCopy == NULL); + use_rendergeometry = (!renderer->QueueCopy); real_srcrect.x = 0.0f; real_srcrect.y = 0.0f; @@ -3283,7 +3283,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, } #endif - use_rendergeometry = (renderer->QueueCopyEx == NULL); + use_rendergeometry = (!renderer->QueueCopyEx); real_srcrect.x = 0.0f; real_srcrect.y = 0.0f; @@ -3823,15 +3823,15 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, } } - if (xy == NULL) { + if (!xy) { return SDL_InvalidParamError("xy"); } - if (color == NULL) { + if (!color) { return SDL_InvalidParamError("color"); } - if (texture && uv == NULL) { + if (texture && !uv) { return SDL_InvalidParamError("uv"); } @@ -3923,7 +3923,7 @@ int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 fo FlushRenderCommands(renderer); /* we need to render before we read the results. */ if (!format) { - if (renderer->target == NULL) { + if (!renderer->target) { format = SDL_GetWindowPixelFormat(renderer->window); } else { format = renderer->target->format; @@ -4078,7 +4078,7 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer) { SDL_RenderCommand *cmd; - if (renderer->render_commands_tail != NULL) { + if (renderer->render_commands_tail) { renderer->render_commands_tail->next = renderer->render_commands_pool; cmd = renderer->render_commands; } else { @@ -4089,7 +4089,7 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer) renderer->render_commands_tail = NULL; renderer->render_commands = NULL; - while (cmd != NULL) { + while (cmd) { SDL_RenderCommand *next = cmd->next; SDL_free(cmd); cmd = next; @@ -4319,7 +4319,7 @@ int SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync) int SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync) { CHECK_RENDERER_MAGIC(renderer, -1); - if (vsync == NULL) { + if (!vsync) { return SDL_InvalidParamError("vsync"); } *vsync = renderer->wanted_vsync; diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index bcc7cdfc04270..9c123dd0422f7 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -46,7 +46,7 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) } swdata = (SDL_SW_YUVTexture *)SDL_calloc(1, sizeof(*swdata)); - if (swdata == NULL) { + if (!swdata) { SDL_OutOfMemory(); return NULL; } diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 9324087eb8bb0..7870d10eb4ff1 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -432,7 +432,7 @@ static int D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *te { HRESULT result; - if (texture->staging == NULL) { + if (!texture->staging) { result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0, texture->d3dfmt, D3DPOOL_SYSTEMMEM, &texture->staging, NULL); if (FAILED(result)) { @@ -524,7 +524,7 @@ static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) DWORD usage; texturedata = (D3D_TextureData *)SDL_calloc(1, sizeof(*texturedata)); - if (texturedata == NULL) { + if (!texturedata) { return SDL_OutOfMemory(); } texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR; @@ -562,7 +562,7 @@ static int D3D_RecreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return 0; } @@ -589,7 +589,7 @@ static int D3D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return SDL_SetError("Texture is not currently available"); } @@ -625,7 +625,7 @@ static int D3D_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return SDL_SetError("Texture is not currently available"); } @@ -649,7 +649,7 @@ static int D3D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; IDirect3DDevice9 *device = data->device; - if (texturedata == NULL) { + if (!texturedata) { return SDL_SetError("Texture is not currently available"); } #if SDL_HAVE_YUV @@ -699,7 +699,7 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return; } #if SDL_HAVE_YUV @@ -727,7 +727,7 @@ static void D3D_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture { D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return; } @@ -743,18 +743,18 @@ static int D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *text IDirect3DDevice9 *device = data->device; /* Release the previous render target if it wasn't the default one */ - if (data->currentRenderTarget != NULL) { + if (data->currentRenderTarget) { IDirect3DSurface9_Release(data->currentRenderTarget); data->currentRenderTarget = NULL; } - if (texture == NULL) { + if (!texture) { IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget); return 0; } texturedata = (D3D_TextureData *)texture->driverdata; - if (texturedata == NULL) { + if (!texturedata) { return SDL_SetError("Texture is not currently available"); } @@ -809,7 +809,7 @@ static int D3D_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -834,7 +834,7 @@ static int D3D_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL int count = indices ? num_indices : num_vertices; Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(Vertex), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -928,9 +928,9 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, LPDIREC { D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - SDL_assert(*shader == NULL); + SDL_assert(!*shader); - if (texturedata == NULL) { + if (!texturedata) { return SDL_SetError("Texture is not currently available"); } @@ -982,11 +982,11 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) LPDIRECT3DPIXELSHADER9 shader = NULL; /* disable any enabled textures we aren't going to use, let SetupTextureState() do the rest. */ - if (texture == NULL) { + if (!texture) { IDirect3DDevice9_SetTexture(data->device, 0, NULL); } #if SDL_HAVE_YUV - if ((newtexturedata == NULL || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) { + if ((!newtexturedata || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) { IDirect3DDevice9_SetTexture(data->device, 1, NULL); IDirect3DDevice9_SetTexture(data->device, 2, NULL); } @@ -1380,7 +1380,7 @@ static void D3D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) #endif } - if (data == NULL) { + if (!data) { return; } @@ -1406,7 +1406,7 @@ static void D3D_DestroyRenderer(SDL_Renderer *renderer) IDirect3DSurface9_Release(data->defaultRenderTarget); data->defaultRenderTarget = NULL; } - if (data->currentRenderTarget != NULL) { + if (data->currentRenderTarget) { IDirect3DSurface9_Release(data->currentRenderTarget); data->currentRenderTarget = NULL; } @@ -1457,7 +1457,7 @@ static int D3D_Reset(SDL_Renderer *renderer) IDirect3DSurface9_Release(data->defaultRenderTarget); data->defaultRenderTarget = NULL; } - if (data->currentRenderTarget != NULL) { + if (data->currentRenderTarget) { IDirect3DSurface9_Release(data->currentRenderTarget); data->currentRenderTarget = NULL; } @@ -1550,14 +1550,14 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) const SDL_DisplayMode *fullscreen_mode = NULL; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index ef11c7de3b074..b66cd4fd556fc 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -397,7 +397,7 @@ static ID3D11BlendState *D3D11_CreateBlendState(SDL_Renderer *renderer, SDL_Blen } blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes)); - if (blendModes == NULL) { + if (!blendModes) { SAFE_RELEASE(blendState); SDL_OutOfMemory(); return NULL; @@ -454,7 +454,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) } CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory"); - if (CreateDXGIFactoryFunc == NULL) { + if (!CreateDXGIFactoryFunc) { result = E_FAIL; goto done; } @@ -754,7 +754,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; #ifdef __WINRT__ IUnknown *coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer); - const BOOL usingXAML = (coreWindow == NULL); + const BOOL usingXAML = (!coreWindow); #else IUnknown *coreWindow = NULL; const BOOL usingXAML = FALSE; @@ -941,7 +941,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer) #endif } else { result = D3D11_CreateSwapChain(renderer, w, h); - if (FAILED(result) || data->swapChain == NULL) { + if (FAILED(result) || !data->swapChain) { goto done; } } @@ -1075,7 +1075,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) } textureData = (D3D11_TextureData *)SDL_calloc(1, sizeof(*textureData)); - if (textureData == NULL) { + if (!textureData) { SDL_OutOfMemory(); return -1; } @@ -1220,7 +1220,7 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer, { D3D11_TextureData *data = (D3D11_TextureData *)texture->driverdata; - if (data == NULL) { + if (!data) { return; } @@ -1331,7 +1331,7 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1367,7 +1367,7 @@ static int D3D11_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1399,7 +1399,7 @@ static int D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, D3D11_TEXTURE2D_DESC stagingTextureDesc; D3D11_MAPPED_SUBRESOURCE textureMemory; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1507,7 +1507,7 @@ static int D3D11_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, D3D11_TEXTURE2D_DESC stagingTextureDesc; D3D11_MAPPED_SUBRESOURCE textureMemory; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } #if SDL_HAVE_YUV @@ -1586,7 +1586,7 @@ static void D3D11_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return; } #if SDL_HAVE_YUV @@ -1622,7 +1622,7 @@ static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu { D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return; } @@ -1635,7 +1635,7 @@ static IDXGIResource *D3D11_GetTextureDXGIResource(SDL_Texture *texture) IDXGIResource *resource = NULL; HRESULT result; - if (textureData == NULL || textureData->mainTexture == NULL) { + if (!textureData || !textureData->mainTexture) { SDL_SetError("Texture is not currently available"); return NULL; } @@ -1654,7 +1654,7 @@ static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = NULL; - if (texture == NULL) { + if (!texture) { rendererData->currentOffscreenRenderTargetView = NULL; return 0; } @@ -1685,7 +1685,7 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, color.b = cmd->data.draw.b; color.a = cmd->data.draw.a; - if (verts == NULL) { + if (!verts) { return -1; } @@ -1712,7 +1712,7 @@ static int D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S int count = indices ? num_indices : num_vertices; VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -1984,9 +1984,9 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c break; } } - if (blendState == NULL) { + if (!blendState) { blendState = D3D11_CreateBlendState(renderer, blendMode); - if (blendState == NULL) { + if (!blendState) { return -1; } } @@ -2239,13 +2239,13 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, D3D11_MAPPED_SUBRESOURCE textureMemory; renderTargetView = D3D11_GetCurrentRenderTargetView(renderer); - if (renderTargetView == NULL) { + if (!renderTargetView) { SDL_SetError("%s, ID3D11DeviceContext::OMGetRenderTargets failed", __FUNCTION__); goto done; } ID3D11View_GetResource(renderTargetView, (ID3D11Resource **)&backBuffer); - if (backBuffer == NULL) { + if (!backBuffer) { SDL_SetError("%s, ID3D11View::GetResource failed", __FUNCTION__); goto done; } @@ -2400,14 +2400,14 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) D3D11_RenderData *data; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 8e89185a0103f..00b24aec1559b 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -642,7 +642,7 @@ static D3D12_PipelineState *D3D12_CreatePipelineState(SDL_Renderer *renderer, } pipelineStates = (D3D12_PipelineState *)SDL_realloc(data->pipelineStates, (data->pipelineStateCount + 1) * sizeof(*pipelineStates)); - if (pipelineStates == NULL) { + if (!pipelineStates) { SAFE_RELEASE(pipelineState); SDL_OutOfMemory(); return NULL; @@ -757,7 +757,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) } } #endif - if (CreateEventExFunc == NULL) { + if (!CreateEventExFunc) { result = E_FAIL; goto done; } @@ -770,7 +770,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) } CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory2"); - if (CreateDXGIFactoryFunc == NULL) { + if (!CreateDXGIFactoryFunc) { result = E_FAIL; goto done; } @@ -814,7 +814,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) /* If the debug hint is set, also create the DXGI factory in debug mode */ DXGIGetDebugInterfaceFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "DXGIGetDebugInterface1"); - if (DXGIGetDebugInterfaceFunc == NULL) { + if (!DXGIGetDebugInterfaceFunc) { result = E_FAIL; goto done; } @@ -1445,7 +1445,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) } textureData = (D3D12_TextureData *)SDL_calloc(1, sizeof(*textureData)); - if (textureData == NULL) { + if (!textureData) { SDL_OutOfMemory(); return -1; } @@ -1603,7 +1603,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return; } @@ -1770,7 +1770,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1815,7 +1815,7 @@ static int D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1839,7 +1839,7 @@ static int D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } @@ -1868,7 +1868,7 @@ static int D3D12_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, BYTE *textureMemory; int bpp; - if (textureData == NULL) { + if (!textureData) { return SDL_SetError("Texture is not currently available"); } #if SDL_HAVE_YUV @@ -1987,7 +1987,7 @@ static void D3D12_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_TEXTURE_COPY_LOCATION dstLocation; int bpp; - if (textureData == NULL) { + if (!textureData) { return; } #if SDL_HAVE_YUV @@ -2058,7 +2058,7 @@ static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu { D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - if (textureData == NULL) { + if (!textureData) { return; } @@ -2071,7 +2071,7 @@ static IDXGIResource *D3D12_GetTextureDXGIResource(SDL_Texture *texture) IDXGIResource *resource = NULL; HRESULT result; - if (textureData == NULL || textureData->mainTexture == NULL) { + if (!textureData || !textureData->mainTexture) { SDL_SetError("Texture is not currently available"); return NULL; } @@ -2089,7 +2089,7 @@ static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData = NULL; - if (texture == NULL) { + if (!texture) { if (rendererData->textureRenderTarget) { D3D12_TransitionResource(rendererData, rendererData->textureRenderTarget->mainTexture, @@ -2132,7 +2132,7 @@ static int D3D12_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, color.b = cmd->data.draw.b; color.a = cmd->data.draw.a; - if (verts == NULL) { + if (!verts) { return -1; } @@ -2159,7 +2159,7 @@ static int D3D12_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S int count = indices ? num_indices : num_vertices; VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -2958,14 +2958,14 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) D3D12_RenderData *data; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 2d7da74667b92..41a6cce73ba55 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -183,7 +183,7 @@ static void GL_ClearErrors(SDL_Renderer *renderer) data->errors = 0; data->error_messages = NULL; } - } else if (data->glGetError != NULL) { + } else if (data->glGetError) { while (data->glGetError() != GL_NO_ERROR) { /* continue; */ } @@ -302,7 +302,7 @@ static GL_FBOList *GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h) result = result->next; } - if (result == NULL) { + if (!result) { result = SDL_malloc(sizeof(GL_FBOList)); if (result) { result->w = w; @@ -460,7 +460,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) } data = (GL_TextureData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } @@ -877,7 +877,7 @@ static int GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) data->drawstate.viewport_dirty = SDL_TRUE; - if (texture == NULL) { + if (!texture) { data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); return 0; } @@ -907,7 +907,7 @@ static int GL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(GLfloat), 0, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -927,7 +927,7 @@ static int GL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, con const size_t vertlen = (sizeof(GLfloat) * 2) * count; GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } cmd->data.draw.count = count; @@ -972,7 +972,7 @@ static int GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_ size_t sz = 2 * sizeof(GLfloat) + 4 * sizeof(Uint8) + (texture ? 2 : 0) * sizeof(GLfloat); verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -1078,7 +1078,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const } if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) { - if (cmd->data.draw.texture == NULL) { + if (!cmd->data.draw.texture) { data->glDisable(data->textype); data->drawstate.texturing = SDL_FALSE; } else { @@ -1283,7 +1283,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SDL_RenderCommand *nextcmd = cmd->next; SDL_BlendMode thisblend = cmd->data.draw.blend; - while (nextcmd != NULL) { + while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) { break; /* can't go any further on this draw call, different render command up next. */ @@ -1317,7 +1317,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SDL_RenderCommand *nextcmd = cmd->next; size_t count = cmd->data.draw.count; int ret; - while (nextcmd != NULL) { + while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; if (nextcmdtype != thiscmdtype) { break; /* can't go any further on this draw call, different render command up next. */ @@ -1426,7 +1426,7 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); temp_pixels = SDL_malloc((size_t)rect->h * temp_pitch); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } @@ -1491,7 +1491,7 @@ static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) renderdata->drawstate.target = NULL; } - if (data == NULL) { + if (!data) { return; } if (data->texture) { @@ -1513,7 +1513,7 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer) GL_RenderData *data = (GL_RenderData *)renderer->driverdata; if (data) { - if (data->context != NULL) { + if (data->context) { /* make sure we delete the right resources! */ GL_ActivateRenderer(renderer); } @@ -1728,13 +1728,13 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) #endif renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); goto error; } data = (GL_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); goto error; @@ -1836,7 +1836,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) } hint = SDL_getenv("GL_ARB_texture_non_power_of_two"); - if (hint == NULL || *hint != '0') { + if (!hint || *hint != '0') { SDL_bool isGL2 = SDL_FALSE; const char *verstr = (const char *)data->glGetString(GL_VERSION); if (verstr) { diff --git a/src/render/opengl/SDL_shaders_gl.c b/src/render/opengl/SDL_shaders_gl.c index 4a35e1e7fa08a..2416038a08ffb 100644 --- a/src/render/opengl/SDL_shaders_gl.c +++ b/src/render/opengl/SDL_shaders_gl.c @@ -495,7 +495,7 @@ GL_ShaderContext *GL_CreateShaderContext(void) int i; ctx = (GL_ShaderContext *)SDL_calloc(1, sizeof(*ctx)); - if (ctx == NULL) { + if (!ctx) { return NULL; } diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 7216a6140f53b..75f9e2c60ed79 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -216,7 +216,7 @@ static int GL_CheckAllErrors(const char *prefix, SDL_Renderer *renderer, const c for (;;) { GLenum error = data->glGetError(); if (error != GL_NO_ERROR) { - if (prefix == NULL || prefix[0] == '\0') { + if (!prefix || prefix[0] == '\0') { prefix = "generic"; } SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error); @@ -269,7 +269,7 @@ static GLES2_FBOList *GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h) while ((result) && ((result->w != w) || (result->h != h))) { result = result->next; } - if (result == NULL) { + if (!result) { result = SDL_malloc(sizeof(GLES2_FBOList)); result->w = w; result->h = h; @@ -415,7 +415,7 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin /* Create a program cache entry */ entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry)); - if (entry == NULL) { + if (!entry) { SDL_OutOfMemory(); return NULL; } @@ -476,7 +476,7 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) { data->glDeleteProgram(data->program_cache.tail->id); data->program_cache.tail = data->program_cache.tail->prev; - if (data->program_cache.tail != NULL) { + if (data->program_cache.tail) { SDL_free(data->program_cache.tail->next); data->program_cache.tail->next = NULL; } @@ -493,7 +493,7 @@ static GLuint GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, G const GLchar *shader_src_list[3]; const GLchar *shader_body = GLES2_GetShader(type); - if (shader_body == NULL) { + if (!shader_body) { SDL_SetError("No shader body src"); return 0; } @@ -703,7 +703,7 @@ static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, /* Generate a matching program */ program = GLES2_CacheProgram(data, vertex, fragment); - if (program == NULL) { + if (!program) { goto fault; } @@ -736,7 +736,7 @@ static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, color.b = cmd->data.draw.b; color.a = cmd->data.draw.a; - if (verts == NULL) { + if (!verts) { return -1; } @@ -769,7 +769,7 @@ static int GLES2_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, color.b = cmd->data.draw.b; color.a = cmd->data.draw.a; - if (verts == NULL) { + if (!verts) { return -1; } @@ -827,7 +827,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S if (texture) { SDL_Vertex *verts = (SDL_Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -867,7 +867,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S } else { SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -947,7 +947,7 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co } if ((texture != NULL) != data->drawstate.texturing) { - if (texture == NULL) { + if (!texture) { data->glDisableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD); data->drawstate.texturing = SDL_FALSE; } else { @@ -1270,7 +1270,7 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_RenderCommand *nextcmd = cmd->next; SDL_BlendMode thisblend = cmd->data.draw.blend; - while (nextcmd != NULL) { + while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) { break; /* can't go any further on this draw call, different render command up next. */ @@ -1304,7 +1304,7 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_RenderCommand *nextcmd = cmd->next; size_t count = cmd->data.draw.count; int ret; - while (nextcmd != NULL) { + while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; if (nextcmdtype != thiscmdtype) { break; /* can't go any further on this draw call, different render command up next. */ @@ -1443,7 +1443,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) /* Allocate a texture struct */ data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } data->texture = 0; @@ -1578,7 +1578,7 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff src = (Uint8 *)pixels; if ((size_t)pitch != src_pitch) { blob = (Uint8 *)SDL_malloc(src_pitch * height); - if (blob == NULL) { + if (!blob) { return SDL_OutOfMemory(); } src = blob; @@ -1595,7 +1595,7 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff int i; Uint32 *src32 = (Uint32 *)src; blob2 = (Uint32 *)SDL_malloc(src_pitch * height); - if (blob2 == NULL) { + if (!blob2) { if (blob) { SDL_free(blob); } @@ -1856,7 +1856,7 @@ static int GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) data->drawstate.viewport_dirty = SDL_TRUE; - if (texture == NULL) { + if (!texture) { data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer); } else { texturedata = (GLES2_TextureData *)texture->driverdata; @@ -1922,7 +1922,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, } temp_pixels = SDL_malloc(buflen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } @@ -2088,13 +2088,13 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) /* Create the renderer struct */ renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); goto error; } data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); goto error; diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index c1d748e32b692..febf7031a95a7 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -104,7 +104,7 @@ static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) { GSTEXTURE *ps2_tex = (GSTEXTURE *)SDL_calloc(1, sizeof(GSTEXTURE)); - if (ps2_tex == NULL) { + if (!ps2_tex) { return SDL_OutOfMemory(); } @@ -201,7 +201,7 @@ static int PS2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c gs_rgbaq rgbaq; int i; - if (vertices == NULL) { + if (!vertices) { return -1; } @@ -236,7 +236,7 @@ static int PS2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL GSPRIMUVPOINT *vertices = (GSPRIMUVPOINT *) SDL_AllocateRenderVertices(renderer, count * sizeof(GSPRIMUVPOINT), 4, &cmd->data.draw.first); GSTEXTURE *ps2_tex = (GSTEXTURE *) texture->driverdata; - if (vertices == NULL) { + if (!vertices) { return -1; } @@ -269,7 +269,7 @@ static int PS2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL } else { GSPRIMPOINT *vertices = (GSPRIMPOINT *)SDL_AllocateRenderVertices(renderer, count * sizeof(GSPRIMPOINT), 4, &cmd->data.draw.first); - if (vertices == NULL) { + if (!vertices) { return -1; } @@ -530,11 +530,11 @@ static void PS2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) GSTEXTURE *ps2_texture = (GSTEXTURE *)texture->driverdata; PS2_RenderData *data = (PS2_RenderData *)renderer->driverdata; - if (data == NULL) { + if (!data) { return; } - if (ps2_texture == NULL) { + if (!ps2_texture) { return; } @@ -583,13 +583,13 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_bool dynamicVsync; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { PS2_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 82b0a6b79fa43..1f5a28385a1db 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -281,11 +281,11 @@ static int TextureSwizzle(PSP_TextureData *psp_texture, void *dst) src = (unsigned int *)psp_texture->data; data = dst; - if (data == NULL) { + if (!data) { data = SDL_malloc(psp_texture->size); } - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } @@ -343,11 +343,11 @@ static int TextureUnswizzle(PSP_TextureData *psp_texture, void *dst) data = dst; - if (data == NULL) { + if (!data) { data = SDL_malloc(psp_texture->size); } - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } @@ -391,7 +391,7 @@ static int TextureSpillToSram(PSP_RenderData *data, PSP_TextureData *psp_texture if (psp_texture->swizzled) { // Texture was swizzled in vram, just copy to system memory void *sdata = SDL_malloc(psp_texture->size); - if (sdata == NULL) { + if (!sdata) { return SDL_OutOfMemory(); } @@ -483,7 +483,7 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) PSP_RenderData *data = renderer->driverdata; PSP_TextureData *psp_texture = (PSP_TextureData *)SDL_calloc(1, sizeof(*psp_texture)); - if (psp_texture == NULL) { + if (!psp_texture) { return SDL_OutOfMemory(); } @@ -629,7 +629,7 @@ static int PSP_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c VertV *verts = (VertV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertV), 4, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -655,10 +655,10 @@ static int PSP_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL cmd->data.draw.count = count; size_indices = indices ? size_indices : 0; - if (texture == NULL) { + if (!texture) { VertCV *verts; verts = (VertCV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertCV), 4, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -691,7 +691,7 @@ static int PSP_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL PSP_TextureData *psp_texture = (PSP_TextureData *)texture->driverdata; VertTCV *verts; verts = (VertTCV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertTCV), 4, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -736,7 +736,7 @@ static int PSP_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co VertV *verts = (VertV *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(VertV), 4, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -772,7 +772,7 @@ static int PSP_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Tex if ((MathAbs(u1) - MathAbs(u0)) < 64.0f) { verts = (VertTV *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(VertTV), 4, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -808,7 +808,7 @@ static int PSP_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Tex cmd->data.draw.count = count; verts = (VertTV *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(VertTV), 4, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -859,7 +859,7 @@ static int PSP_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_T float u1 = srcrect->x + srcrect->w; float v1 = srcrect->y + srcrect->h; - if (verts == NULL) { + if (!verts) { return -1; } @@ -1010,7 +1010,7 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state) } if (state->texture != current->texture) { - if (state->texture != NULL) { + if (state->texture) { TextureActivate(state->texture); sceGuEnable(GU_TEXTURE_2D); } else { @@ -1034,7 +1034,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v rendering backends report a reasonable maximum, so the higher level can flush if we appear to be exceeding that. */ gpumem = (Uint8 *)sceGuGetMemory(vertsize); - if (gpumem == NULL) { + if (!gpumem) { return SDL_SetError("Couldn't obtain a %d-byte vertex buffer!", (int)vertsize); } SDL_memcpy(gpumem, vertices, vertsize); @@ -1176,7 +1176,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v case SDL_RENDERCMD_GEOMETRY: { const size_t count = cmd->data.draw.count; - if (cmd->data.draw.texture == NULL) { + if (!cmd->data.draw.texture) { const VertCV *verts = (VertCV *)(gpumem + cmd->data.draw.first); sceGuDisable(GU_TEXTURE_2D); /* In GU_SMOOTH mode */ @@ -1244,11 +1244,11 @@ static void PSP_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) PSP_RenderData *renderdata = (PSP_RenderData *)renderer->driverdata; PSP_TextureData *psp_texture = (PSP_TextureData *)texture->driverdata; - if (renderdata == NULL) { + if (!renderdata) { return; } - if (psp_texture == NULL) { + if (!psp_texture) { return; } @@ -1299,13 +1299,13 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) void *doublebuffer = NULL; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { PSP_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; diff --git a/src/render/software/SDL_blendfillrect.c b/src/render/software/SDL_blendfillrect.c index 72a01d7a6326d..73c456c1f0615 100644 --- a/src/render/software/SDL_blendfillrect.c +++ b/src/render/software/SDL_blendfillrect.c @@ -211,7 +211,7 @@ int SDL_BlendFillRect(SDL_Surface *dst, const SDL_Rect *rect, { SDL_Rect clipped; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_BlendFillRect(): dst"); } @@ -281,7 +281,7 @@ int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL; int status = 0; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_BlendFillRects(): dst"); } @@ -325,7 +325,7 @@ int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, break; } - if (func == NULL) { + if (!func) { if (!dst->format->Amask) { func = SDL_BlendFillRect_RGB; } else { diff --git a/src/render/software/SDL_blendline.c b/src/render/software/SDL_blendline.c index 1bacf9457f77a..83280e44b6782 100644 --- a/src/render/software/SDL_blendline.c +++ b/src/render/software/SDL_blendline.c @@ -798,12 +798,12 @@ int SDL_BlendLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, { BlendLineFunc func; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_BlendLine(): dst"); } func = SDL_CalculateBlendLineFunc(dst->format); - if (func == NULL) { + if (!func) { return SDL_SetError("SDL_BlendLine(): Unsupported surface format"); } @@ -826,12 +826,12 @@ int SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_bool draw_end; BlendLineFunc func; - if (dst == NULL) { + if (!dst) { return SDL_SetError("SDL_BlendLines(): Passed NULL destination surface"); } func = SDL_CalculateBlendLineFunc(dst->format); - if (func == NULL) { + if (!func) { return SDL_SetError("SDL_BlendLines(): Unsupported surface format"); } diff --git a/src/render/software/SDL_blendpoint.c b/src/render/software/SDL_blendpoint.c index 34ed59994ab3e..59b1fd6db3a54 100644 --- a/src/render/software/SDL_blendpoint.c +++ b/src/render/software/SDL_blendpoint.c @@ -209,7 +209,7 @@ static int SDL_BlendPoint_RGBA(SDL_Surface *dst, int x, int y, SDL_BlendMode ble int SDL_BlendPoint(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_BlendPoint(): dst"); } @@ -277,7 +277,7 @@ int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL; int status = 0; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_BlendPoints(): dst"); } @@ -323,7 +323,7 @@ int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count, break; } - if (func == NULL) { + if (!func) { if (!dst->format->Amask) { func = SDL_BlendPoint_RGB; } else { diff --git a/src/render/software/SDL_drawline.c b/src/render/software/SDL_drawline.c index 556805740ad1f..bb7d6a3d403a1 100644 --- a/src/render/software/SDL_drawline.c +++ b/src/render/software/SDL_drawline.c @@ -137,12 +137,12 @@ int SDL_DrawLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color) { DrawLineFunc func; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_DrawLine(): dst"); } func = SDL_CalculateDrawLineFunc(dst->format); - if (func == NULL) { + if (!func) { return SDL_SetError("SDL_DrawLine(): Unsupported surface format"); } @@ -165,12 +165,12 @@ int SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count, SDL_bool draw_end; DrawLineFunc func; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_DrawLines(): dst"); } func = SDL_CalculateDrawLineFunc(dst->format); - if (func == NULL) { + if (!func) { return SDL_SetError("SDL_DrawLines(): Unsupported surface format"); } diff --git a/src/render/software/SDL_drawpoint.c b/src/render/software/SDL_drawpoint.c index 7f3c2a80af54c..a9bd16cb96da8 100644 --- a/src/render/software/SDL_drawpoint.c +++ b/src/render/software/SDL_drawpoint.c @@ -27,7 +27,7 @@ int SDL_DrawPoint(SDL_Surface *dst, int x, int y, Uint32 color) { - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_DrawPoint(): dst"); } @@ -67,7 +67,7 @@ int SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count, int i; int x, y; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_DrawPoints(): dst"); } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 24e15c3e34b81..e6516a43b445d 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -101,7 +101,7 @@ static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) { SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format); - if (surface == NULL) { + if (!surface) { return SDL_SetError("Cannot create surface"); } texture->driverdata = surface; @@ -191,7 +191,7 @@ static int SW_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co SDL_Point *verts = (SDL_Point *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Point), 0, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -210,7 +210,7 @@ static int SW_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, con SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Rect), 0, &cmd->data.draw.first); int i; - if (verts == NULL) { + if (!verts) { return -1; } @@ -231,7 +231,7 @@ static int SW_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Text { SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(SDL_Rect), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -268,7 +268,7 @@ static int SW_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Te { CopyExData *verts = (CopyExData *)SDL_AllocateRenderVertices(renderer, sizeof(CopyExData), 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -324,7 +324,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex int blitRequired = SDL_FALSE; int isOpaque = SDL_FALSE; - if (surface == NULL) { + if (!surface) { return -1; } @@ -344,7 +344,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex * The original source surface must be treated as read-only. */ src_clone = SDL_CreateSurfaceFrom(src->pixels, src->w, src->h, src->pitch, src->format->format); - if (src_clone == NULL) { + if (!src_clone) { if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } @@ -387,7 +387,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex */ if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) { mask = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); - if (mask == NULL) { + if (!mask) { retval = -1; } else { SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD); @@ -400,7 +400,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex if (!retval && (blitRequired || applyModulation)) { SDL_Rect scale_rect = tmp_rect; src_scaled = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); - if (src_scaled == NULL) { + if (!src_scaled) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); @@ -423,15 +423,15 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex src_rotated = SDLgfx_rotateSurface(src_clone, angle, (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, &rect_dest, cangle, sangle, center); - if (src_rotated == NULL) { + if (!src_rotated) { retval = -1; } - if (!retval && mask != NULL) { + if (!retval && mask) { /* The mask needed for the NONE blend mode gets rotated with the same parameters. */ mask_rotated = SDLgfx_rotateSurface(mask, angle, SDL_FALSE, 0, 0, &rect_dest, cangle, sangle, center); - if (mask_rotated == NULL) { + if (!mask_rotated) { retval = -1; } } @@ -487,7 +487,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex src_rotated_rgb = SDL_CreateSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h, src_rotated->pitch, f); - if (src_rotated_rgb == NULL) { + if (!src_rotated_rgb) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD); @@ -499,7 +499,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex } SDL_DestroySurface(mask_rotated); } - if (src_rotated != NULL) { + if (src_rotated) { SDL_DestroySurface(src_rotated); } } @@ -508,10 +508,10 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } - if (mask != NULL) { + if (mask) { SDL_DestroySurface(mask); } - if (src_clone != NULL) { + if (src_clone) { SDL_DestroySurface(src_clone); } return retval; @@ -538,10 +538,10 @@ static int SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_ int i; int count = indices ? num_indices : num_vertices; void *verts; - size_t sz = texture != NULL ? sizeof(GeometryCopyData) : sizeof(GeometryFillData); + size_t sz = texture ? sizeof(GeometryCopyData) : sizeof(GeometryFillData); verts = SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first); - if (verts == NULL) { + if (!verts) { return -1; } @@ -641,9 +641,9 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate) if (drawstate->surface_cliprect_dirty) { const SDL_Rect *viewport = drawstate->viewport; const SDL_Rect *cliprect = drawstate->cliprect; - SDL_assert_release(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */ + SDL_assert_release(viewport); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */ - if (cliprect != NULL) { + if (cliprect) { SDL_Rect clip_rect; clip_rect.x = cliprect->x + viewport->x; clip_rect.y = cliprect->y + viewport->y; @@ -663,7 +663,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SDL_Surface *surface = SW_ActivateRenderer(renderer); SW_DrawStateCache drawstate; - if (surface == NULL) { + if (!surface) { return -1; } @@ -717,7 +717,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SetDrawState(surface, &drawstate); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { int i; for (i = 0; i < count; i++) { verts[i].x += drawstate.viewport->x; @@ -745,7 +745,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SetDrawState(surface, &drawstate); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { int i; for (i = 0; i < count; i++) { verts[i].x += drawstate.viewport->x; @@ -773,7 +773,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SetDrawState(surface, &drawstate); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { int i; for (i = 0; i < count; i++) { verts[i].x += drawstate.viewport->x; @@ -802,7 +802,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo PrepTextureForCopy(cmd); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { dstrect->x += drawstate.viewport->x; dstrect->y += drawstate.viewport->y; } @@ -861,7 +861,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo PrepTextureForCopy(cmd); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { copydata->dstrect.x += drawstate.viewport->x; copydata->dstrect.y += drawstate.viewport->y; } @@ -890,7 +890,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo PrepTextureForCopy(cmd); /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { SDL_Point vp; vp.x = drawstate.viewport->x; vp.y = drawstate.viewport->y; @@ -913,7 +913,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo GeometryFillData *ptr = (GeometryFillData *)verts; /* Apply viewport */ - if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) { + if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) { SDL_Point vp; vp.x = drawstate.viewport->x; vp.y = drawstate.viewport->y; @@ -948,7 +948,7 @@ static int SW_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 src_format; void *src_pixels; - if (surface == NULL) { + if (!surface) { return -1; } @@ -975,7 +975,7 @@ static int SW_RenderPresent(SDL_Renderer *renderer) { SDL_Window *window = renderer->window; - if (window == NULL) { + if (!window) { return -1; } return SDL_UpdateWindowSurface(window); @@ -1098,19 +1098,19 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) SDL_Renderer *renderer; SW_RenderData *data; - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("surface"); return NULL; } renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (SW_RenderData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SW_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; @@ -1155,7 +1155,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) /* Set the vsync hint based on our flags, if it's not already set */ hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); - if (hint == NULL || !*hint) { + if (!hint || !*hint) { no_hint_set = SDL_TRUE; } else { no_hint_set = SDL_FALSE; @@ -1172,7 +1172,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_SetHint(SDL_HINT_RENDER_VSYNC, ""); } - if (surface == NULL) { + if (!surface) { return NULL; } return SW_CreateRendererForSurface(surface); diff --git a/src/render/software/SDL_rotate.c b/src/render/software/SDL_rotate.c index b40330786b567..637653a5b3841 100644 --- a/src/render/software/SDL_rotate.c +++ b/src/render/software/SDL_rotate.c @@ -498,7 +498,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in double sangleinv, cangleinv; /* Sanity check */ - if (src == NULL) { + if (!src) { return NULL; } @@ -522,7 +522,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in if (is8bit) { /* Target surface is 8 bit */ rz_dst = SDL_CreateSurface(rect_dest->w, rect_dest->h + GUARD_ROWS, src->format->format); - if (rz_dst != NULL) { + if (rz_dst) { if (src->format->palette) { for (i = 0; i < src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = src->format->palette->colors[i]; @@ -536,7 +536,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in } /* Check target */ - if (rz_dst == NULL) { + if (!rz_dst) { return NULL; } diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index 576c8d9899239..619925c589fa9 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -219,7 +219,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin SDL_Surface *tmp = NULL; - if (dst == NULL) { + if (!dst) { return -1; } @@ -271,7 +271,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin /* Use an intermediate surface */ tmp = SDL_CreateSurface(dstrect.w, dstrect.h, format); - if (tmp == NULL) { + if (!tmp) { ret = -1; goto end; } @@ -459,7 +459,7 @@ int SDL_SW_BlitTriangle( int has_modulation; - if (src == NULL || dst == NULL) { + if (!src || !dst) { return -1; } diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index de0fa7e189590..289ab06f8f4be 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -167,7 +167,7 @@ void StartDrawing(SDL_Renderer *renderer) // data->colorFragmentProgram = in->color; // data->textureFragmentProgram = in->texture; - if (renderer->target == NULL) { + if (!renderer->target) { sceGxmBeginScene( data->gxm_context, 0, @@ -215,13 +215,13 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) VITA_GXM_RenderData *data; renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); - if (renderer == NULL) { + if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData)); - if (data == NULL) { + if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; @@ -293,7 +293,7 @@ static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData)); - if (vita_texture == NULL) { + if (!vita_texture) { return SDL_OutOfMemory(); } @@ -581,7 +581,7 @@ static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, *pitch = vita_texture->pitch; // make sure that rendering is finished on render target textures - if (vita_texture->tex->gxm_rendertarget != NULL) { + if (vita_texture->tex->gxm_rendertarget) { sceGxmFinish(data->gxm_context); } @@ -731,7 +731,7 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd data, count * sizeof(texture_vertex)); - if (vertices == NULL) { + if (!vertices) { return -1; } @@ -770,7 +770,7 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd data, count * sizeof(color_vertex)); - if (vertices == NULL) { + if (!vertices) { return -1; } @@ -1004,7 +1004,7 @@ static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *c SDL_RenderCommand *nextcmd = cmd->next; size_t count = cmd->data.draw.count; int ret; - while (nextcmd != NULL) { + while (nextcmd) { const SDL_RenderCommandType nextcmdtype = nextcmd->command; if (nextcmdtype != thiscmdtype) { break; /* can't go any further on this draw call, different render command up next. */ @@ -1101,7 +1101,7 @@ static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rec } temp_pixels = SDL_malloc(buflen); - if (temp_pixels == NULL) { + if (!temp_pixels) { return SDL_OutOfMemory(); } @@ -1184,15 +1184,15 @@ static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; - if (data == NULL) { + if (!data) { return; } - if (vita_texture == NULL) { + if (!vita_texture) { return; } - if (vita_texture->tex == NULL) { + if (!vita_texture->tex) { return; } diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/src/render/vitagxm/SDL_render_vita_gxm_memory.c index 0c29c76cfaa8e..159aa5624c05e 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_memory.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.c @@ -66,7 +66,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size) { void *mem; - if (data->texturePool == NULL) { + if (!data->texturePool) { int poolsize; int ret; SceKernelFreeMemorySizeInfo info; @@ -88,7 +88,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size) } data->texturePool = sceClibMspaceCreate(mem, poolsize); - if (data->texturePool == NULL) { + if (!data->texturePool) { return NULL; } ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE); @@ -101,7 +101,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size) void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr) { - if (data->texturePool != NULL) { + if (data->texturePool) { sceClibMspaceFree(data->texturePool, ptr); } } @@ -109,7 +109,7 @@ void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr) void vita_gpu_mem_destroy(VITA_GXM_RenderData *data) { void *mem = NULL; - if (data->texturePool != NULL) { + if (data->texturePool) { sceClibMspaceDestroy(data->texturePool); data->texturePool = NULL; if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0) { diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c index 7a8b59f4110df..bb89fa2c4a219 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c @@ -1001,7 +1001,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2; } - if (texture == NULL) { + if (!texture) { return NULL; } @@ -1015,7 +1015,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig tex_size); /* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */ - if (texture_data == NULL) { + if (!texture_data) { SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n"); texture_data = vita_mem_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, @@ -1028,7 +1028,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig texture->cdram = 1; } - if (texture_data == NULL) { + if (!texture_data) { SDL_free(texture); return NULL; } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 3eeb9e85ab64e..88cda800c54d0 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -329,7 +329,7 @@ SDL_Sensor *SDL_OpenSensor(SDL_SensorID instance_id) /* Create and initialize the sensor */ sensor = (SDL_Sensor *)SDL_calloc(sizeof(*sensor), 1); - if (sensor == NULL) { + if (!sensor) { SDL_OutOfMemory(); SDL_UnlockSensors(); return NULL; diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index f2556b7369b40..db137d5e2fe41 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -138,7 +138,7 @@ static int SDL_ANDROID_SensorInit(void) ASensorList sensors; SDL_sensor_manager = ASensorManager_getInstance(); - if (SDL_sensor_manager == NULL) { + if (!SDL_sensor_manager) { return SDL_SetError("Couldn't create sensor manager"); } @@ -146,7 +146,7 @@ static int SDL_ANDROID_SensorInit(void) sensors_count = ASensorManager_getSensorList(SDL_sensor_manager, &sensors); if (sensors_count > 0) { SDL_sensors = (SDL_AndroidSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors)); - if (SDL_sensors == NULL) { + if (!SDL_sensors) { return SDL_OutOfMemory(); } diff --git a/src/sensor/vita/SDL_vitasensor.c b/src/sensor/vita/SDL_vitasensor.c index 50838a46ff5e7..9495a5e2db297 100644 --- a/src/sensor/vita/SDL_vitasensor.c +++ b/src/sensor/vita/SDL_vitasensor.c @@ -51,7 +51,7 @@ static int SDL_VITA_SensorInit(void) SDL_sensors_count = 2; SDL_sensors = (SDL_VitaSensor *)SDL_calloc(SDL_sensors_count, sizeof(*SDL_sensors)); - if (SDL_sensors == NULL) { + if (!SDL_sensors) { return SDL_OutOfMemory(); } @@ -118,7 +118,7 @@ static int SDL_VITA_SensorOpen(SDL_Sensor *sensor, int device_index) struct sensor_hwdata *hwdata; hwdata = (struct sensor_hwdata *)SDL_calloc(1, sizeof(*hwdata)); - if (hwdata == NULL) { + if (!hwdata) { return SDL_OutOfMemory(); } sensor->hwdata = hwdata; diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index 11fbe3ea3f523..a3bad4f51b6ca 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -62,7 +62,7 @@ static int DisconnectSensor(ISensor *sensor); static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_QueryInterface(ISensorManagerEvents *This, REFIID riid, void **ppvObject) { - if (ppvObject == NULL) { + if (!ppvObject) { return E_INVALIDARG; } @@ -102,7 +102,7 @@ static ISensorManagerEvents sensor_manager_events = { static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_QueryInterface(ISensorEvents *This, REFIID riid, void **ppvObject) { - if (ppvObject == NULL) { + if (!ppvObject) { return E_INVALIDARG; } @@ -295,13 +295,13 @@ static int ConnectSensor(ISensor *sensor) if (bstr_name != NULL) { SysFreeString(bstr_name); } - if (name == NULL) { + if (!name) { return SDL_OutOfMemory(); } SDL_LockSensors(); new_sensors = (SDL_Windows_Sensor *)SDL_realloc(SDL_sensors, (SDL_num_sensors + 1) * sizeof(SDL_Windows_Sensor)); - if (new_sensors == NULL) { + if (!new_sensors) { SDL_UnlockSensors(); SDL_free(name); return SDL_OutOfMemory(); diff --git a/src/stdlib/SDL_getenv.c b/src/stdlib/SDL_getenv.c index 7d84cb128c3b1..b6837e5846b17 100644 --- a/src/stdlib/SDL_getenv.c +++ b/src/stdlib/SDL_getenv.c @@ -40,7 +40,7 @@ static size_t SDL_envmemlen = 0; int SDL_setenv(const char *name, const char *value, int overwrite) { /* Input validation */ - if (name == NULL || *name == '\0' || SDL_strchr(name, '=') != NULL || value == NULL) { + if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { return -1; } @@ -50,7 +50,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite) int SDL_setenv(const char *name, const char *value, int overwrite) { /* Input validation */ - if (name == NULL || *name == '\0' || SDL_strchr(name, '=') != NULL || value == NULL) { + if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { return -1; } @@ -72,7 +72,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite) char *new_variable; /* Input validation */ - if (name == NULL || *name == '\0' || SDL_strchr(name, '=') != NULL || value == NULL) { + if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { return -1; } @@ -87,7 +87,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite) /* This leaks. Sorry. Get a better OS so we don't have to do this. */ len = SDL_strlen(name) + SDL_strlen(value) + 2; new_variable = (char *)SDL_malloc(len); - if (new_variable == NULL) { + if (!new_variable) { return -1; } @@ -104,7 +104,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite) char *new_variable; /* Input validation */ - if (name == NULL || *name == '\0' || SDL_strchr(name, '=') != NULL || value == NULL) { + if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { return -1; } @@ -116,7 +116,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite) /* Allocate memory for the variable */ len = SDL_strlen(name) + SDL_strlen(value) + 2; new_variable = (char *)SDL_malloc(len); - if (new_variable == NULL) { + if (!new_variable) { return -1; } @@ -169,7 +169,7 @@ char *SDL_getenv(const char *name) #endif /* Input validation */ - if (name == NULL || *name == '\0') { + if (!name || *name == '\0') { return NULL; } @@ -181,7 +181,7 @@ char *SDL_getenv(const char *name) size_t bufferlen; /* Input validation */ - if (name == NULL || *name == '\0') { + if (!name || *name == '\0') { return NULL; } @@ -192,7 +192,7 @@ char *SDL_getenv(const char *name) } if (bufferlen > SDL_envmemlen) { char *newmem = (char *)SDL_realloc(SDL_envmem, bufferlen); - if (newmem == NULL) { + if (!newmem) { return NULL; } SDL_envmem = newmem; @@ -208,14 +208,14 @@ char *SDL_getenv(const char *name) char *value; /* Input validation */ - if (name == NULL || *name == '\0') { + if (!name || *name == '\0') { return NULL; } value = (char *)0; if (SDL_env) { len = SDL_strlen(name); - for (i = 0; SDL_env[i] && value == NULL; ++i) { + for (i = 0; SDL_env[i] && !value; ++i) { if ((SDL_strncmp(SDL_env[i], name, len) == 0) && (SDL_env[i][len] == '=')) { value = &SDL_env[i][len + 1]; diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c index 7e8f90db4e28f..f1ea29e63e305 100644 --- a/src/stdlib/SDL_iconv.c +++ b/src/stdlib/SDL_iconv.c @@ -158,28 +158,28 @@ static const char *getlocale(char *buffer, size_t bufsize) char *ptr; lang = SDL_getenv("LC_ALL"); - if (lang == NULL) { + if (!lang) { lang = SDL_getenv("LC_CTYPE"); } - if (lang == NULL) { + if (!lang) { lang = SDL_getenv("LC_MESSAGES"); } - if (lang == NULL) { + if (!lang) { lang = SDL_getenv("LANG"); } - if (lang == NULL || !*lang || SDL_strcmp(lang, "C") == 0) { + if (!lang || !*lang || SDL_strcmp(lang, "C") == 0) { lang = "ASCII"; } /* We need to trim down strings like "en_US.UTF-8@blah" to "UTF-8" */ ptr = SDL_strchr(lang, '.'); - if (ptr != NULL) { + if (ptr) { lang = ptr + 1; } SDL_strlcpy(buffer, lang, bufsize); ptr = SDL_strchr(buffer, '@'); - if (ptr != NULL) { + if (ptr) { *ptr = '\0'; /* chop end of string. */ } @@ -194,10 +194,10 @@ SDL_iconv_t SDL_iconv_open(const char *tocode, const char *fromcode) char fromcode_buffer[64]; char tocode_buffer[64]; - if (fromcode == NULL || !*fromcode) { + if (!fromcode || !*fromcode) { fromcode = getlocale(fromcode_buffer, sizeof(fromcode_buffer)); } - if (tocode == NULL || !*tocode) { + if (!tocode || !*tocode) { tocode = getlocale(tocode_buffer, sizeof(tocode_buffer)); } for (i = 0; i < SDL_arraysize(encodings); ++i) { @@ -236,11 +236,11 @@ size_t SDL_iconv(SDL_iconv_t cd, Uint32 ch = 0; size_t total; - if (inbuf == NULL || !*inbuf) { + if (!inbuf || !*inbuf) { /* Reset the context */ return 0; } - if (outbuf == NULL || !*outbuf || outbytesleft == NULL || !*outbytesleft) { + if (!outbuf || !*outbuf || !outbytesleft || !*outbytesleft) { return SDL_ICONV_E2BIG; } src = *inbuf; @@ -786,10 +786,10 @@ char *SDL_iconv_string(const char *tocode, const char *fromcode, const char *inb size_t outbytesleft; size_t retCode = 0; - if (tocode == NULL || !*tocode) { + if (!tocode || !*tocode) { tocode = "UTF-8"; } - if (fromcode == NULL || !*fromcode) { + if (!fromcode || !*fromcode) { fromcode = "UTF-8"; } cd = SDL_iconv_open(tocode, fromcode); @@ -799,7 +799,7 @@ char *SDL_iconv_string(const char *tocode, const char *fromcode, const char *inb stringsize = inbytesleft; string = (char *)SDL_malloc(stringsize + sizeof(Uint32)); - if (string == NULL) { + if (!string) { SDL_iconv_close(cd); return NULL; } @@ -816,7 +816,7 @@ char *SDL_iconv_string(const char *tocode, const char *fromcode, const char *inb char *oldstring = string; stringsize *= 2; string = (char *)SDL_realloc(string, stringsize + sizeof(Uint32)); - if (string == NULL) { + if (!string) { SDL_free(oldstring); SDL_iconv_close(cd); return NULL; diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 9f434a46cbe03..cdc51ef8db509 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1237,7 +1237,7 @@ int SDL_vsscanf(const char *text, const char *fmt, va_list ap) { int retval = 0; - if (text == NULL || !*text) { + if (!text || !*text) { return -1; } @@ -1641,7 +1641,7 @@ static size_t SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, c size_t length = 0; size_t slen, sz; - if (string == NULL) { + if (!string) { string = "(null)"; } @@ -1701,7 +1701,7 @@ static void SDL_IntPrecisionAdjust(char *num, size_t maxlen, SDL_FormatInfo *inf { /* left-pad num with zeroes. */ size_t sz, pad, have_sign; - if (info == NULL) { + if (!info) { return; } @@ -2189,7 +2189,7 @@ int SDL_vasprintf(char **strp, const char *fmt, va_list ap) *strp = NULL; p = (char *)SDL_malloc(size); - if (p == NULL) { + if (!p) { return -1; } @@ -2215,7 +2215,7 @@ int SDL_vasprintf(char **strp, const char *fmt, va_list ap) size = retval + 1; /* Precisely what is needed */ np = (char *)SDL_realloc(p, size); - if (np == NULL) { + if (!np) { SDL_free(p); return -1; } else { diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 25cf72c23c467..6c98b9db28057 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -102,7 +102,7 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags) } state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state)); - if (state == NULL) { + if (!state) { SDL_OutOfMemory(); return NULL; } @@ -1090,7 +1090,7 @@ static SDL_Surface *SDLTest_LoadIcon(const char *file) /* Load the icon surface */ icon = SDL_LoadBMP(file); - if (icon == NULL) { + if (!icon) { SDL_Log("Couldn't load %s: %s\n", file, SDL_GetError()); return NULL; } @@ -1919,7 +1919,7 @@ static void SDLTest_CopyScreenShot(SDL_Renderer *renderer) }; SDLTest_ClipboardData *clipboard_data; - if (renderer == NULL) { + if (!renderer) { return; } @@ -1927,7 +1927,7 @@ static void SDLTest_CopyScreenShot(SDL_Renderer *renderer) surface = SDL_CreateSurface(viewport.w, viewport.h, SDL_PIXELFORMAT_BGR24); - if (surface == NULL) { + if (!surface) { SDL_Log("Couldn't create surface: %s\n", SDL_GetError()); return; } diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index 1bb5c8b50450c..f0244d57fd13a 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -66,12 +66,12 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, char referenceFilename[FILENAME_SIZE]; /* Validate input surfaces */ - if (surface == NULL) { + if (!surface) { SDLTest_LogError("Cannot compare NULL surface"); return -1; } - if (referenceSurface == NULL) { + if (!referenceSurface) { SDLTest_LogError("Cannot compare NULL reference surface"); return -1; } diff --git a/src/test/SDL_test_crc32.c b/src/test/SDL_test_crc32.c index ef40003458f79..57ebef3734957 100644 --- a/src/test/SDL_test_crc32.c +++ b/src/test/SDL_test_crc32.c @@ -33,7 +33,7 @@ int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext) CrcUint32 c; /* Sanity check context pointer */ - if (crcContext == NULL) { + if (!crcContext) { return -1; } @@ -87,7 +87,7 @@ int SDLTest_Crc32Calc(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint int SDLTest_Crc32CalcStart(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32) { /* Sanity check pointers */ - if (crcContext == NULL) { + if (!crcContext) { *crc32 = 0; return -1; } @@ -105,7 +105,7 @@ int SDLTest_Crc32CalcStart(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32) int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32) { /* Sanity check pointers */ - if (crcContext == NULL) { + if (!crcContext) { *crc32 = 0; return -1; } @@ -125,12 +125,12 @@ int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, C CrcUint8 *p; register CrcUint32 crc; - if (crcContext == NULL) { + if (!crcContext) { *crc32 = 0; return -1; } - if (inBuf == NULL) { + if (!inBuf) { return -1; } @@ -152,7 +152,7 @@ int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, C int SDLTest_Crc32Done(SDLTest_Crc32Context *crcContext) { - if (crcContext == NULL) { + if (!crcContext) { return -1; } diff --git a/src/test/SDL_test_font.c b/src/test/SDL_test_font.c index 41c6adcd80b1c..7f33918980e62 100644 --- a/src/test/SDL_test_font.c +++ b/src/test/SDL_test_font.c @@ -3165,14 +3165,14 @@ int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c) ci = c; /* Search for this renderer's cache */ - for (cache = SDLTest_CharTextureCacheList; cache != NULL; cache = cache->next) { + for (cache = SDLTest_CharTextureCacheList; cache; cache = cache->next) { if (cache->renderer == renderer) { break; } } /* Allocate a new cache for this renderer if needed */ - if (cache == NULL) { + if (!cache) { cache = (struct SDLTest_CharTextureCache *)SDL_calloc(1, sizeof(struct SDLTest_CharTextureCache)); cache->renderer = renderer; cache->next = SDLTest_CharTextureCacheList; @@ -3187,7 +3187,7 @@ int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c) * Redraw character into surface */ character = SDL_CreateSurface(charWidth, charHeight, SDL_PIXELFORMAT_RGBA8888); - if (character == NULL) { + if (!character) { return -1; } @@ -3357,7 +3357,7 @@ SDLTest_TextWindow *SDLTest_TextWindowCreate(float x, float y, float w, float h) { SDLTest_TextWindow *textwin = (SDLTest_TextWindow *)SDL_malloc(sizeof(*textwin)); - if (textwin == NULL) { + if (!textwin) { return NULL; } diff --git a/src/test/SDL_test_fuzzer.c b/src/test/SDL_test_fuzzer.c index 0941c5f33e495..37fe9a591f2fb 100644 --- a/src/test/SDL_test_fuzzer.c +++ b/src/test/SDL_test_fuzzer.c @@ -472,7 +472,7 @@ char *SDLTest_RandomAsciiStringOfSize(int size) } string = (char *)SDL_malloc((size + 1) * sizeof(char)); - if (string == NULL) { + if (!string) { return NULL; } diff --git a/src/test/SDL_test_harness.c b/src/test/SDL_test_harness.c index 7414fe8ebfecb..e17bb12159eca 100644 --- a/src/test/SDL_test_harness.c +++ b/src/test/SDL_test_harness.c @@ -74,7 +74,7 @@ char *SDLTest_GenerateRunSeed(const int length) /* Allocate output buffer */ seed = (char *)SDL_malloc((length + 1) * sizeof(char)); - if (seed == NULL) { + if (!seed) { SDLTest_LogError("SDL_malloc for run seed output buffer failed."); SDL_Error(SDL_ENOMEM); return NULL; @@ -118,17 +118,17 @@ static Uint64 SDLTest_GenerateExecKey(const char *runSeed, const char *suiteName size_t entireStringLength; char *buffer; - if (runSeed == NULL || runSeed[0] == '\0') { + if (!runSeed || runSeed[0] == '\0') { SDLTest_LogError("Invalid runSeed string."); return -1; } - if (suiteName == NULL || suiteName[0] == '\0') { + if (!suiteName || suiteName[0] == '\0') { SDLTest_LogError("Invalid suiteName string."); return -1; } - if (testName == NULL || testName[0] == '\0') { + if (!testName || testName[0] == '\0') { SDLTest_LogError("Invalid testName string."); return -1; } @@ -149,7 +149,7 @@ static Uint64 SDLTest_GenerateExecKey(const char *runSeed, const char *suiteName iterationStringLength = SDL_strlen(iterationString); entireStringLength = runSeedLength + suiteNameLength + testNameLength + iterationStringLength + 1; buffer = (char *)SDL_malloc(entireStringLength); - if (buffer == NULL) { + if (!buffer) { SDLTest_LogError("Failed to allocate buffer for execKey generation."); SDL_Error(SDL_ENOMEM); return 0; @@ -181,7 +181,7 @@ static SDL_TimerID SDLTest_SetTestTimeout(int timeout, void(SDLCALL *callback)(v Uint32 timeoutInMilliseconds; SDL_TimerID timerID; - if (callback == NULL) { + if (!callback) { SDLTest_LogError("Timeout callback can't be NULL"); return -1; } @@ -239,7 +239,7 @@ static int SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, const SDLTest_ int testResult = 0; int fuzzerCount; - if (testSuite == NULL || testCase == NULL || testSuite->name == NULL || testCase->name == NULL) { + if (!testSuite || !testCase || !testSuite->name || !testCase->name) { SDLTest_LogError("Setup failure: testSuite or testCase references NULL"); return TEST_RESULT_SETUP_FAILURE; } @@ -412,9 +412,9 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user } /* Generate run see if we don't have one already */ - if (userRunSeed == NULL || userRunSeed[0] == '\0') { + if (!userRunSeed || userRunSeed[0] == '\0') { char *tmp = SDLTest_GenerateRunSeed(16); - if (tmp == NULL) { + if (!tmp) { SDLTest_LogError("Generating a random seed failed"); return 2; } @@ -455,20 +455,20 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user /* Pre-allocate an array for tracking failed tests (potentially all test cases) */ failedTests = (const SDLTest_TestCaseReference **)SDL_malloc(totalNumberOfTests * sizeof(SDLTest_TestCaseReference *)); - if (failedTests == NULL) { + if (!failedTests) { SDLTest_LogError("Unable to allocate cache for failed tests"); SDL_Error(SDL_ENOMEM); return -1; } /* Initialize filtering */ - if (filter != NULL && filter[0] != '\0') { + if (filter && filter[0] != '\0') { /* Loop over all suites to check if we have a filter match */ suiteCounter = 0; while (testSuites[suiteCounter] && suiteFilter == 0) { testSuite = testSuites[suiteCounter]; suiteCounter++; - if (testSuite->name != NULL && SDL_strcasecmp(filter, testSuite->name) == 0) { + if (testSuite->name && SDL_strcasecmp(filter, testSuite->name) == 0) { /* Matched a suite name */ suiteFilter = 1; suiteFilterName = testSuite->name; @@ -481,7 +481,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user while (testSuite->testCases[testCounter] && testFilter == 0) { testCase = testSuite->testCases[testCounter]; testCounter++; - if (testCase->name != NULL && SDL_strcasecmp(filter, testCase->name) == 0) { + if (testCase->name && SDL_strcasecmp(filter, testCase->name) == 0) { /* Matched a test name */ suiteFilter = 1; suiteFilterName = testSuite->name; @@ -497,7 +497,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user SDLTest_LogError("Filter '%s' did not match any test suite/case.", filter); for (suiteCounter = 0; testSuites[suiteCounter]; ++suiteCounter) { testSuite = testSuites[suiteCounter]; - if (testSuite->name != NULL) { + if (testSuite->name) { SDLTest_Log("Test suite: %s", testSuite->name); } @@ -521,7 +521,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user suiteCounter++; /* Filter suite if flag set and we have a name */ - if (suiteFilter == 1 && suiteFilterName != NULL && testSuite->name != NULL && + if (suiteFilter == 1 && suiteFilterName && testSuite->name && SDL_strcasecmp(suiteFilterName, testSuite->name) != 0) { /* Skip suite */ SDLTest_Log("===== Test Suite %i: '%s' " COLOR_BLUE "skipped" COLOR_END "\n", @@ -550,7 +550,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user testCounter++; /* Filter tests if flag set and we have a name */ - if (testFilter == 1 && testFilterName != NULL && testCase->name != NULL && + if (testFilter == 1 && testFilterName && testCase->name && SDL_strcasecmp(testFilterName, testCase->name) != 0) { /* Skip test */ SDLTest_Log("===== Test Case %i.%i: '%s' " COLOR_BLUE "skipped" COLOR_END "\n", @@ -572,7 +572,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user suiteCounter, testCounter, currentTestName); - if (testCase->description != NULL && testCase->description[0] != '\0') { + if (testCase->description && testCase->description[0] != '\0') { SDLTest_Log("Test Description: '%s'", (testCase->description) ? testCase->description : SDLTEST_INVALID_NAME_FORMAT); } diff --git a/src/test/SDL_test_md5.c b/src/test/SDL_test_md5.c index 9f7448e441040..ce89e4ddaf72f 100644 --- a/src/test/SDL_test_md5.c +++ b/src/test/SDL_test_md5.c @@ -110,7 +110,7 @@ static unsigned char MD5PADDING[64] = { void SDLTest_Md5Init(SDLTest_Md5Context *mdContext) { - if (mdContext == NULL) { + if (!mdContext) { return; } @@ -138,10 +138,10 @@ void SDLTest_Md5Update(SDLTest_Md5Context *mdContext, unsigned char *inBuf, int mdi; unsigned int i, ii; - if (mdContext == NULL) { + if (!mdContext) { return; } - if (inBuf == NULL || inLen < 1) { + if (!inBuf || inLen < 1) { return; } @@ -190,7 +190,7 @@ void SDLTest_Md5Final(SDLTest_Md5Context *mdContext) unsigned int i, ii; unsigned int padLen; - if (mdContext == NULL) { + if (!mdContext) { return; } diff --git a/src/test/SDL_test_memory.c b/src/test/SDL_test_memory.c index 2ca790fb312a5..5ec92cfc5e94b 100644 --- a/src/test/SDL_test_memory.c +++ b/src/test/SDL_test_memory.c @@ -118,7 +118,7 @@ static void SDL_TrackAllocation(void *mem, size_t size) return; } entry = (SDL_tracked_allocation *)SDL_malloc_orig(sizeof(*entry)); - if (entry == NULL) { + if (!entry) { return; } entry->mem = mem; @@ -272,7 +272,7 @@ static void *SDLCALL SDLTest_TrackedRealloc(void *ptr, size_t size) static void SDLCALL SDLTest_TrackedFree(void *ptr) { - if (ptr == NULL) { + if (!ptr) { return; } diff --git a/src/test/SDL_test_random.c b/src/test/SDL_test_random.c index c5633cec6247a..f004ac7a72cee 100644 --- a/src/test/SDL_test_random.c +++ b/src/test/SDL_test_random.c @@ -36,7 +36,7 @@ void SDLTest_RandomInit(SDLTest_RandomContext *rndContext, unsigned int xi, unsigned int ci) { - if (rndContext == NULL) { + if (!rndContext) { return; } @@ -64,7 +64,7 @@ void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext) { int a, b; - if (rndContext == NULL) { + if (!rndContext) { return; } @@ -81,7 +81,7 @@ unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext) { unsigned int xh, xl; - if (rndContext == NULL) { + if (!rndContext) { return -1; } diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 7328316e63134..c03fc41301c27 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -37,7 +37,7 @@ void *SDL_GetTLS(SDL_TLSID id) SDL_TLSData *storage; storage = SDL_SYS_GetTLSData(); - if (storage == NULL || id == 0 || id > storage->limit) { + if (!storage || id == 0 || id > storage->limit) { return NULL; } return storage->array[id - 1].data; @@ -52,13 +52,13 @@ int SDL_SetTLS(SDL_TLSID id, const void *value, void(SDLCALL *destructor)(void * } storage = SDL_SYS_GetTLSData(); - if (storage == NULL || (id > storage->limit)) { + if (!storage || (id > storage->limit)) { unsigned int i, oldlimit, newlimit; oldlimit = storage ? storage->limit : 0; newlimit = (id + TLS_ALLOC_CHUNKSIZE); storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage) + (newlimit - 1) * sizeof(storage->array[0])); - if (storage == NULL) { + if (!storage) { return SDL_OutOfMemory(); } storage->limit = newlimit; @@ -118,14 +118,14 @@ SDL_TLSData *SDL_Generic_GetTLSData(void) SDL_TLSData *storage = NULL; #ifndef SDL_THREADS_DISABLED - if (SDL_generic_TLS_mutex == NULL) { + if (!SDL_generic_TLS_mutex) { static SDL_SpinLock tls_lock; SDL_AtomicLock(&tls_lock); - if (SDL_generic_TLS_mutex == NULL) { + if (!SDL_generic_TLS_mutex) { SDL_Mutex *mutex = SDL_CreateMutex(); SDL_MemoryBarrierRelease(); SDL_generic_TLS_mutex = mutex; - if (SDL_generic_TLS_mutex == NULL) { + if (!SDL_generic_TLS_mutex) { SDL_AtomicUnlock(&tls_lock); return NULL; } @@ -159,10 +159,10 @@ int SDL_Generic_SetTLSData(SDL_TLSData *data) prev = NULL; for (entry = SDL_generic_TLS; entry; entry = entry->next) { if (entry->thread == thread) { - if (data != NULL) { + if (data) { entry->storage = data; } else { - if (prev != NULL) { + if (prev) { prev->next = entry->next; } else { SDL_generic_TLS = entry->next; @@ -173,7 +173,7 @@ int SDL_Generic_SetTLSData(SDL_TLSData *data) } prev = entry; } - if (entry == NULL) { + if (!entry) { entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry)); if (entry) { entry->thread = thread; @@ -184,7 +184,7 @@ int SDL_Generic_SetTLSData(SDL_TLSData *data) } SDL_UnlockMutex(SDL_generic_TLS_mutex); - if (entry == NULL) { + if (!entry) { return SDL_OutOfMemory(); } return 0; @@ -249,7 +249,7 @@ SDL_error *SDL_GetErrBuf(void) if (errbuf == ALLOCATION_IN_PROGRESS) { return SDL_GetStaticErrBuf(); } - if (errbuf == NULL) { + if (!errbuf) { /* Get the original memory functions for this allocation because the lifetime * of the error buffer may span calls to SDL_SetMemoryFunctions() by the app */ @@ -260,7 +260,7 @@ SDL_error *SDL_GetErrBuf(void) /* Mark that we're in the middle of allocating our buffer */ SDL_SetTLS(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL); errbuf = (SDL_error *)realloc_func(NULL, sizeof(*errbuf)); - if (errbuf == NULL) { + if (!errbuf) { SDL_SetTLS(tls_errbuf, NULL, NULL); return SDL_GetStaticErrBuf(); } @@ -328,7 +328,7 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *), /* Allocate memory for the thread info structure */ thread = (SDL_Thread *)SDL_calloc(1, sizeof(*thread)); - if (thread == NULL) { + if (!thread) { SDL_OutOfMemory(); return NULL; } @@ -336,9 +336,9 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *), SDL_AtomicSet(&thread->state, SDL_THREAD_STATE_ALIVE); /* Set up the arguments for the thread */ - if (name != NULL) { + if (name) { thread->name = SDL_strdup(name); - if (thread->name == NULL) { + if (!thread->name) { SDL_OutOfMemory(); SDL_free(thread); return NULL; @@ -381,7 +381,7 @@ DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int(SDLCALL *fn)(void *), size_t stacksize = 0; /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */ - if (stackhint != NULL) { + if (stackhint) { char *endp = NULL; const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10); if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */ @@ -450,7 +450,7 @@ void SDL_WaitThread(SDL_Thread *thread, int *status) void SDL_DetachThread(SDL_Thread *thread) { - if (thread == NULL) { + if (!thread) { return; } diff --git a/src/thread/generic/SDL_syscond.c b/src/thread/generic/SDL_syscond.c index 6535008a7c3fd..e6b1a5d6bd7af 100644 --- a/src/thread/generic/SDL_syscond.c +++ b/src/thread/generic/SDL_syscond.c @@ -92,7 +92,7 @@ void SDL_DestroyCondition_generic(SDL_Condition *_cond) int SDL_SignalCondition_generic(SDL_Condition *_cond) { SDL_cond_generic *cond = (SDL_cond_generic *)_cond; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -116,7 +116,7 @@ int SDL_SignalCondition_generic(SDL_Condition *_cond) int SDL_BroadcastCondition_generic(SDL_Condition *_cond) { SDL_cond_generic *cond = (SDL_cond_generic *)_cond; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -172,7 +172,7 @@ int SDL_WaitConditionTimeoutNS_generic(SDL_Condition *_cond, SDL_Mutex *mutex, S SDL_cond_generic *cond = (SDL_cond_generic *)_cond; int retval; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index 579d028ee3efa..95f4cecd1f0f1 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -87,7 +87,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) { int retval = 0; #ifndef SDL_THREADS_DISABLED - if (mutex != NULL) { + if (mutex) { SDL_threadID this_thread = SDL_ThreadID(); if (mutex->owner == this_thread) { ++mutex->recursive; diff --git a/src/thread/generic/SDL_syssem.c b/src/thread/generic/SDL_syssem.c index 3dae50be4bf32..bf945695fdf96 100644 --- a/src/thread/generic/SDL_syssem.c +++ b/src/thread/generic/SDL_syssem.c @@ -66,7 +66,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_Semaphore *sem; sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); - if (sem == NULL) { + if (!sem) { SDL_OutOfMemory(); return NULL; } @@ -108,7 +108,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) { int retval; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -156,7 +156,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) int SDL_PostSemaphore(SDL_Semaphore *sem) { - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } diff --git a/src/thread/n3ds/SDL_syscond.c b/src/thread/n3ds/SDL_syscond.c index e170ab55e2e7e..5595010fb6ad2 100644 --- a/src/thread/n3ds/SDL_syscond.c +++ b/src/thread/n3ds/SDL_syscond.c @@ -54,7 +54,7 @@ void SDL_DestroyCondition(SDL_Condition *cond) /* Restart one of the threads that are waiting on the condition variable */ int SDL_SignalCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -65,7 +65,7 @@ int SDL_SignalCondition(SDL_Condition *cond) /* Restart all threads that are waiting on the condition variable */ int SDL_BroadcastCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -98,10 +98,10 @@ int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 tim { Result res; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } - if (mutex == NULL) { + if (!mutex) { return SDL_InvalidParamError("mutex"); } diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 47e848582da2c..57d189db5631f 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -53,7 +53,7 @@ void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doe int SDL_TryLockMutex(SDL_Mutex *mutex) { - return (mutex == NULL) ? 0 : RecursiveLock_TryLock(&mutex->lock); + return (!mutex) ? 0 : RecursiveLock_TryLock(&mutex->lock); } void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes diff --git a/src/thread/n3ds/SDL_syssem.c b/src/thread/n3ds/SDL_syssem.c index 261609b27846a..f41d69c348894 100644 --- a/src/thread/n3ds/SDL_syssem.c +++ b/src/thread/n3ds/SDL_syssem.c @@ -43,7 +43,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) } sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); - if (sem == NULL) { + if (!sem) { SDL_OutOfMemory(); return NULL; } @@ -63,7 +63,7 @@ void SDL_DestroySemaphore(SDL_Semaphore *sem) int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) { - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -99,7 +99,7 @@ int WaitOnSemaphoreFor(SDL_Semaphore *sem, Sint64 timeout) Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) { - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -108,7 +108,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) int SDL_PostSemaphore(SDL_Semaphore *sem) { - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } LightSemaphore_Release(&sem->semaphore, 1); diff --git a/src/thread/n3ds/SDL_systhread.c b/src/thread/n3ds/SDL_systhread.c index 348c037230893..17a50bb24e364 100644 --- a/src/thread/n3ds/SDL_systhread.c +++ b/src/thread/n3ds/SDL_systhread.c @@ -66,7 +66,7 @@ int SDL_SYS_CreateThread(SDL_Thread *thread) cpu, false); - if (thread->handle == NULL) { + if (!thread->handle) { return SDL_SetError("Couldn't create thread"); } diff --git a/src/thread/ngage/SDL_syssem.cpp b/src/thread/ngage/SDL_syssem.cpp index e7306e8a16a1b..8c458e947187a 100644 --- a/src/thread/ngage/SDL_syssem.cpp +++ b/src/thread/ngage/SDL_syssem.cpp @@ -90,7 +90,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) void SDL_DestroySemaphore(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { RSemaphore sema; sema.SetHandle(sem->handle); sema.Signal(sema.Count()); @@ -102,7 +102,7 @@ void SDL_DestroySemaphore(SDL_Semaphore *sem) int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) { - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -140,7 +140,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) { - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -149,7 +149,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) int SDL_PostSemaphore(SDL_Semaphore *sem) { - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } sem->count++; diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index 587bf494172b2..04e0b2d831cf7 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -47,7 +47,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) ee_sema_t sema; sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); - if (sem != NULL) { + if (sem) { /* TODO: Figure out the limit on the maximum value. */ sema.init_count = initial_value; sema.max_count = 255; @@ -69,7 +69,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) /* Free the semaphore */ void SDL_DestroySemaphore(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { if (sem->semid > 0) { DeleteSema(sem->semid); sem->semid = 0; @@ -85,7 +85,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) struct timer_alarm_t alarm; InitializeTimerAlarm(&alarm); - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -114,7 +114,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) { ee_sema_t info; - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -130,7 +130,7 @@ int SDL_PostSemaphore(SDL_Semaphore *sem) { int res; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } diff --git a/src/thread/psp/SDL_syscond.c b/src/thread/psp/SDL_syscond.c index a5389444c7110..0dc6f177d3075 100644 --- a/src/thread/psp/SDL_syscond.c +++ b/src/thread/psp/SDL_syscond.c @@ -78,7 +78,7 @@ void SDL_DestroyCondition(SDL_Condition *cond) /* Restart one of the threads that are waiting on the condition variable */ int SDL_SignalCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -101,7 +101,7 @@ int SDL_SignalCondition(SDL_Condition *cond) /* Restart all threads that are waiting on the condition variable */ int SDL_BroadcastCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -156,7 +156,7 @@ int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 tim { int retval; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index f6701bb123e10..82e63e6febaed 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -80,7 +80,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) { int retval = 0; #ifndef SDL_THREADS_DISABLED - if (mutex != NULL) { + if (mutex) { const SceInt32 res = sceKernelTryLockLwMutex(&mutex->lock, 1); if (res == SCE_KERNEL_ERROR_OK) { retval = 0; diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index f54e53ccfe34f..c6b1a3c571282 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -41,7 +41,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_Semaphore *sem; sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); - if (sem != NULL) { + if (sem) { /* TODO: Figure out the limit on the maximum value. */ sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL); if (sem->semid < 0) { @@ -59,7 +59,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) /* Free the semaphore */ void SDL_DestroySemaphore(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { if (sem->semid > 0) { sceKernelDeleteSema(sem->semid); sem->semid = 0; @@ -79,7 +79,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) SceUInt *pTimeout; int res; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -114,7 +114,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) { SceKernelSemaInfo info; - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -130,7 +130,7 @@ int SDL_PostSemaphore(SDL_Semaphore *sem) { int res; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } diff --git a/src/thread/pthread/SDL_syscond.c b/src/thread/pthread/SDL_syscond.c index f41602494b6c3..026f0a1a10ecb 100644 --- a/src/thread/pthread/SDL_syscond.c +++ b/src/thread/pthread/SDL_syscond.c @@ -63,7 +63,7 @@ int SDL_SignalCondition(SDL_Condition *cond) { int retval; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -79,7 +79,7 @@ int SDL_BroadcastCondition(SDL_Condition *cond) { int retval; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -98,7 +98,7 @@ int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 tim #endif struct timespec abstime; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index 4b921e1a48171..30f796cd7fbc8 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -88,7 +88,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) { int retval = 0; - if (mutex != NULL) { + if (mutex) { #ifdef FAKE_RECURSIVE_MUTEX pthread_t this_thread = pthread_self(); if (mutex->owner == this_thread) { diff --git a/src/thread/pthread/SDL_syssem.c b/src/thread/pthread/SDL_syssem.c index b1b38fa53b353..d2ecb57d9ebeb 100644 --- a/src/thread/pthread/SDL_syssem.c +++ b/src/thread/pthread/SDL_syssem.c @@ -42,7 +42,7 @@ struct SDL_Semaphore SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) { SDL_Semaphore *sem = (SDL_Semaphore *)SDL_malloc(sizeof(SDL_Semaphore)); - if (sem != NULL) { + if (sem) { if (sem_init(&sem->sem, 0, initial_value) < 0) { SDL_SetError("sem_init() failed"); SDL_free(sem); @@ -56,7 +56,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) void SDL_DestroySemaphore(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { sem_destroy(&sem->sem); SDL_free(sem); } @@ -74,7 +74,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) Uint64 end; #endif - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -152,7 +152,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) { int ret = 0; - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -168,7 +168,7 @@ int SDL_PostSemaphore(SDL_Semaphore *sem) { int retval; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index b4b6193a54bfa..c1e7d062462a6 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -118,10 +118,10 @@ void SDL_SYS_SetupThread(const char *name) int i; sigset_t mask; - if (name != NULL) { + if (name) { #if (defined(__MACOS__) || defined(__IOS__) || defined(__LINUX__)) && defined(HAVE_DLOPEN) SDL_assert(checked_setname); - if (ppthread_setname_np != NULL) { + if (ppthread_setname_np) { #if defined(__MACOS__) || defined(__IOS__) ppthread_setname_np(name); #elif defined(__LINUX__) diff --git a/src/thread/stdcpp/SDL_syscond.cpp b/src/thread/stdcpp/SDL_syscond.cpp index 90c8a88a4b93a..72536d601c8a6 100644 --- a/src/thread/stdcpp/SDL_syscond.cpp +++ b/src/thread/stdcpp/SDL_syscond.cpp @@ -56,7 +56,7 @@ SDL_CreateCondition(void) extern "C" void SDL_DestroyCondition(SDL_Condition *cond) { - if (cond != NULL) { + if (cond) { delete cond; } } @@ -65,7 +65,7 @@ SDL_DestroyCondition(SDL_Condition *cond) extern "C" int SDL_SignalCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -77,7 +77,7 @@ SDL_SignalCondition(SDL_Condition *cond) extern "C" int SDL_BroadcastCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } diff --git a/src/thread/stdcpp/SDL_sysmutex.cpp b/src/thread/stdcpp/SDL_sysmutex.cpp index 3619c4139817c..1d33701b2fb93 100644 --- a/src/thread/stdcpp/SDL_sysmutex.cpp +++ b/src/thread/stdcpp/SDL_sysmutex.cpp @@ -45,7 +45,7 @@ extern "C" SDL_Mutex * SDL_CreateMutex(void) extern "C" void SDL_DestroyMutex(SDL_Mutex *mutex) { - if (mutex != NULL) { + if (mutex) { delete mutex; } } @@ -64,7 +64,7 @@ extern "C" void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS / extern "C" int SDL_TryLockMutex(SDL_Mutex *mutex) { - return ((mutex == NULL) || mutex->cpp_mutex.try_lock()) ? 0 : SDL_MUTEX_TIMEDOUT; + return ((!mutex) || mutex->cpp_mutex.try_lock()) ? 0 : SDL_MUTEX_TIMEDOUT; } /* Unlock the mutex */ diff --git a/src/thread/stdcpp/SDL_sysrwlock.cpp b/src/thread/stdcpp/SDL_sysrwlock.cpp index e85f879a9c4ca..7e6742c4e947a 100644 --- a/src/thread/stdcpp/SDL_sysrwlock.cpp +++ b/src/thread/stdcpp/SDL_sysrwlock.cpp @@ -46,7 +46,7 @@ extern "C" SDL_RWLock *SDL_CreateRWLock(void) extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock) { - if (rwlock != NULL) { + if (rwlock) { delete rwlock; } } diff --git a/src/thread/vita/SDL_syscond.c b/src/thread/vita/SDL_syscond.c index dd32da5d0b9e9..2218f755eae21 100644 --- a/src/thread/vita/SDL_syscond.c +++ b/src/thread/vita/SDL_syscond.c @@ -43,7 +43,7 @@ SDL_Condition *SDL_CreateCondition(void) SDL_Condition *cond; cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition)); - if (cond != NULL) { + if (cond) { cond->lock = SDL_CreateMutex(); cond->wait_sem = SDL_CreateSemaphore(0); cond->wait_done = SDL_CreateSemaphore(0); @@ -61,7 +61,7 @@ SDL_Condition *SDL_CreateCondition(void) /* Destroy a condition variable */ void SDL_DestroyCondition(SDL_Condition *cond) { - if (cond != NULL) { + if (cond) { if (cond->wait_sem) { SDL_DestroySemaphore(cond->wait_sem); } @@ -78,7 +78,7 @@ void SDL_DestroyCondition(SDL_Condition *cond) /* Restart one of the threads that are waiting on the condition variable */ int SDL_SignalCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -101,7 +101,7 @@ int SDL_SignalCondition(SDL_Condition *cond) /* Restart all threads that are waiting on the condition variable */ int SDL_BroadcastCondition(SDL_Condition *cond) { - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -156,7 +156,7 @@ int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 tim { int retval; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index 1bc27780e8413..e63e77fa59f96 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -35,7 +35,7 @@ struct SDL_Mutex SDL_Mutex *SDL_CreateMutex(void) { SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); - if (mutex != NULL) { + if (mutex) { const SceInt32 res = sceKernelCreateLwMutex( &mutex->lock, "SDL mutex", @@ -56,7 +56,7 @@ SDL_Mutex *SDL_CreateMutex(void) void SDL_DestroyMutex(SDL_Mutex *mutex) { - if (mutex != NULL) { + if (mutex) { sceKernelDeleteLwMutex(&mutex->lock); SDL_free(mutex); } @@ -79,7 +79,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) #else SceInt32 res = 0; - if (mutex == NULL) { + if (!mutex) { return 0; } diff --git a/src/thread/vita/SDL_syssem.c b/src/thread/vita/SDL_syssem.c index 105b18d247ba3..f43cbaba5892f 100644 --- a/src/thread/vita/SDL_syssem.c +++ b/src/thread/vita/SDL_syssem.c @@ -42,7 +42,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_Semaphore *sem; sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); - if (sem != NULL) { + if (sem) { /* TODO: Figure out the limit on the maximum value. */ sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL); if (sem->semid < 0) { @@ -60,7 +60,7 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) /* Free the semaphore */ void SDL_DestroySemaphore(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { if (sem->semid > 0) { sceKernelDeleteSema(sem->semid); sem->semid = 0; @@ -80,7 +80,7 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) SceUInt *pTimeout; int res; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -116,7 +116,7 @@ Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem) SceKernelSemaInfo info; info.size = sizeof(info); - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -132,7 +132,7 @@ int SDL_PostSemaphore(SDL_Semaphore *sem) { int res; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } diff --git a/src/thread/windows/SDL_syscond_cv.c b/src/thread/windows/SDL_syscond_cv.c index b0142d8b92e52..91a5e23bda9cb 100644 --- a/src/thread/windows/SDL_syscond_cv.c +++ b/src/thread/windows/SDL_syscond_cv.c @@ -84,7 +84,7 @@ static SDL_Condition *SDL_CreateCondition_cv(void) /* Relies on CONDITION_VARIABLE_INIT == 0. */ cond = (SDL_cond_cv *)SDL_calloc(1, sizeof(*cond)); - if (cond == NULL) { + if (!cond) { SDL_OutOfMemory(); } @@ -93,7 +93,7 @@ static SDL_Condition *SDL_CreateCondition_cv(void) static void SDL_DestroyCondition_cv(SDL_Condition *cond) { - if (cond != NULL) { + if (cond) { /* There are no kernel allocated resources */ SDL_free(cond); } @@ -102,7 +102,7 @@ static void SDL_DestroyCondition_cv(SDL_Condition *cond) static int SDL_SignalCondition_cv(SDL_Condition *_cond) { SDL_cond_cv *cond = (SDL_cond_cv *)_cond; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -114,7 +114,7 @@ static int SDL_SignalCondition_cv(SDL_Condition *_cond) static int SDL_BroadcastCondition_cv(SDL_Condition *_cond) { SDL_cond_cv *cond = (SDL_cond_cv *)_cond; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } @@ -129,10 +129,10 @@ static int SDL_WaitConditionTimeoutNS_cv(SDL_Condition *_cond, SDL_Mutex *_mutex DWORD timeout; int ret; - if (cond == NULL) { + if (!cond) { return SDL_InvalidParamError("cond"); } - if (_mutex == NULL) { + if (!_mutex) { return SDL_InvalidParamError("mutex"); } @@ -208,13 +208,13 @@ static const SDL_cond_impl_t SDL_cond_impl_generic = { SDL_Condition *SDL_CreateCondition(void) { - if (SDL_cond_impl_active.Create == NULL) { + if (!SDL_cond_impl_active.Create) { const SDL_cond_impl_t *impl = NULL; if (SDL_mutex_impl_active.Type == SDL_MUTEX_INVALID) { /* The mutex implementation isn't decided yet, trigger it */ SDL_Mutex *mutex = SDL_CreateMutex(); - if (mutex == NULL) { + if (!mutex) { return NULL; } SDL_DestroyMutex(mutex); diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index d70aa1be16e6c..1d62e7e8d65fd 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -61,7 +61,7 @@ static SDL_Mutex *SDL_CreateMutex_srw(void) SDL_mutex_srw *mutex; mutex = (SDL_mutex_srw *)SDL_calloc(1, sizeof(*mutex)); - if (mutex == NULL) { + if (!mutex) { SDL_OutOfMemory(); } @@ -145,7 +145,7 @@ static const SDL_mutex_impl_t SDL_mutex_impl_srw = { static SDL_Mutex *SDL_CreateMutex_cs(void) { SDL_mutex_cs *mutex = (SDL_mutex_cs *)SDL_malloc(sizeof(*mutex)); - if (mutex != NULL) { + if (mutex) { // Initialize // On SMP systems, a non-zero spin count generally helps performance #ifdef __WINRT__ @@ -199,7 +199,7 @@ static const SDL_mutex_impl_t SDL_mutex_impl_cs = { SDL_Mutex *SDL_CreateMutex(void) { - if (SDL_mutex_impl_active.Create == NULL) { + if (!SDL_mutex_impl_active.Create) { // Default to fallback implementation const SDL_mutex_impl_t *impl = &SDL_mutex_impl_cs; @@ -239,7 +239,7 @@ void SDL_DestroyMutex(SDL_Mutex *mutex) void SDL_LockMutex(SDL_Mutex *mutex) { - if (mutex != NULL) { + if (mutex) { SDL_mutex_impl_active.Lock(mutex); } } @@ -251,7 +251,7 @@ int SDL_TryLockMutex(SDL_Mutex *mutex) void SDL_UnlockMutex(SDL_Mutex *mutex) { - if (mutex != NULL) { + if (mutex) { SDL_mutex_impl_active.Unlock(mutex); } } diff --git a/src/thread/windows/SDL_sysrwlock_srw.c b/src/thread/windows/SDL_sysrwlock_srw.c index c22eecae8e358..5b5953a38985d 100644 --- a/src/thread/windows/SDL_sysrwlock_srw.c +++ b/src/thread/windows/SDL_sysrwlock_srw.c @@ -88,7 +88,7 @@ typedef struct SDL_rwlock_srw static SDL_RWLock *SDL_CreateRWLock_srw(void) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *)SDL_calloc(1, sizeof(*rwlock)); - if (rwlock == NULL) { + if (!rwlock) { SDL_OutOfMemory(); } pInitializeSRWLock(&rwlock->srw); @@ -125,7 +125,7 @@ static int SDL_TryLockRWLockForReading_srw(SDL_RWLock *_rwlock) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; int retval = 0; - if (rwlock != NULL) { + if (rwlock) { retval = pTryAcquireSRWLockShared(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT; } return retval; @@ -135,7 +135,7 @@ static int SDL_TryLockRWLockForWriting_srw(SDL_RWLock *_rwlock) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; int retval = 0; - if (rwlock != NULL) { + if (rwlock) { retval = pTryAcquireSRWLockExclusive(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT; } return retval; @@ -182,7 +182,7 @@ static const SDL_rwlock_impl_t SDL_rwlock_impl_generic = { SDL_RWLock *SDL_CreateRWLock(void) { - if (SDL_rwlock_impl_active.Create == NULL) { + if (!SDL_rwlock_impl_active.Create) { const SDL_rwlock_impl_t *impl; #ifdef __WINRT__ diff --git a/src/thread/windows/SDL_syssem.c b/src/thread/windows/SDL_syssem.c index b1097e315eea2..493dd3178657b 100644 --- a/src/thread/windows/SDL_syssem.c +++ b/src/thread/windows/SDL_syssem.c @@ -83,7 +83,7 @@ static SDL_Semaphore *SDL_CreateSemaphore_atom(Uint32 initial_value) SDL_sem_atom *sem; sem = (SDL_sem_atom *)SDL_malloc(sizeof(*sem)); - if (sem != NULL) { + if (sem) { sem->count = initial_value; } else { SDL_OutOfMemory(); @@ -93,7 +93,7 @@ static SDL_Semaphore *SDL_CreateSemaphore_atom(Uint32 initial_value) static void SDL_DestroySemaphore_atom(SDL_Semaphore *sem) { - if (sem != NULL) { + if (sem) { SDL_free(sem); } } @@ -106,7 +106,7 @@ static int SDL_WaitSemaphoreTimeoutNS_atom(SDL_Semaphore *_sem, Sint64 timeoutNS Uint64 deadline; DWORD timeout_eff; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -176,7 +176,7 @@ static Uint32 SDL_GetSemaphoreValue_atom(SDL_Semaphore *_sem) { SDL_sem_atom *sem = (SDL_sem_atom *)_sem; - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -188,7 +188,7 @@ static int SDL_PostSemaphore_atom(SDL_Semaphore *_sem) { SDL_sem_atom *sem = (SDL_sem_atom *)_sem; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -224,7 +224,7 @@ static SDL_Semaphore *SDL_CreateSemaphore_kern(Uint32 initial_value) /* Allocate sem memory */ sem = (SDL_sem_kern *)SDL_malloc(sizeof(*sem)); - if (sem != NULL) { + if (sem) { /* Create the semaphore, with max value 32K */ #ifdef __WINRT__ sem->id = CreateSemaphoreEx(NULL, initial_value, 32 * 1024, NULL, 0, SEMAPHORE_ALL_ACCESS); @@ -247,7 +247,7 @@ static SDL_Semaphore *SDL_CreateSemaphore_kern(Uint32 initial_value) static void SDL_DestroySemaphore_kern(SDL_Semaphore *_sem) { SDL_sem_kern *sem = (SDL_sem_kern *)_sem; - if (sem != NULL) { + if (sem) { if (sem->id) { CloseHandle(sem->id); sem->id = 0; @@ -262,7 +262,7 @@ static int SDL_WaitSemaphoreTimeoutNS_kern(SDL_Semaphore *_sem, Sint64 timeoutNS int retval; DWORD dwMilliseconds; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } @@ -290,7 +290,7 @@ static int SDL_WaitSemaphoreTimeoutNS_kern(SDL_Semaphore *_sem, Sint64 timeoutNS static Uint32 SDL_GetSemaphoreValue_kern(SDL_Semaphore *_sem) { SDL_sem_kern *sem = (SDL_sem_kern *)_sem; - if (sem == NULL) { + if (!sem) { SDL_InvalidParamError("sem"); return 0; } @@ -300,7 +300,7 @@ static Uint32 SDL_GetSemaphoreValue_kern(SDL_Semaphore *_sem) static int SDL_PostSemaphore_kern(SDL_Semaphore *_sem) { SDL_sem_kern *sem = (SDL_sem_kern *)_sem; - if (sem == NULL) { + if (!sem) { return SDL_InvalidParamError("sem"); } /* Increase the counter in the first place, because @@ -330,7 +330,7 @@ static const SDL_sem_impl_t SDL_sem_impl_kern = { SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) { - if (SDL_sem_impl_active.Create == NULL) { + if (!SDL_sem_impl_active.Create) { /* Default to fallback implementation */ const SDL_sem_impl_t *impl = &SDL_sem_impl_kern; diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c index 8755f67c38331..0076656506ce6 100644 --- a/src/thread/windows/SDL_systhread.c +++ b/src/thread/windows/SDL_systhread.c @@ -47,7 +47,7 @@ static DWORD RunThread(void *data) SDL_Thread *thread = (SDL_Thread *)data; pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)thread->endfunc; SDL_RunThread(thread); - if (pfnEndThread != NULL) { + if (pfnEndThread) { pfnEndThread(0); } return 0; @@ -96,7 +96,7 @@ int SDL_SYS_CreateThread(SDL_Thread *thread) RunThreadViaCreateThread, thread, flags, &threadid); } - if (thread->handle == NULL) { + if (!thread->handle) { return SDL_SetError("Not enough resources to create thread"); } return 0; @@ -116,7 +116,7 @@ typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR); void SDL_SYS_SetupThread(const char *name) { - if (name != NULL) { + if (name) { #ifndef __WINRT__ /* !!! FIXME: There's no LoadLibrary() in WinRT; don't know if SetThreadDescription is available there at all at the moment. */ static pfnSetThreadDescription pSetThreadDescription = NULL; static HMODULE kernel32 = NULL; @@ -128,7 +128,7 @@ void SDL_SYS_SetupThread(const char *name) } } - if (pSetThreadDescription != NULL) { + if (pSetThreadDescription) { WCHAR *strw = WIN_UTF8ToStringW(name); if (strw) { pSetThreadDescription(GetCurrentThread(), strw); diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index 67296bbb8440b..a5ca6757972bc 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -171,7 +171,7 @@ static int SDLCALL SDL_TimerThread(void *_data) current->scheduled = tick + interval; SDL_AddTimerInternal(data, current); } else { - if (freelist_head == NULL) { + if (!freelist_head) { freelist_head = current; } if (freelist_tail) { @@ -296,7 +296,7 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para SDL_RemoveTimer(timer->timerID); } else { timer = (SDL_Timer *)SDL_malloc(sizeof(*timer)); - if (timer == NULL) { + if (!timer) { SDL_OutOfMemory(); return 0; } @@ -309,7 +309,7 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para SDL_AtomicSet(&timer->canceled, 0); entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); - if (entry == NULL) { + if (!entry) { SDL_free(timer); SDL_OutOfMemory(); return 0; @@ -422,7 +422,7 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para SDL_TimerMap *entry; entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); - if (entry == NULL) { + if (!entry) { SDL_OutOfMemory(); return 0; } diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index 5c478a58ddff3..a9e82465c351d 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -1023,7 +1023,7 @@ static int RLEAlphaSurface(SDL_Surface *surface) SDL_PixelFormat *, SDL_PixelFormat *); dest = surface->map->dst; - if (dest == NULL) { + if (!dest) { return -1; } df = dest->format; @@ -1080,7 +1080,7 @@ static int RLEAlphaSurface(SDL_Surface *surface) maxsize += sizeof(RLEDestFormat); rlebuf = (Uint8 *)SDL_malloc(maxsize); - if (rlebuf == NULL) { + if (!rlebuf) { return SDL_OutOfMemory(); } { @@ -1226,7 +1226,7 @@ static int RLEAlphaSurface(SDL_Surface *surface) /* reallocate the buffer to release unused memory */ { Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); - if (p == NULL) { + if (!p) { p = rlebuf; } surface->map->data = p; @@ -1299,7 +1299,7 @@ static int RLEColorkeySurface(SDL_Surface *surface) } rlebuf = (Uint8 *)SDL_malloc(maxsize); - if (rlebuf == NULL) { + if (!rlebuf) { return SDL_OutOfMemory(); } @@ -1394,7 +1394,7 @@ static int RLEColorkeySurface(SDL_Surface *surface) { /* If SDL_realloc returns NULL, the original block is left intact */ Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); - if (p == NULL) { + if (!p) { p = rlebuf; } surface->map->data = p; @@ -1496,7 +1496,7 @@ static SDL_bool UnRLEAlpha(SDL_Surface *surface) } surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size); - if (surface->pixels == NULL) { + if (!surface->pixels) { return SDL_FALSE; } surface->flags |= SDL_SIMD_ALIGNED; @@ -1568,7 +1568,7 @@ void SDL_UnRLESurface(SDL_Surface *surface, int recode) return; } surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size); - if (surface->pixels == NULL) { + if (!surface->pixels) { /* Oh crap... */ surface->flags |= SDL_RLEACCEL; return; diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index cb3f25a169242..44807bcb9f14b 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -247,7 +247,7 @@ int SDL_CalculateBlit(SDL_Surface *surface) } #endif #if SDL_HAVE_BLIT_AUTO - if (blit == NULL) { + if (!blit) { Uint32 src_format = surface->format->format; Uint32 dst_format = dst->format->format; @@ -258,7 +258,7 @@ int SDL_CalculateBlit(SDL_Surface *surface) #endif #ifndef TEST_SLOW_BLIT - if (blit == NULL) + if (!blit) #endif { Uint32 src_format = surface->format->format; @@ -274,7 +274,7 @@ int SDL_CalculateBlit(SDL_Surface *surface) map->data = blit; /* Make sure we have a blit function */ - if (blit == NULL) { + if (!blit) { SDL_InvalidateMap(map); return SDL_SetError("Blit combination not supported"); } diff --git a/src/video/SDL_blit_A.c b/src/video/SDL_blit_A.c index ef0b8de4e3143..0e61c8a356e81 100644 --- a/src/video/SDL_blit_A.c +++ b/src/video/SDL_blit_A.c @@ -1326,7 +1326,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface) /* Per-pixel alpha blits */ switch (df->BytesPerPixel) { case 1: - if (df->palette != NULL) { + if (df->palette) { return BlitNto1PixelAlpha; } else { /* RGB332 has no palette ! */ @@ -1397,7 +1397,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface) /* Per-surface alpha blits */ switch (df->BytesPerPixel) { case 1: - if (df->palette != NULL) { + if (df->palette) { return BlitNto1SurfaceAlpha; } else { /* RGB332 has no palette ! */ @@ -1452,7 +1452,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface) if (sf->Amask == 0) { if (df->BytesPerPixel == 1) { - if (df->palette != NULL) { + if (df->palette) { return BlitNto1SurfaceAlphaKey; } else { /* RGB332 has no palette ! */ diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index 4c1f8c3e3997c..541e6edb11e14 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -971,7 +971,7 @@ static void Blit_XRGB8888_index8(SDL_BlitInfo *info) dstskip = info->dst_skip; map = info->table; - if (map == NULL) { + if (!map) { while (height--) { #ifdef USE_DUFFS_LOOP /* *INDENT-OFF* */ /* clang-format off */ @@ -1085,7 +1085,7 @@ static void Blit_RGB101010_index8(SDL_BlitInfo *info) dstskip = info->dst_skip; map = info->table; - if (map == NULL) { + if (!map) { while (height--) { #ifdef USE_DUFFS_LOOP /* *INDENT-OFF* */ /* clang-format off */ @@ -2109,7 +2109,7 @@ static void BlitNto1(SDL_BlitInfo *info) srcfmt = info->src_fmt; srcbpp = srcfmt->BytesPerPixel; - if (map == NULL) { + if (!map) { while (height--) { #ifdef USE_DUFFS_LOOP /* *INDENT-OFF* */ /* clang-format off */ @@ -2505,7 +2505,7 @@ static void BlitNto1Key(SDL_BlitInfo *info) srcbpp = srcfmt->BytesPerPixel; ckey &= rgbmask; - if (palmap == NULL) { + if (!palmap) { while (height--) { /* *INDENT-OFF* */ /* clang-format off */ DUFFS_LOOP( diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index 998bee1f30875..c9fdcdbaf5185 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -235,7 +235,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) /* Make sure we are passed a valid data source */ surface = NULL; - if (src == NULL) { + if (!src) { SDL_InvalidParamError("src"); goto done; } @@ -442,7 +442,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) format = SDL_GetPixelFormatEnumForMasks(biBitCount, Rmask, Gmask, Bmask, Amask); surface = SDL_CreateSurface(biWidth, biHeight, format); - if (surface == NULL) { + if (!surface) { goto done; } } @@ -695,7 +695,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst) } #endif /* SAVE_32BIT_BMP */ - if (surface->format->palette != NULL && !save32bit) { + if (surface->format->palette && !save32bit) { if (surface->format->BitsPerPixel == 8) { intermediate_surface = surface; } else { @@ -726,7 +726,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst) pixel_format = SDL_PIXELFORMAT_BGR24; } intermediate_surface = SDL_ConvertSurfaceFormat(surface, pixel_format); - if (intermediate_surface == NULL) { + if (!intermediate_surface) { SDL_SetError("Couldn't convert image to %d bpp", (int)SDL_BITSPERPIXEL(pixel_format)); goto done; diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c index a2396bd4fe099..df116314b54cd 100644 --- a/src/video/SDL_clipboard.c +++ b/src/video/SDL_clipboard.c @@ -58,7 +58,7 @@ int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanu SDL_VideoDevice *_this = SDL_GetVideoDevice(); size_t i; - if (_this == NULL) { + if (!_this) { return SDL_SetError("Video subsystem must be initialized to set clipboard text"); } @@ -168,7 +168,7 @@ void *SDL_GetClipboardData(const char *mime_type, size_t *size) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to get clipboard data"); return NULL; } @@ -215,7 +215,7 @@ SDL_bool SDL_HasClipboardData(const char *mime_type) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to check clipboard data"); return SDL_FALSE; } @@ -272,7 +272,7 @@ int SDL_SetClipboardText(const char *text) size_t num_mime_types; const char **text_mime_types; - if (_this == NULL) { + if (!_this) { return SDL_SetError("Video subsystem must be initialized to set clipboard text"); } @@ -293,7 +293,7 @@ char *SDL_GetClipboardText(void) size_t length; char *text = NULL; - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to get clipboard text"); return SDL_strdup(""); } @@ -318,7 +318,7 @@ SDL_bool SDL_HasClipboardText(void) size_t i, num_mime_types; const char **text_mime_types; - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to check clipboard text"); return SDL_FALSE; } @@ -338,11 +338,11 @@ int SDL_SetPrimarySelectionText(const char *text) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (_this == NULL) { + if (!_this) { return SDL_SetError("Video subsystem must be initialized to set primary selection text"); } - if (text == NULL) { + if (!text) { text = ""; } if (_this->SetPrimarySelectionText) { @@ -362,7 +362,7 @@ char *SDL_GetPrimarySelectionText(void) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to get primary selection text"); return SDL_strdup(""); } @@ -371,7 +371,7 @@ char *SDL_GetPrimarySelectionText(void) return _this->GetPrimarySelectionText(_this); } else { const char *text = _this->primary_selection_text; - if (text == NULL) { + if (!text) { text = ""; } return SDL_strdup(text); @@ -382,7 +382,7 @@ SDL_bool SDL_HasPrimarySelectionText(void) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (_this == NULL) { + if (!_this) { SDL_SetError("Video subsystem must be initialized to check primary selection text"); return SDL_FALSE; } diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 19b8042866c83..a2d72114bf64e 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -184,7 +184,7 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type const char *ext_start; /* Invalid extensions can be rejected early */ - if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) { + if (!ext || *ext == 0 || SDL_strchr(ext, ' ') != NULL) { /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */ return SDL_FALSE; } @@ -197,7 +197,7 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type * 1 If set, the client extension is masked and not present to SDL. */ ext_override = SDL_getenv(ext); - if (ext_override != NULL) { + if (ext_override) { int disable_ext = SDL_atoi(ext_override); if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) { return SDL_FALSE; @@ -223,12 +223,12 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type return SDL_FALSE; } - if (egl_extstr != NULL) { + if (egl_extstr) { ext_start = egl_extstr; while (*ext_start) { ext_start = SDL_strstr(ext_start, ext); - if (ext_start == NULL) { + if (!ext_start) { return SDL_FALSE; } /* Check if the match is not just a substring of one of the extensions */ @@ -251,24 +251,24 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type SDL_FunctionPointer SDL_EGL_GetProcAddressInternal(SDL_VideoDevice *_this, const char *proc) { SDL_FunctionPointer retval = NULL; - if (_this->egl_data != NULL) { + if (_this->egl_data) { const Uint32 eglver = (((Uint32)_this->egl_data->egl_version_major) << 16) | ((Uint32)_this->egl_data->egl_version_minor); const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32)1) << 16) | 5); /* EGL 1.5 can use eglGetProcAddress() for any symbol. 1.4 and earlier can't use it for core entry points. */ - if (retval == NULL && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) { + if (!retval && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) { retval = _this->egl_data->eglGetProcAddress(proc); } #if !defined(__EMSCRIPTEN__) && !defined(SDL_VIDEO_DRIVER_VITA) /* LoadFunction isn't needed on Emscripten and will call dlsym(), causing other problems. */ /* Try SDL_LoadFunction() first for EGL <= 1.4, or as a fallback for >= 1.5. */ - if (retval == NULL) { + if (!retval) { retval = SDL_LoadFunction(_this->egl_data->opengl_dll_handle, proc); } #endif /* Try eglGetProcAddress if we're on <= 1.4 and still searching... */ - if (retval == NULL && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) { + if (!retval && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) { retval = _this->egl_data->eglGetProcAddress(proc); } } @@ -342,17 +342,17 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p #if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA) /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); - if (path != NULL) { + if (path) { opengl_dll_handle = SDL_LoadObject(path); } - if (opengl_dll_handle == NULL) { + if (!opengl_dll_handle) { if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { if (_this->gl_config.major_version > 1) { path = DEFAULT_OGL_ES2; opengl_dll_handle = SDL_LoadObject(path); #ifdef ALT_OGL_ES2 - if (opengl_dll_handle == NULL && !vc4) { + if (!opengl_dll_handle && !vc4) { path = ALT_OGL_ES2; opengl_dll_handle = SDL_LoadObject(path); } @@ -361,12 +361,12 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p } else { path = DEFAULT_OGL_ES; opengl_dll_handle = SDL_LoadObject(path); - if (opengl_dll_handle == NULL) { + if (!opengl_dll_handle) { path = DEFAULT_OGL_ES_PVR; opengl_dll_handle = SDL_LoadObject(path); } #ifdef ALT_OGL_ES2 - if (opengl_dll_handle == NULL && !vc4) { + if (!opengl_dll_handle && !vc4) { path = ALT_OGL_ES2; opengl_dll_handle = SDL_LoadObject(path); } @@ -378,7 +378,7 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p path = DEFAULT_OGL; opengl_dll_handle = SDL_LoadObject(path); #ifdef ALT_OGL - if (opengl_dll_handle == NULL) { + if (!opengl_dll_handle) { path = ALT_OGL; opengl_dll_handle = SDL_LoadObject(path); } @@ -388,34 +388,34 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p } _this->egl_data->opengl_dll_handle = opengl_dll_handle; - if (opengl_dll_handle == NULL) { + if (!opengl_dll_handle) { return SDL_SetError("Could not initialize OpenGL / GLES library"); } /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */ - if (egl_path != NULL) { + if (egl_path) { egl_dll_handle = SDL_LoadObject(egl_path); } /* Try loading a EGL symbol, if it does not work try the default library paths */ - if (egl_dll_handle == NULL || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) { - if (egl_dll_handle != NULL) { + if (!egl_dll_handle || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) { + if (egl_dll_handle) { SDL_UnloadObject(egl_dll_handle); } path = SDL_getenv("SDL_VIDEO_EGL_DRIVER"); - if (path == NULL) { + if (!path) { path = DEFAULT_EGL; } egl_dll_handle = SDL_LoadObject(path); #ifdef ALT_EGL - if (egl_dll_handle == NULL && !vc4) { + if (!egl_dll_handle && !vc4) { path = ALT_EGL; egl_dll_handle = SDL_LoadObject(path); } #endif - if (egl_dll_handle == NULL || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) { - if (egl_dll_handle != NULL) { + if (!egl_dll_handle || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) { + if (egl_dll_handle) { SDL_UnloadObject(egl_dll_handle); } return SDL_SetError("Could not load EGL library"); @@ -550,7 +550,7 @@ int SDL_EGL_LoadLibrary(SDL_VideoDevice *_this, const char *egl_path, NativeDisp #endif /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */ if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) && - (_this->egl_data->eglGetDisplay != NULL) && + (_this->egl_data->eglGetDisplay) && SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK, SDL_TRUE)) { _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); } @@ -594,11 +594,11 @@ int SDL_EGL_InitializeOffscreen(SDL_VideoDevice *_this, int device) } /* Check for all extensions that are optional until used and fail if any is missing */ - if (_this->egl_data->eglQueryDevicesEXT == NULL) { + if (!_this->egl_data->eglQueryDevicesEXT) { return SDL_SetError("eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)"); } - if (_this->egl_data->eglGetPlatformDisplayEXT == NULL) { + if (!_this->egl_data->eglGetPlatformDisplayEXT) { return SDL_SetError("eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)"); } diff --git a/src/video/SDL_fillrect.c b/src/video/SDL_fillrect.c index 1e0eac852dde2..2a4c132be22f0 100644 --- a/src/video/SDL_fillrect.c +++ b/src/video/SDL_fillrect.c @@ -231,12 +231,12 @@ static void SDL_FillSurfaceRect4(Uint8 *pixels, int pitch, Uint32 color, int w, */ int SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color) { - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_FillSurfaceRect(): dst"); } /* If 'rect' == NULL, then fill the whole surface */ - if (rect == NULL) { + if (!rect) { rect = &dst->clip_rect; /* Don't attempt to fill if the surface's clip_rect is empty */ if (SDL_RectEmpty(rect)) { @@ -304,7 +304,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, void (*fill_function)(Uint8 * pixels, int pitch, Uint32 color, int w, int h) = NULL; int i; - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("SDL_FillSurfaceRects(): dst"); } @@ -318,7 +318,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, return SDL_SetError("SDL_FillSurfaceRects(): You must lock the surface"); } - if (rects == NULL) { + if (!rects) { return SDL_InvalidParamError("SDL_FillSurfaceRects(): rects"); } @@ -340,7 +340,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, } #ifdef SDL_ARM_NEON_BLITTERS - if (SDL_HasNEON() && dst->format->BytesPerPixel != 3 && fill_function == NULL) { + if (SDL_HasNEON() && dst->format->BytesPerPixel != 3 && !fill_function) { switch (dst->format->BytesPerPixel) { case 1: fill_function = fill_8_neon; @@ -355,7 +355,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, } #endif #ifdef SDL_ARM_SIMD_BLITTERS - if (SDL_HasARMSIMD() && dst->format->BytesPerPixel != 3 && fill_function == NULL) { + if (SDL_HasARMSIMD() && dst->format->BytesPerPixel != 3 && !fill_function) { switch (dst->format->BytesPerPixel) { case 1: fill_function = fill_8_simd; @@ -370,7 +370,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, } #endif - if (fill_function == NULL) { + if (!fill_function) { switch (dst->format->BytesPerPixel) { case 1: { diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index f9e79bfd42ae0..262880c83da04 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -558,7 +558,7 @@ SDL_PixelFormat *SDL_CreatePixelFormat(Uint32 pixel_format) /* Allocate an empty pixel format structure, and initialize it */ format = SDL_malloc(sizeof(*format)); - if (format == NULL) { + if (!format) { SDL_AtomicUnlock(&formats_lock); SDL_OutOfMemory(); return NULL; @@ -656,7 +656,7 @@ void SDL_DestroyPixelFormat(SDL_PixelFormat *format) { SDL_PixelFormat *prev; - if (format == NULL) { + if (!format) { return; } @@ -699,7 +699,7 @@ SDL_Palette *SDL_CreatePalette(int ncolors) } palette = (SDL_Palette *)SDL_malloc(sizeof(*palette)); - if (palette == NULL) { + if (!palette) { SDL_OutOfMemory(); return NULL; } @@ -721,7 +721,7 @@ SDL_Palette *SDL_CreatePalette(int ncolors) int SDL_SetPixelFormatPalette(SDL_PixelFormat *format, SDL_Palette *palette) { - if (format == NULL) { + if (!format) { return SDL_InvalidParamError("SDL_SetPixelFormatPalette(): format"); } @@ -752,7 +752,7 @@ int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, int status = 0; /* Verify the parameters */ - if (palette == NULL) { + if (!palette) { return -1; } if (ncolors > (palette->ncolors - firstcolor)) { @@ -774,7 +774,7 @@ int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, void SDL_DestroyPalette(SDL_Palette *palette) { - if (palette == NULL) { + if (!palette) { return; } if (--palette->refcount > 0) { @@ -895,7 +895,7 @@ Uint32 SDL_MapRGB(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b) SDL_InvalidParamError("format"); return 0; } - if (format->palette == NULL) { + if (!format->palette) { return (r >> format->Rloss) << format->Rshift | (g >> format->Gloss) << format->Gshift | (b >> format->Bloss) << format->Bshift | format->Amask; } else { return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE); @@ -910,7 +910,7 @@ Uint32 SDL_MapRGBA(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b, SDL_InvalidParamError("format"); return 0; } - if (format->palette == NULL) { + if (!format->palette) { return (r >> format->Rloss) << format->Rshift | (g >> format->Gloss) << format->Gshift | (b >> format->Bloss) << format->Bshift | ((Uint32)(a >> format->Aloss) << format->Ashift & format->Amask); } else { return SDL_FindColor(format->palette, r, g, b, a); @@ -920,7 +920,7 @@ Uint32 SDL_MapRGBA(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b, void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat *format, Uint8 *r, Uint8 *g, Uint8 *b) { - if (format->palette == NULL) { + if (!format->palette) { unsigned v; v = (pixel & format->Rmask) >> format->Rshift; *r = SDL_expand_byte[format->Rloss][v]; @@ -942,7 +942,7 @@ void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat *format, Uint8 *r, Uint8 *g, void SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat *format, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { - if (format->palette == NULL) { + if (!format->palette) { unsigned v; v = (pixel & format->Rmask) >> format->Rshift; *r = SDL_expand_byte[format->Rloss][v]; @@ -983,7 +983,7 @@ static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) *identical = 0; } map = (Uint8 *)SDL_calloc(256, sizeof(Uint8)); - if (map == NULL) { + if (!map) { SDL_OutOfMemory(); return NULL; } @@ -1006,7 +1006,7 @@ static Uint8 *Map1toN(SDL_PixelFormat *src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); map = (Uint8 *)SDL_calloc(256, bpp); - if (map == NULL) { + if (!map) { SDL_OutOfMemory(); return NULL; } @@ -1042,7 +1042,7 @@ SDL_BlitMap *SDL_AllocBlitMap(void) /* Allocate the empty map */ map = (SDL_BlitMap *)SDL_calloc(1, sizeof(*map)); - if (map == NULL) { + if (!map) { SDL_OutOfMemory(); return NULL; } @@ -1071,7 +1071,7 @@ void SDL_InvalidateAllBlitMap(SDL_Surface *surface) void SDL_InvalidateMap(SDL_BlitMap *map) { - if (map == NULL) { + if (!map) { return; } if (map->dst) { @@ -1110,7 +1110,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst) map->info.table = Map1to1(srcfmt->palette, dstfmt->palette, &map->identity); if (!map->identity) { - if (map->info.table == NULL) { + if (!map->info.table) { return -1; } } @@ -1122,7 +1122,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst) map->info.table = Map1toN(srcfmt, src->map->info.r, src->map->info.g, src->map->info.b, src->map->info.a, dstfmt); - if (map->info.table == NULL) { + if (!map->info.table) { return -1; } } @@ -1131,7 +1131,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst) /* BitField --> Palette */ map->info.table = MapNto1(srcfmt, dstfmt, &map->identity); if (!map->identity) { - if (map->info.table == NULL) { + if (!map->info.table) { return -1; } } diff --git a/src/video/SDL_rect.c b/src/video/SDL_rect.c index af3a809c7d49f..d37361149b258 100644 --- a/src/video/SDL_rect.c +++ b/src/video/SDL_rect.c @@ -37,10 +37,10 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height, } else if (height < 1) { SDL_InvalidParamError("height"); return SDL_FALSE; - } else if (rects == NULL) { + } else if (!rects) { SDL_InvalidParamError("rects"); return SDL_FALSE; - } else if (span == NULL) { + } else if (!span) { SDL_InvalidParamError("span"); return SDL_FALSE; } else if (numrects < 1) { diff --git a/src/video/SDL_rect_impl.h b/src/video/SDL_rect_impl.h index 4b8713c37348e..15591a5ac4143 100644 --- a/src/video/SDL_rect_impl.h +++ b/src/video/SDL_rect_impl.h @@ -25,10 +25,10 @@ SDL_bool SDL_HASINTERSECTION(const RECTTYPE *A, const RECTTYPE *B) { SCALARTYPE Amin, Amax, Bmin, Bmax; - if (A == NULL) { + if (!A) { SDL_InvalidParamError("A"); return SDL_FALSE; - } else if (B == NULL) { + } else if (!B) { SDL_InvalidParamError("B"); return SDL_FALSE; } else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) { @@ -70,13 +70,13 @@ SDL_bool SDL_INTERSECTRECT(const RECTTYPE *A, const RECTTYPE *B, RECTTYPE *resul { SCALARTYPE Amin, Amax, Bmin, Bmax; - if (A == NULL) { + if (!A) { SDL_InvalidParamError("A"); return SDL_FALSE; - } else if (B == NULL) { + } else if (!B) { SDL_InvalidParamError("B"); return SDL_FALSE; - } else if (result == NULL) { + } else if (!result) { SDL_InvalidParamError("result"); return SDL_FALSE; } else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) { /* Special cases for empty rects */ @@ -120,11 +120,11 @@ int SDL_UNIONRECT(const RECTTYPE *A, const RECTTYPE *B, RECTTYPE *result) { SCALARTYPE Amin, Amax, Bmin, Bmax; - if (A == NULL) { + if (!A) { return SDL_InvalidParamError("A"); - } else if (B == NULL) { + } else if (!B) { return SDL_InvalidParamError("B"); - } else if (result == NULL) { + } else if (!result) { return SDL_InvalidParamError("result"); } else if (SDL_RECTEMPTY(A)) { /* Special cases for empty Rects */ if (SDL_RECTEMPTY(B)) { /* A and B empty */ @@ -178,7 +178,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c SCALARTYPE x, y; int i; - if (points == NULL) { + if (!points) { SDL_InvalidParamError("points"); return SDL_FALSE; } else if (count < 1) { @@ -208,7 +208,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c } if (!added) { /* Special case: if no result was requested, we are done */ - if (result == NULL) { + if (!result) { return SDL_TRUE; } @@ -234,7 +234,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c } } else { /* Special case: if no result was requested, we are done */ - if (result == NULL) { + if (!result) { return SDL_TRUE; } @@ -297,19 +297,19 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY SCALARTYPE recty2; int outcode1, outcode2; - if (rect == NULL) { + if (!rect) { SDL_InvalidParamError("rect"); return SDL_FALSE; - } else if (X1 == NULL) { + } else if (!X1) { SDL_InvalidParamError("X1"); return SDL_FALSE; - } else if (Y1 == NULL) { + } else if (!Y1) { SDL_InvalidParamError("Y1"); return SDL_FALSE; - } else if (X2 == NULL) { + } else if (!X2) { SDL_InvalidParamError("X2"); return SDL_FALSE; - } else if (Y2 == NULL) { + } else if (!Y2) { SDL_InvalidParamError("Y2"); return SDL_FALSE; } else if (SDL_RECTEMPTY(rect)) { diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index b5fc437b7dae3..2afcf6319ecff 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -28,13 +28,13 @@ SDL_Window *SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags { SDL_Window *result = NULL; result = SDL_CreateWindow(title, w, h, (flags | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE)); - if (result != NULL) { + if (result) { if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) { SDL_DestroyWindow(result); return NULL; } result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result); - if (result->shaper != NULL) { + if (result->shaper) { result->shaper->mode.mode = ShapeModeDefault; result->shaper->mode.parameters.binarizationCutoff = 1; result->shaper->hasshape = SDL_FALSE; @@ -113,7 +113,7 @@ static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SD SDL_ShapeTree *result = (SDL_ShapeTree *)SDL_malloc(sizeof(SDL_ShapeTree)); SDL_Rect next = { 0, 0, 0, 0 }; - if (result == NULL) { + if (!result) { SDL_OutOfMemory(); return NULL; } @@ -200,7 +200,7 @@ SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *sha void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure) { - SDL_assert(tree != NULL); + SDL_assert(tree); if (tree->kind == QuadShape) { SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft, function, closure); SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright, function, closure); @@ -228,16 +228,16 @@ int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMo SDL_VideoDevice *_this = SDL_GetVideoDevice(); int result; - if (window == NULL || !SDL_IsShapedWindow(window)) { + if (!window || !SDL_IsShapedWindow(window)) { /* The window given was not a shapeable window. */ return SDL_NONSHAPEABLE_WINDOW; } - if (shape == NULL) { + if (!shape) { /* Invalid shape argument. */ return SDL_INVALID_SHAPE_ARGUMENT; } - if (shape_mode != NULL) { + if (shape_mode) { window->shaper->mode = *shape_mode; } result = _this->shape_driver.SetWindowShape(window->shaper, shape, shape_mode); @@ -250,7 +250,7 @@ int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMo static SDL_bool SDL_WindowHasAShape(SDL_Window *window) { - if (window == NULL || !SDL_IsShapedWindow(window)) { + if (!window || !SDL_IsShapedWindow(window)) { return SDL_FALSE; } return window->shaper->hasshape; @@ -258,8 +258,8 @@ static SDL_bool SDL_WindowHasAShape(SDL_Window *window) int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode) { - if (window != NULL && SDL_IsShapedWindow(window)) { - if (shape_mode == NULL) { + if (window && SDL_IsShapedWindow(window)) { + if (!shape_mode) { if (SDL_WindowHasAShape(window)) { return 0; /* The window given has a shape. */ } else { diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 00e747fcb0c7c..bc71c541341b8 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -142,7 +142,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) /* Allocate the surface */ surface = (SDL_Surface *)SDL_calloc(1, sizeof(*surface)); - if (surface == NULL) { + if (!surface) { SDL_OutOfMemory(); return NULL; } @@ -160,7 +160,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) if (SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) { SDL_Palette *palette = SDL_CreatePalette((1 << surface->format->BitsPerPixel)); - if (palette == NULL) { + if (!palette) { SDL_DestroySurface(surface); return NULL; } @@ -225,7 +225,7 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc return NULL; } - if (pitch == 0 && pixels == NULL) { + if (pitch == 0 && !pixels) { /* The application will fill these in later with valid values */ } else { size_t minimalPitch; @@ -243,7 +243,7 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc } surface = SDL_CreateSurface(0, 0, format); - if (surface != NULL) { + if (surface) { surface->flags |= SDL_PREALLOC; surface->pixels = pixels; surface->w = width; @@ -256,7 +256,7 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface) { - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("surface"); return 0; } @@ -269,7 +269,7 @@ SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface) int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette) { - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) { @@ -284,7 +284,7 @@ int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) { int flags; - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -302,7 +302,7 @@ int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) SDL_bool SDL_SurfaceHasRLE(SDL_Surface *surface) { - if (surface == NULL) { + if (!surface) { return SDL_FALSE; } @@ -317,7 +317,7 @@ int SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key) { int flags; - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -345,7 +345,7 @@ int SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key) SDL_bool SDL_SurfaceHasColorKey(SDL_Surface *surface) { - if (surface == NULL) { + if (!surface) { return SDL_FALSE; } @@ -358,7 +358,7 @@ SDL_bool SDL_SurfaceHasColorKey(SDL_Surface *surface) int SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 *key) { - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -378,7 +378,7 @@ static void SDL_ConvertColorkeyToAlpha(SDL_Surface *surface, SDL_bool ignore_alp { int x, y, bpp; - if (surface == NULL) { + if (!surface) { return; } @@ -467,7 +467,7 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) { int flags; - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -489,7 +489,7 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b) { - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -509,7 +509,7 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) { int flags; - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -529,7 +529,7 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha) { - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -543,7 +543,7 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode) { int flags, status; - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -580,11 +580,11 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode) int SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode) { - if (surface == NULL) { + if (!surface) { return SDL_InvalidParamError("surface"); } - if (blendMode == NULL) { + if (!blendMode) { return 0; } @@ -613,7 +613,7 @@ SDL_bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect) SDL_Rect full_rect; /* Don't do anything if there's no surface to act on */ - if (surface == NULL) { + if (!surface) { return SDL_FALSE; } @@ -624,7 +624,7 @@ SDL_bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect) full_rect.h = surface->h; /* Set the clipping rectangle */ - if (rect == NULL) { + if (!rect) { surface->clip_rect = full_rect; return SDL_TRUE; } @@ -682,7 +682,7 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, int srcx, srcy, w, h; /* Make sure the surfaces aren't locked */ - if (src == NULL || dst == NULL) { + if (!src || !dst) { return SDL_InvalidParamError("SDL_BlitSurface(): src/dst"); } if (src->locked || dst->locked) { @@ -690,7 +690,7 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, } /* If the destination rectangle is NULL, use the entire dest surface */ - if (dstrect == NULL) { + if (!dstrect) { fulldst.x = fulldst.y = 0; fulldst.w = dst->w; fulldst.h = dst->h; @@ -794,14 +794,14 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, int dst_w, dst_h; /* Make sure the surfaces aren't locked */ - if (src == NULL || dst == NULL) { + if (!src || !dst) { return SDL_InvalidParamError("SDL_BlitSurfaceScaled(): src/dst"); } if (src->locked || dst->locked) { return SDL_SetError("Surfaces must not be locked during blit"); } - if (srcrect == NULL) { + if (!srcrect) { src_w = src->w; src_h = src->h; } else { @@ -809,7 +809,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, src_h = srcrect->h; } - if (dstrect == NULL) { + if (!dstrect) { dst_w = dst->w; dst_h = dst->h; } else { @@ -825,7 +825,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, scaling_w = (double)dst_w / src_w; scaling_h = (double)dst_h / src_h; - if (dstrect == NULL) { + if (!dstrect) { dst_x0 = 0; dst_y0 = 0; dst_x1 = dst_w; @@ -837,7 +837,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, dst_y1 = dst_y0 + dst_h; } - if (srcrect == NULL) { + if (!srcrect) { src_x0 = 0; src_y0 = 0; src_x1 = src_w; @@ -1120,17 +1120,17 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for Uint8 *palette_saved_alpha = NULL; int palette_saved_alpha_ncolors = 0; - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("surface"); return NULL; } - if (format == NULL) { + if (!format) { SDL_InvalidParamError("format"); return NULL; } /* Check for empty destination palette! (results in empty image) */ - if (format->palette != NULL) { + if (format->palette) { int i; for (i = 0; i < format->palette->ncolors; ++i) { if ((format->palette->colors[i].r != 0xFF) || (format->palette->colors[i].g != 0xFF) || (format->palette->colors[i].b != 0xFF)) { @@ -1145,7 +1145,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for /* Create a new surface with the desired format */ convert = SDL_CreateSurface(surface->w, surface->h, format->format); - if (convert == NULL) { + if (!convert) { return NULL; } @@ -1303,7 +1303,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for /* Create a dummy surface to get the colorkey converted */ tmp = SDL_CreateSurface(1, 1, surface->format->format); - if (tmp == NULL) { + if (!tmp) { SDL_DestroySurface(convert); return NULL; } @@ -1319,7 +1319,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for /* Conversion of the colorkey */ tmp2 = SDL_ConvertSurface(tmp, format); - if (tmp2 == NULL) { + if (!tmp2) { SDL_DestroySurface(tmp); SDL_DestroySurface(convert); return NULL; @@ -1425,13 +1425,13 @@ int SDL_ConvertPixels(int width, int height, void *nonconst_src = (void *)src; int ret; - if (src == NULL) { + if (!src) { return SDL_InvalidParamError("src"); } if (!src_pitch) { return SDL_InvalidParamError("src_pitch"); } - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("dst"); } if (!dst_pitch) { @@ -1507,13 +1507,13 @@ int SDL_PremultiplyAlpha(int width, int height, Uint32 dstpixel; Uint32 dstR, dstG, dstB, dstA; - if (src == NULL) { + if (!src) { return SDL_InvalidParamError("src"); } if (!src_pitch) { return SDL_InvalidParamError("src_pitch"); } - if (dst == NULL) { + if (!dst) { return SDL_InvalidParamError("dst"); } if (!dst_pitch) { @@ -1555,7 +1555,7 @@ int SDL_PremultiplyAlpha(int width, int height, */ void SDL_DestroySurface(SDL_Surface *surface) { - if (surface == NULL) { + if (!surface) { return; } if (surface->flags & SDL_DONTFREE) { diff --git a/src/video/SDL_surface_pixel_impl.h b/src/video/SDL_surface_pixel_impl.h index 43985b78b9bde..94f1073615292 100644 --- a/src/video/SDL_surface_pixel_impl.h +++ b/src/video/SDL_surface_pixel_impl.h @@ -29,7 +29,7 @@ static int SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 * size_t bytes_per_pixel; void *p; - if (surface == NULL || surface->format == NULL || surface->pixels == NULL) { + if (!surface || !surface->format || !surface->pixels) { return SDL_InvalidParamError("surface"); } @@ -41,19 +41,19 @@ static int SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 * return SDL_InvalidParamError("y"); } - if (r == NULL) { + if (!r) { return SDL_InvalidParamError("r"); } - if (g == NULL) { + if (!g) { return SDL_InvalidParamError("g"); } - if (b == NULL) { + if (!b) { return SDL_InvalidParamError("b"); } - if (a == NULL) { + if (!a) { return SDL_InvalidParamError("a"); } diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index d4ab9a475d1a4..591e0277c7f71 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -196,12 +196,12 @@ typedef struct static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this) { #if (defined(SDL_VIDEO_OPENGL) && defined(__MACOS__)) || (defined(__IOS__) && !TARGET_OS_MACCATALYST) || defined(__ANDROID__) - if (_this->GL_CreateContext != NULL) { + if (_this->GL_CreateContext) { return SDL_WINDOW_OPENGL; } #endif #if defined(SDL_VIDEO_METAL) && (TARGET_OS_MACCATALYST || defined(__MACOS__) || defined(__IOS__)) - if (_this->Metal_CreateView != NULL) { + if (_this->Metal_CreateView) { return SDL_WINDOW_METAL; } #endif @@ -233,7 +233,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_GetWindowSizeInPixels(window, &w, &h); - if (data == NULL) { + if (!data) { SDL_Renderer *renderer = NULL; const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION); const SDL_bool specific_accelerated_renderer = (hint && *hint != '0' && *hint != '1' && @@ -244,7 +244,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U /* Check to see if there's a specific driver requested */ if (specific_accelerated_renderer) { renderer = SDL_CreateRenderer(window, hint, 0); - if (renderer == NULL || (SDL_GetRendererInfo(renderer, &info) == -1)) { + if (!renderer || (SDL_GetRendererInfo(renderer, &info) == -1)) { if (renderer) { SDL_DestroyRenderer(renderer); } @@ -266,16 +266,16 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U } } } - if (renderer == NULL) { + if (!renderer) { return SDL_SetError("No hardware accelerated renderers available"); } } - SDL_assert(renderer != NULL); /* should have explicitly checked this above. */ + SDL_assert(renderer); /* should have explicitly checked this above. */ /* Create the data after we successfully create the renderer (bug #1116) */ data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { SDL_DestroyRenderer(renderer); return SDL_OutOfMemory(); } @@ -350,7 +350,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, SDL_GetWindowSizeInPixels(window, &w, &h); data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); - if (data == NULL || !data->texture) { + if (!data || !data->texture) { return SDL_SetError("No window texture data"); } @@ -382,10 +382,10 @@ int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync) SDL_WindowTextureData *data; data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); - if (data == NULL) { + if (!data) { return -1; } - if (data->renderer == NULL ) { + if (!data->renderer) { return -1; } return SDL_SetRenderVSync(data->renderer, vsync); @@ -448,7 +448,7 @@ int SDL_VideoInit(const char *driver_name) int i = 0; /* Check to make sure we don't overwrite '_this' */ - if (_this != NULL) { + if (_this) { SDL_VideoQuit(); } @@ -480,14 +480,14 @@ int SDL_VideoInit(const char *driver_name) /* Select the proper video driver */ video = NULL; - if (driver_name == NULL) { + if (!driver_name) { driver_name = SDL_GetHint(SDL_HINT_VIDEO_DRIVER); } - if (driver_name != NULL && *driver_name != 0) { + if (driver_name && *driver_name != 0) { const char *driver_attempt = driver_name; - while (driver_attempt != NULL && *driver_attempt != 0 && video == NULL) { + while (driver_attempt && *driver_attempt != 0 && !video) { const char *driver_attempt_end = SDL_strchr(driver_attempt, ','); - size_t driver_attempt_len = (driver_attempt_end != NULL) ? (driver_attempt_end - driver_attempt) + size_t driver_attempt_len = (driver_attempt_end) ? (driver_attempt_end - driver_attempt) : SDL_strlen(driver_attempt); for (i = 0; bootstrap[i]; ++i) { @@ -498,17 +498,17 @@ int SDL_VideoInit(const char *driver_name) } } - driver_attempt = (driver_attempt_end != NULL) ? (driver_attempt_end + 1) : NULL; + driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL; } } else { for (i = 0; bootstrap[i]; ++i) { video = bootstrap[i]->create(); - if (video != NULL) { + if (video) { break; } } } - if (video == NULL) { + if (!video) { if (driver_name) { SDL_SetError("%s not available", driver_name); goto pre_driver_error; @@ -570,7 +570,7 @@ int SDL_VideoInit(const char *driver_name) return 0; pre_driver_error: - SDL_assert(_this == NULL); + SDL_assert(!_this); if (init_video_capture) { SDL_QuitVideoCapture(); } @@ -591,7 +591,7 @@ int SDL_VideoInit(const char *driver_name) const char *SDL_GetCurrentVideoDriver(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -855,7 +855,7 @@ int SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Rect *rect) CHECK_DISPLAY_MAGIC(display, -1); - if (rect == NULL) { + if (!rect) { return SDL_InvalidParamError("rect"); } @@ -890,7 +890,7 @@ int SDL_GetDisplayUsableBounds(SDL_DisplayID displayID, SDL_Rect *rect) CHECK_DISPLAY_MAGIC(display, -1); - if (rect == NULL) { + if (!rect) { return SDL_InvalidParamError("rect"); } @@ -1032,7 +1032,7 @@ SDL_bool SDL_AddFullscreenDisplayMode(SDL_VideoDisplay *display, const SDL_Displ /* Go ahead and add the new mode */ if (nmodes == display->max_fullscreen_modes) { modes = (SDL_DisplayMode *)SDL_malloc((display->max_fullscreen_modes + 32) * sizeof(*modes)); - if (modes == NULL) { + if (!modes) { return SDL_FALSE; } @@ -1312,7 +1312,7 @@ void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int if (SDL_WINDOW_IS_POPUP(window)) { /* Calculate the total offset of the popup from the parents */ - for (w = window->parent; w != NULL; w = w->parent) { + for (w = window->parent; w; w = w->parent) { rel_x += w->x; rel_y += w->y; } @@ -1332,7 +1332,7 @@ void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int if (SDL_WINDOW_IS_POPUP(window)) { /* Convert absolute window coordinates to relative for a popup */ - for (w = window->parent; w != NULL; w = w->parent) { + for (w = window->parent; w; w = w->parent) { abs_x -= w->x; abs_y -= w->y; } @@ -1522,7 +1522,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) if (fullscreen) { mode = (SDL_DisplayMode *)SDL_GetWindowFullscreenMode(window); - if (mode != NULL) { + if (mode) { window->fullscreen_exclusive = SDL_TRUE; } else { /* Make sure the current mode is zeroed for fullscreen desktop. */ @@ -1851,14 +1851,14 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int SDL_bool undefined_x = SDL_FALSE; SDL_bool undefined_y = SDL_FALSE; - if (_this == NULL) { + if (!_this) { /* Initialize the video system if needed */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { return NULL; } /* Make clang-tidy happy */ - if (_this == NULL) { + if (!_this) { return NULL; } } @@ -1967,7 +1967,7 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int } window = (SDL_Window *)SDL_calloc(1, sizeof(*window)); - if (window == NULL) { + if (!window) { SDL_OutOfMemory(); return NULL; } @@ -2067,7 +2067,7 @@ SDL_Window *SDL_CreateWindowWithPosition(const char *title, int x, int y, int w, SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -2097,7 +2097,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) SDL_Window *window; Uint32 flags = SDL_WINDOW_FOREIGN; - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -2133,7 +2133,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) } window = (SDL_Window *)SDL_calloc(1, sizeof(*window)); - if (window == NULL) { + if (!window) { SDL_OutOfMemory(); return NULL; } @@ -2297,7 +2297,7 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) SDL_bool SDL_HasWindows(void) { - return _this && _this->windows != NULL; + return _this && _this->windows; } SDL_WindowID SDL_GetWindowID(SDL_Window *window) @@ -2311,7 +2311,7 @@ SDL_Window *SDL_GetWindowFromID(SDL_WindowID id) { SDL_Window *window; - if (_this == NULL) { + if (!_this) { return NULL; } for (window = _this->windows; window; window = window->next) { @@ -2375,7 +2375,7 @@ int SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon) { CHECK_WINDOW_MAGIC(window, -1); - if (icon == NULL) { + if (!icon) { return SDL_InvalidParamError("icon"); } @@ -2614,16 +2614,16 @@ int SDL_GetWindowBordersSize(SDL_Window *window, int *top, int *left, int *botto { int dummy = 0; - if (top == NULL) { + if (!top) { top = &dummy; } - if (left == NULL) { + if (!left) { left = &dummy; } - if (right == NULL) { + if (!right) { right = &dummy; } - if (bottom == NULL) { + if (!bottom) { bottom = &dummy; } @@ -2645,11 +2645,11 @@ int SDL_GetWindowSizeInPixels(SDL_Window *window, int *w, int *h) CHECK_WINDOW_MAGIC(window, -1); - if (w == NULL) { + if (!w) { w = &filter; } - if (h == NULL) { + if (!h) { h = &filter; } @@ -2791,7 +2791,7 @@ int SDL_ShowWindow(SDL_Window *window) window->pending_flags = 0; /* Restore child windows */ - for (child = window->first_child; child != NULL; child = child->next_sibling) { + for (child = window->first_child; child; child = child->next_sibling) { if (!child->restore_on_show && (child->flags & SDL_WINDOW_HIDDEN)) { break; } @@ -2812,7 +2812,7 @@ int SDL_HideWindow(SDL_Window *window) } /* Hide all child windows */ - for (child = window->first_child; child != NULL; child = child->next_sibling) { + for (child = window->first_child; child; child = child->next_sibling) { if (child->flags & SDL_WINDOW_HIDDEN) { break; } @@ -2995,7 +2995,7 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window) #ifdef __LINUX__ /* On WSL, direct X11 is faster than using OpenGL for window framebuffers, so try to detect WSL and avoid texture framebuffer. */ - else if ((_this->CreateWindowFramebuffer != NULL) && (SDL_strcmp(_this->name, "x11") == 0)) { + else if ((_this->CreateWindowFramebuffer) && (SDL_strcmp(_this->name, "x11") == 0)) { struct stat sb; if ((stat("/proc/sys/fs/binfmt_misc/WSLInterop", &sb) == 0) || (stat("/run/WSL", &sb) == 0)) { /* if either of these exist, we're on WSL. */ attempt_texture_framebuffer = SDL_FALSE; @@ -3003,7 +3003,7 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window) } #endif #if defined(__WIN32__) || defined(__WINGDK__) /* GDI BitBlt() is way faster than Direct3D dynamic textures right now. (!!! FIXME: is this still true?) */ - else if ((_this->CreateWindowFramebuffer != NULL) && (SDL_strcmp(_this->name, "windows") == 0)) { + else if ((_this->CreateWindowFramebuffer) && (SDL_strcmp(_this->name, "windows") == 0)) { attempt_texture_framebuffer = SDL_FALSE; } #endif @@ -3510,7 +3510,7 @@ static SDL_bool SDL_ShouldMinimizeOnFocusLoss(SDL_Window *window) /* Real fullscreen windows should minimize on focus loss so the desktop video mode is restored */ hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS); - if (hint == NULL || !*hint || SDL_strcasecmp(hint, "auto") == 0) { + if (!hint || !*hint || SDL_strcasecmp(hint, "auto") == 0) { if (window->fullscreen_exclusive && !ModeSwitchingEmulated(_this)) { return SDL_TRUE; } else { @@ -3643,7 +3643,7 @@ void SDL_DestroyWindow(SDL_Window *window) SDL_bool SDL_ScreenSaverEnabled(void) { - if (_this == NULL) { + if (!_this) { return SDL_TRUE; } return !_this->suspend_screensaver; @@ -3651,7 +3651,7 @@ SDL_bool SDL_ScreenSaverEnabled(void) int SDL_EnableScreenSaver(void) { - if (_this == NULL) { + if (!_this) { return 0; } if (!_this->suspend_screensaver) { @@ -3667,7 +3667,7 @@ int SDL_EnableScreenSaver(void) int SDL_DisableScreenSaver(void) { - if (_this == NULL) { + if (!_this) { return 0; } if (_this->suspend_screensaver) { @@ -3685,7 +3685,7 @@ void SDL_VideoQuit(void) { int i; - if (_this == NULL) { + if (!_this) { return; } @@ -3728,7 +3728,7 @@ int SDL_GL_LoadLibrary(const char *path) { int retval; - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); } if (_this->gl_config.driver_loaded) { @@ -3756,7 +3756,7 @@ SDL_FunctionPointer SDL_GL_GetProcAddress(const char *proc) { SDL_FunctionPointer func; - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -3799,7 +3799,7 @@ SDL_FunctionPointer SDL_EGL_GetProcAddress(const char *proc) void SDL_GL_UnloadLibrary(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return; } @@ -3849,7 +3849,7 @@ SDL_bool SDL_GL_ExtensionSupported(const char *extension) /* Lookup the available extensions */ glGetStringFunc = (PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"); - if (glGetStringFunc == NULL) { + if (!glGetStringFunc) { return SDL_FALSE; } @@ -3861,7 +3861,7 @@ SDL_bool SDL_GL_ExtensionSupported(const char *extension) glGetStringiFunc = (PFNGLGETSTRINGIPROC)SDL_GL_GetProcAddress("glGetStringi"); glGetIntegervFunc = (PFNGLGETINTEGERVPROC)SDL_GL_GetProcAddress("glGetIntegerv"); - if ((glGetStringiFunc == NULL) || (glGetIntegervFunc == NULL)) { + if ((!glGetStringiFunc) || (!glGetIntegervFunc)) { return SDL_FALSE; } @@ -3882,7 +3882,7 @@ SDL_bool SDL_GL_ExtensionSupported(const char *extension) /* Try the old way with glGetString(GL_EXTENSIONS) ... */ extensions = (const char *)glGetStringFunc(GL_EXTENSIONS); - if (extensions == NULL) { + if (!extensions) { return SDL_FALSE; } /* @@ -3894,7 +3894,7 @@ SDL_bool SDL_GL_ExtensionSupported(const char *extension) for (;;) { where = SDL_strstr(start, extension); - if (where == NULL) { + if (!where) { break; } @@ -3957,7 +3957,7 @@ void SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribC void SDL_GL_ResetAttributes(void) { - if (_this == NULL) { + if (!_this) { return; } @@ -4020,7 +4020,7 @@ int SDL_GL_SetAttribute(SDL_GLattr attr, int value) #if defined(SDL_VIDEO_OPENGL) || defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2) int retval; - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); } retval = 0; @@ -4153,14 +4153,14 @@ int SDL_GL_GetAttribute(SDL_GLattr attr, int *value) GLenum attachmentattrib = 0; #endif - if (value == NULL) { + if (!value) { return SDL_InvalidParamError("value"); } /* Clear value in any case */ *value = 0; - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); } @@ -4331,7 +4331,7 @@ int SDL_GL_GetAttribute(SDL_GLattr attr, int *value) #ifdef SDL_VIDEO_OPENGL glGetStringFunc = (PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"); - if (glGetStringFunc == NULL) { + if (!glGetStringFunc) { return -1; } @@ -4368,7 +4368,7 @@ int SDL_GL_GetAttribute(SDL_GLattr attr, int *value) } glGetErrorFunc = (PFNGLGETERRORPROC)SDL_GL_GetProcAddress("glGetError"); - if (glGetErrorFunc == NULL) { + if (!glGetErrorFunc) { return -1; } @@ -4415,7 +4415,7 @@ int SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext context) { int retval; - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); } @@ -4449,7 +4449,7 @@ int SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext context) SDL_Window *SDL_GL_GetCurrentWindow(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -4458,7 +4458,7 @@ SDL_Window *SDL_GL_GetCurrentWindow(void) SDL_GLContext SDL_GL_GetCurrentContext(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -4524,7 +4524,7 @@ SDL_EGLConfig SDL_EGL_GetWindowEGLSurface(SDL_Window *window) int SDL_GL_SetSwapInterval(int interval) { - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); } else if (SDL_GL_GetCurrentContext() == NULL) { return SDL_SetError("No OpenGL context has been made current"); @@ -4537,13 +4537,13 @@ int SDL_GL_SetSwapInterval(int interval) int SDL_GL_GetSwapInterval(int *interval) { - if (interval == NULL) { + if (!interval) { return SDL_InvalidParamError("interval"); } *interval = 0; - if (_this == NULL) { + if (!_this) { return SDL_SetError("no video driver");; } else if (SDL_GL_GetCurrentContext() == NULL) { return SDL_SetError("no current context");; @@ -4571,7 +4571,7 @@ int SDL_GL_SwapWindow(SDL_Window *window) int SDL_GL_DeleteContext(SDL_GLContext context) { - if (_this == NULL) { + if (!_this) { return SDL_UninitializedVideo(); \ } if (!context) { @@ -4749,7 +4749,7 @@ void SDL_StopTextInput(void) int SDL_SetTextInputRect(const SDL_Rect *rect) { - if (rect == NULL) { + if (!rect) { return SDL_InvalidParamError("rect"); } @@ -4820,7 +4820,7 @@ int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) SDL_Window *current_window; SDL_MessageBoxData mbdata; - if (messageboxdata == NULL) { + if (!messageboxdata) { return SDL_InvalidParamError("messageboxdata"); } else if (messageboxdata->numbuttons < 0) { return SDL_SetError("Invalid number of buttons"); @@ -4836,7 +4836,7 @@ int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) SDL_ShowCursor(); SDL_ResetKeyboard(); - if (buttonid == NULL) { + if (!buttonid) { buttonid = &dummybutton; } @@ -4948,10 +4948,10 @@ int SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *messag /* Web browsers don't (currently) have an API for a custom message box that can block, but for the most common case (SDL_ShowSimpleMessageBox), we can use the standard Javascript alert() function. */ - if (title == NULL) { + if (!title) { title = ""; } - if (message == NULL) { + if (!message) { message = ""; } EM_ASM({ @@ -5031,7 +5031,7 @@ void SDL_OnApplicationWillResignActive(void) { if (_this) { SDL_Window *window; - for (window = _this->windows; window != NULL; window = window->next) { + for (window = _this->windows; window; window = window->next) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } SDL_SetKeyboardFocus(NULL); @@ -5055,7 +5055,7 @@ void SDL_OnApplicationDidBecomeActive(void) if (_this) { SDL_Window *window; - for (window = _this->windows; window != NULL; window = window->next) { + for (window = _this->windows; window; window = window->next) { SDL_SetKeyboardFocus(window); SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); } @@ -5067,7 +5067,7 @@ void SDL_OnApplicationDidBecomeActive(void) int SDL_Vulkan_LoadLibrary(const char *path) { int retval; - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return -1; } @@ -5090,7 +5090,7 @@ int SDL_Vulkan_LoadLibrary(const char *path) SDL_FunctionPointer SDL_Vulkan_GetVkGetInstanceProcAddr(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return NULL; } @@ -5103,7 +5103,7 @@ SDL_FunctionPointer SDL_Vulkan_GetVkGetInstanceProcAddr(void) void SDL_Vulkan_UnloadLibrary(void) { - if (_this == NULL) { + if (!_this) { SDL_UninitializedVideo(); return; } @@ -5139,7 +5139,7 @@ SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window, return SDL_FALSE; } - if (surface == NULL) { + if (!surface) { SDL_InvalidParamError("surface"); return SDL_FALSE; } diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index e44275a9c3b66..a16908a9d385f 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -148,7 +148,7 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList( retval = SDL_calloc(count, sizeof(VkExtensionProperties)); } - if (retval == NULL) { + if (!retval) { SDL_OutOfMemory(); return NULL; } @@ -211,7 +211,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, goto error; } chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY"); - if (chosenDisplayId != NULL) { + if (chosenDisplayId) { displayId = SDL_atoi(chosenDisplayId); } @@ -228,7 +228,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, } physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); - if (physicalDevices == NULL) { + if (!physicalDevices) { SDL_OutOfMemory(); goto error; } @@ -271,7 +271,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, } displayProperties = SDL_malloc(sizeof(VkDisplayPropertiesKHR) * displayPropertiesCount); - if (displayProperties == NULL) { + if (!displayProperties) { SDL_OutOfMemory(); goto error; } @@ -300,7 +300,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display modes: %u", displayModePropertiesCount); displayModeProperties = SDL_malloc(sizeof(VkDisplayModePropertiesKHR) * displayModePropertiesCount); - if (displayModeProperties == NULL) { + if (!displayModeProperties) { SDL_OutOfMemory(); goto error; } @@ -347,7 +347,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display planes: %u", displayPlanePropertiesCount); displayPlaneProperties = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * displayPlanePropertiesCount); - if (displayPlaneProperties == NULL) { + if (!displayPlaneProperties) { SDL_OutOfMemory(); goto error; } @@ -378,7 +378,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of supported displays for plane %u: %u", i, planeSupportedDisplaysCount); planeSupportedDisplays = SDL_malloc(sizeof(VkDisplayKHR) * planeSupportedDisplaysCount); - if (planeSupportedDisplays == NULL) { + if (!planeSupportedDisplays) { SDL_free(displayPlaneProperties); SDL_OutOfMemory(); goto error; diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c index 151ef95e9cc51..6eb248bb66ceb 100644 --- a/src/video/SDL_yuv.c +++ b/src/video/SDL_yuv.c @@ -615,7 +615,7 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height, int tmp_pitch = (width * sizeof(Uint32)); tmp = SDL_malloc((size_t)tmp_pitch * height); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } @@ -996,7 +996,7 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height, int tmp_pitch = (width * sizeof(Uint32)); tmp = SDL_malloc((size_t)tmp_pitch * height); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } @@ -1085,7 +1085,7 @@ static int SDL_ConvertPixels_SwapUVPlanes(int width, int height, const void *src /* Allocate a temporary row for the swap */ tmp = (Uint8 *)SDL_malloc(UVwidth); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } for (y = 0; y < UVheight; ++y) { @@ -1321,7 +1321,7 @@ static int SDL_ConvertPixels_PackUVPlanes_to_NV_std(int width, int height, const if (src == dst) { /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch); @@ -1375,7 +1375,7 @@ static int SDL_ConvertPixels_SplitNV_to_UVPlanes_std(int width, int height, cons if (src == dst) { /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch); - if (tmp == NULL) { + if (!tmp) { return SDL_OutOfMemory(); } SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch); diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c index 3e38d85b1d91e..bc97260b1b776 100644 --- a/src/video/android/SDL_androidmouse.c +++ b/src/video/android/SDL_androidmouse.c @@ -88,7 +88,7 @@ static SDL_Cursor *Android_CreateCursor(SDL_Surface *surface, int hot_x, int hot SDL_Surface *converted; converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888); - if (converted == NULL) { + if (!converted) { return NULL; } custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y); @@ -117,7 +117,7 @@ static void Android_FreeCursor(SDL_Cursor *cursor) static SDL_Cursor *Android_CreateEmptyCursor() { - if (empty_cursor == NULL) { + if (!empty_cursor) { SDL_Surface *empty_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888); if (empty_surface) { SDL_memset(empty_surface->pixels, 0, (size_t)empty_surface->h * empty_surface->pitch); @@ -138,7 +138,7 @@ static void Android_DestroyEmptyCursor() static int Android_ShowCursor(SDL_Cursor *cursor) { - if (cursor == NULL) { + if (!cursor) { cursor = Android_CreateEmptyCursor(); } if (cursor) { @@ -215,7 +215,7 @@ void Android_OnMouse(SDL_Window *window, int state, int action, float x, float y int changes; Uint8 button; - if (window == NULL) { + if (!window) { return; } diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 18d9cd026394a..85e7e04cad29a 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -52,7 +52,7 @@ void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_fin SDL_TouchID touchDeviceId = 0; SDL_FingerID fingerId = 0; - if (window == NULL) { + if (!window) { return; } diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 96cc2d7edb869..1d6d0c282b1d2 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -86,13 +86,13 @@ static SDL_VideoDevice *Android_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (data == NULL) { + if (!data) { SDL_OutOfMemory(); SDL_free(device); return NULL; diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c index 1d1577cfff09f..9c18996f8c1e4 100644 --- a/src/video/android/SDL_androidvulkan.c +++ b/src/video/android/SDL_androidvulkan.c @@ -48,10 +48,10 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan loader library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { path = "libvulkan.so"; } _this->vulkan_config.loader_handle = SDL_LoadObject(path); @@ -76,7 +76,7 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) (PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } for (i = 0; i < extensionCount; i++) { diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 1ef9cd518269d..3f640fdaac09a 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -61,7 +61,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_SetKeyboardFocus(window); data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { retval = SDL_OutOfMemory(); goto endfunction; } @@ -129,7 +129,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL } data = window->driverdata; - if (data == NULL || !data->native_window) { + if (!data || !data->native_window) { if (data && !data->native_window) { SDL_SetError("Missing native window"); } diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index 5978d3b0a0c1e..d51b3c4085788 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -43,7 +43,7 @@ int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window /* Create a new framebuffer */ SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); - if (surface == NULL) { + if (!surface) { return -1; } @@ -61,7 +61,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window SDL_Surface *surface; surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE); - if (surface == NULL) { + if (!surface) { return SDL_SetError("Couldn't find dummy surface for window"); } diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index d2bd677beb2c4..6a85ac9800e26 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -83,7 +83,7 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index e25dff184d51c..18b36a79462cd 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -964,7 +964,7 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data) /* Keyboard events are awkward */ keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT); - if (keyElement == NULL) { + if (!keyElement) { keyElement = EMSCRIPTEN_EVENT_TARGET_WINDOW; } @@ -1007,7 +1007,7 @@ 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 == NULL) { + if (!target) { target = EMSCRIPTEN_EVENT_TARGET_WINDOW; } diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.c b/src/video/emscripten/SDL_emscriptenframebuffer.c index b620d554ecc8b..318a32305fe3c 100644 --- a/src/video/emscripten/SDL_emscriptenframebuffer.c +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c @@ -42,7 +42,7 @@ int Emscripten_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *windo SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); - if (surface == NULL) { + if (!surface) { return -1; } @@ -60,7 +60,7 @@ int Emscripten_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *windo SDL_WindowData *data = window->driverdata; surface = data->surface; - if (surface == NULL) { + if (!surface) { return SDL_SetError("Couldn't find framebuffer surface for window"); } diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c index 9aa794674ced9..1913c068698b9 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.c +++ b/src/video/emscripten/SDL_emscriptenmouse.c @@ -48,7 +48,7 @@ static SDL_Cursor *Emscripten_CreateCursorFromString(const char *cursor_str, SDL cursor = SDL_calloc(1, sizeof(SDL_Cursor)); if (cursor) { curdata = (Emscripten_CursorData *)SDL_calloc(1, sizeof(*curdata)); - if (curdata == NULL) { + if (!curdata) { SDL_OutOfMemory(); SDL_free(cursor); return NULL; @@ -78,7 +78,7 @@ static SDL_Cursor *Emscripten_CreateCursor(SDL_Surface *surface, int hot_x, int conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888); - if (conv_surf == NULL) { + if (!conv_surf) { return NULL; } @@ -175,7 +175,7 @@ static void Emscripten_FreeCursor(SDL_Cursor *cursor) if (cursor) { curdata = (Emscripten_CursorData *)cursor->driverdata; - if (curdata != NULL) { + if (curdata) { if (curdata->is_custom) { SDL_free((char *)curdata->system_cursor); } @@ -223,7 +223,7 @@ static int Emscripten_SetRelativeMouseMode(SDL_bool enabled) /* TODO: pointer lock isn't actually enabled yet */ if (enabled) { window = SDL_GetMouseFocus(); - if (window == NULL) { + if (!window) { return -1; } diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c index 6a40c24c95373..6f0cdd9df48fb 100644 --- a/src/video/emscripten/SDL_emscriptenopengles.c +++ b/src/video/emscripten/SDL_emscriptenopengles.c @@ -117,7 +117,7 @@ int Emscripten_GLES_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context) SDL_Window *window; /* remove the context from its window */ - for (window = _this->windows; window != NULL; window = window->next) { + for (window = _this->windows; window; window = window->next) { SDL_WindowData *window_data = window->driverdata; if (window_data->gl_context == context) { diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index b9a8c11d9991b..0c2209dd07544 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -61,7 +61,7 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } @@ -180,7 +180,7 @@ static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (wdata == NULL) { + if (!wdata) { return SDL_OutOfMemory(); } diff --git a/src/video/gdk/SDL_gdktextinput.cpp b/src/video/gdk/SDL_gdktextinput.cpp index 92485ecbe489b..b073198817f2a 100644 --- a/src/video/gdk/SDL_gdktextinput.cpp +++ b/src/video/gdk/SDL_gdktextinput.cpp @@ -63,7 +63,7 @@ static void SDLCALL GDK_InternalHintCallback( const char *oldValue, const char *newValue) { - if (userdata == NULL) { + if (!userdata) { return; } @@ -72,7 +72,7 @@ static void SDLCALL GDK_InternalHintCallback( if (userdata == &g_TextInputScope || userdata == &g_MaxTextLength) { /* int32 hint */ - Sint32 intValue = (newValue == NULL || newValue[0] == '\0') ? 0 : SDL_atoi(newValue); + Sint32 intValue = (!newValue || newValue[0] == '\0') ? 0 : SDL_atoi(newValue); if (userdata == &g_MaxTextLength && intValue <= 0) { intValue = g_DefaultMaxTextLength; } else if (userdata == &g_TextInputScope && intValue < 0) { @@ -82,13 +82,13 @@ static void SDLCALL GDK_InternalHintCallback( *(Sint32 *)userdata = intValue; } else { /* string hint */ - if (newValue == NULL || newValue[0] == '\0') { + if (!newValue || newValue[0] == '\0') { /* treat empty or NULL strings as just NULL for this impl */ SDL_free(*(char **)userdata); *(char **)userdata = NULL; } else { char *newString = SDL_strdup(newValue); - if (newString == NULL) { + if (!newString) { /* couldn't strdup, oh well */ SDL_OutOfMemory(); } else { @@ -102,7 +102,7 @@ static void SDLCALL GDK_InternalHintCallback( static int GDK_InternalEnsureTaskQueue(void) { - if (g_TextTaskQueue == NULL) { + if (!g_TextTaskQueue) { if (SDL_GDKGetTaskQueue(&g_TextTaskQueue) < 0) { /* SetError will be done for us. */ return -1; @@ -128,7 +128,7 @@ static void CALLBACK GDK_InternalTextEntryCallback(XAsyncBlock *asyncBlock) } else if (resultSize > 0) { /* +1 to be super sure that the buffer will be null terminated */ resultBuffer = (char *)SDL_calloc(sizeof(*resultBuffer), 1 + (size_t)resultSize); - if (resultBuffer == NULL) { + if (!resultBuffer) { SDL_OutOfMemory(); } else { /* still pass the original size that we got from ResultSize */ @@ -251,7 +251,7 @@ void GDK_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) HRESULT hR = S_OK; - if (g_TextBlock != NULL) { + if (g_TextBlock) { /* already showing the keyboard */ return; } @@ -262,7 +262,7 @@ void GDK_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) } g_TextBlock = (XAsyncBlock *)SDL_calloc(1, sizeof(*g_TextBlock)); - if (g_TextBlock == NULL) { + if (!g_TextBlock) { SDL_OutOfMemory(); return; } @@ -285,7 +285,7 @@ void GDK_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) void GDK_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) { - if (g_TextBlock != NULL) { + if (g_TextBlock) { XAsyncCancel(g_TextBlock); /* the completion callback will free the block */ } diff --git a/src/video/haiku/SDL_bclipboard.cc b/src/video/haiku/SDL_bclipboard.cc index 8bc1558404c20..5759482680eae 100644 --- a/src/video/haiku/SDL_bclipboard.cc +++ b/src/video/haiku/SDL_bclipboard.cc @@ -64,7 +64,7 @@ char *HAIKU_GetClipboardText(SDL_VideoDevice *_this) { be_clipboard->Unlock(); } - if (text == NULL) { + if (!text) { result = SDL_strdup(""); } else { /* Copy the data and pass on to SDL */ diff --git a/src/video/haiku/SDL_bframebuffer.cc b/src/video/haiku/SDL_bframebuffer.cc index 0151c72c53075..f519650b46982 100644 --- a/src/video/haiku/SDL_bframebuffer.cc +++ b/src/video/haiku/SDL_bframebuffer.cc @@ -94,7 +94,7 @@ int HAIKU_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, int HAIKU_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, const SDL_Rect * rects, int numrects) { - if (window == NULL) { + if (!window) { return 0; } diff --git a/src/video/haiku/SDL_bmessagebox.cc b/src/video/haiku/SDL_bmessagebox.cc index 3709f2c0a0118..84d2d5f6135d0 100644 --- a/src/video/haiku/SDL_bmessagebox.cc +++ b/src/video/haiku/SDL_bmessagebox.cc @@ -356,15 +356,15 @@ int HAIKU_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid // "You need a valid BApplication object before interacting with the app_server." // "2 BApplication objects were created. Only one is allowed." std::unique_ptr application; - if (be_app == NULL) { + if (!be_app) { application = std::unique_ptr(new(std::nothrow) BApplication(SDL_signature)); - if (application == NULL) { + if (!application) { return SDL_SetError("Cannot create the BApplication object. Lack of memory?"); } } HAIKU_SDL_MessageBox *SDL_MessageBox = new(std::nothrow) HAIKU_SDL_MessageBox(messageboxdata); - if (SDL_MessageBox == NULL) { + if (!SDL_MessageBox) { return SDL_SetError("Cannot create the HAIKU_SDL_MessageBox (BAlert inheritor) object. Lack of memory?"); } const int closeButton = SDL_MessageBox->GetCloseButtonId(); diff --git a/src/video/haiku/SDL_bopengl.cc b/src/video/haiku/SDL_bopengl.cc index 52f2ed9c42dd7..7a2f7335a017e 100644 --- a/src/video/haiku/SDL_bopengl.cc +++ b/src/video/haiku/SDL_bopengl.cc @@ -65,7 +65,7 @@ int HAIKU_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) SDL_FunctionPointer HAIKU_GL_GetProcAddress(SDL_VideoDevice *_this, const char *proc) { - if (_this->gl_config.dll_handle != NULL) { + if (_this->gl_config.dll_handle) { void *location = NULL; status_t err; if ((err = @@ -92,8 +92,8 @@ int HAIKU_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window * window) { int HAIKU_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window * window, SDL_GLContext context) { BGLView* glView = (BGLView*)context; // printf("HAIKU_GL_MakeCurrent(%llx), win = %llx, thread = %d\n", (uint64)context, (uint64)window, find_thread(NULL)); - if (glView != NULL) { - if ((glView->Window() == NULL) || (window == NULL) || (_ToBeWin(window)->GetGLView() != glView)) { + if (glView) { + if ((glView->Window() == NULL) || (!window) || (_ToBeWin(window)->GetGLView() != glView)) { return SDL_SetError("MakeCurrent failed"); } } @@ -146,7 +146,7 @@ int HAIKU_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context) { // printf("HAIKU_GL_DeleteContext(%llx), thread = %d\n", (uint64)context, find_thread(NULL)); BGLView* glView = (BGLView*)context; SDL_BWin *bwin = (SDL_BWin*)glView->Window(); - if (bwin == NULL) { + if (!bwin) { delete glView; } else { bwin->RemoveGLView(); diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 86b8037d531b0..b97ee5a01c24a 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -184,7 +184,7 @@ static SDL_Cursor * HAIKU_CreateCursor(SDL_Surface * surface, int hot_x, int hot SDL_Surface *converted; converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888); - if (converted == NULL) { + if (!converted) { return NULL; } @@ -206,7 +206,7 @@ static int HAIKU_ShowCursor(SDL_Cursor *cursor) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return 0; } @@ -225,7 +225,7 @@ static int HAIKU_ShowCursor(SDL_Cursor *cursor) static int HAIKU_SetRelativeMouseMode(SDL_bool enabled) { SDL_Window *window = SDL_GetMouseFocus(); - if (window == NULL) { + if (!window) { return 0; } @@ -245,7 +245,7 @@ static int HAIKU_SetRelativeMouseMode(SDL_bool enabled) static void HAIKU_MouseInit(SDL_VideoDevice *_this) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return; } mouse->CreateCursor = HAIKU_CreateCursor; diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index f69bec1f67e03..bb99a0fb995ca 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -65,7 +65,7 @@ static int _InitWindow(SDL_VideoDevice *_this, SDL_Window *window) { } SDL_BWin *bwin = new(std::nothrow) SDL_BWin(bounds, look, flags); - if (bwin == NULL) { + if (!bwin) { return -1; } diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.c b/src/video/kmsdrm/SDL_kmsdrmdyn.c index a5416c48b8d85..e37e2c3e930b6 100644 --- a/src/video/kmsdrm/SDL_kmsdrmdyn.c +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.c @@ -49,22 +49,22 @@ static void *KMSDRM_GetSym(const char *fnname, int *pHasModule) int i; void *fn = NULL; for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].lib != NULL) { + if (kmsdrmlibs[i].lib) { fn = SDL_LoadFunction(kmsdrmlibs[i].lib, fnname); - if (fn != NULL) { + if (fn) { break; } } } #if DEBUG_DYNAMIC_KMSDRM - if (fn != NULL) + if (fn) SDL_Log("KMSDRM: Found '%s' in %s (%p)\n", fnname, kmsdrmlibs[i].libname, fn); else SDL_Log("KMSDRM: Symbol '%s' NOT FOUND!\n", fnname); #endif - if (fn == NULL) { + if (!fn) { *pHasModule = 0; /* kill this module. */ } @@ -98,7 +98,7 @@ void SDL_KMSDRM_UnloadSymbols(void) #ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].lib != NULL) { + if (kmsdrmlibs[i].lib) { SDL_UnloadObject(kmsdrmlibs[i].lib); kmsdrmlibs[i].lib = NULL; } @@ -119,7 +119,7 @@ int SDL_KMSDRM_LoadSymbols(void) int i; int *thismod = NULL; for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].libname != NULL) { + if (kmsdrmlibs[i].libname) { kmsdrmlibs[i].lib = SDL_LoadObject(kmsdrmlibs[i].libname); } } diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c index 962802cefe572..1e092726aa02e 100644 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.c +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c @@ -147,7 +147,7 @@ static int KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor) int i; int ret; - if (curdata == NULL || !dispdata->cursor_bo) { + if (!curdata || !dispdata->cursor_bo) { return SDL_SetError("Cursor or display not initialized properly."); } @@ -158,7 +158,7 @@ static int KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor) ready_buffer = (uint8_t *)SDL_calloc(1, bufsize); - if (ready_buffer == NULL) { + if (!ready_buffer) { ret = SDL_OutOfMemory(); goto cleanup; } @@ -236,12 +236,12 @@ static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_ ret = NULL; cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); - if (cursor == NULL) { + if (!cursor) { SDL_OutOfMemory(); goto cleanup; } curdata = (KMSDRM_CursorData *)SDL_calloc(1, sizeof(*curdata)); - if (curdata == NULL) { + if (!curdata) { SDL_OutOfMemory(); goto cleanup; } @@ -277,7 +277,7 @@ static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_ ret = cursor; cleanup: - if (ret == NULL) { + if (!ret) { if (curdata) { if (curdata->buffer) { SDL_free(curdata->buffer); @@ -305,13 +305,13 @@ static int KMSDRM_ShowCursor(SDL_Cursor *cursor) /* Get the mouse focused window, if any. */ mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return SDL_SetError("No mouse."); } window = mouse->focus; - if (window == NULL || cursor == NULL) { + if (!window || !cursor) { /* If no window is focused by mouse or cursor is NULL, since we have no window (no mouse->focus) and hence we have no display, we simply hide mouse on all displays. diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c index 1df556e23a98d..30ad56d163320 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -142,7 +142,7 @@ int KMSDRM_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Get an actual usable fb for the next front buffer. */ fb_info = KMSDRM_FBFromBO(_this, windata->next_bo); - if (fb_info == NULL) { + if (!fb_info) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get a framebuffer"); return 0; } diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 643a469d86d7c..9aee16dae53ca 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -86,7 +86,7 @@ static int get_driindex(void) SDL_strlcpy(device, kmsdrm_dri_path, sizeof(device)); folder = opendir(device); - if (folder == NULL) { + if (!folder) { SDL_SetError("Failed to open directory '%s'", device); return -ENOENT; } @@ -124,7 +124,7 @@ static int get_driindex(void) KMSDRM_drmModeGetConnector( drm_fd, resources->connectors[i]); - if (conn == NULL) { + if (!conn) { continue; } @@ -260,13 +260,13 @@ static SDL_VideoDevice *KMSDRM_CreateDevice(void) } device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } viddata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (viddata == NULL) { + if (!viddata) { SDL_OutOfMemory(); goto cleanup; } @@ -364,7 +364,7 @@ KMSDRM_FBInfo *KMSDRM_FBFromBO(SDL_VideoDevice *_this, struct gbm_bo *bo) when the backing buffer is destroyed */ fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo)); - if (fb_info == NULL) { + if (!fb_info) { SDL_OutOfMemory(); return NULL; } @@ -689,7 +689,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto /* Reserve memory for the new display's driverdata. */ dispdata = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); - if (dispdata == NULL) { + if (!dispdata) { ret = SDL_OutOfMemory(); goto cleanup; } @@ -710,7 +710,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto for (i = 0; i < resources->count_encoders; i++) { encoder = KMSDRM_drmModeGetEncoder(viddata->drm_fd, resources->encoders[i]); - if (encoder == NULL) { + if (!encoder) { continue; } @@ -722,13 +722,13 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto encoder = NULL; } - if (encoder == NULL) { + if (!encoder) { /* No encoder was connected, find the first supported one */ for (i = 0; i < resources->count_encoders; i++) { encoder = KMSDRM_drmModeGetEncoder(viddata->drm_fd, resources->encoders[i]); - if (encoder == NULL) { + if (!encoder) { continue; } @@ -747,7 +747,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto } } - if (encoder == NULL) { + if (!encoder) { ret = SDL_SetError("No connected encoder found for connector."); goto cleanup; } @@ -757,7 +757,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto /* If no CRTC was connected to the encoder, find the first CRTC that is supported by the encoder, and use that. */ - if (crtc == NULL) { + if (!crtc) { for (i = 0; i < resources->count_crtcs; i++) { if (encoder->possible_crtcs & (1 << i)) { encoder->crtc_id = resources->crtcs[i]; @@ -767,7 +767,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto } } - if (crtc == NULL) { + if (!crtc) { ret = SDL_SetError("No CRTC found for connector."); goto cleanup; } @@ -852,7 +852,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto There's no problem with it being still incomplete. */ modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (modedata == NULL) { + if (!modedata) { ret = SDL_OutOfMemory(); goto cleanup; } @@ -924,7 +924,7 @@ static int KMSDRM_InitDisplays(SDL_VideoDevice *_this) /* Get all of the available connectors / devices / crtcs */ resources = KMSDRM_drmModeGetResources(viddata->drm_fd); - if (resources == NULL) { + if (!resources) { ret = SDL_SetError("drmModeGetResources(%d) failed", viddata->drm_fd); goto cleanup; } @@ -935,7 +935,7 @@ static int KMSDRM_InitDisplays(SDL_VideoDevice *_this) drmModeConnector *connector = KMSDRM_drmModeGetConnector(viddata->drm_fd, resources->connectors[i]); - if (connector == NULL) { + if (!connector) { continue; } @@ -1351,7 +1351,7 @@ int KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL return 0; } - if (modedata == NULL) { + if (!modedata) { return SDL_SetError("Mode doesn't have an associated index"); } @@ -1374,7 +1374,7 @@ void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_bool is_vulkan = window->flags & SDL_WINDOW_VULKAN; /* Is this a VK window? */ unsigned int i, j; - if (windata == NULL) { + if (!windata) { return; } @@ -1458,7 +1458,7 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (windata == NULL) { + if (!windata) { return SDL_OutOfMemory(); } diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index 038bd2db92dcb..c30d9fe98c61e 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -55,10 +55,10 @@ int KMSDRM_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { path = DEFAULT_VULKAN; } @@ -92,7 +92,7 @@ int KMSDRM_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 46fe98ea073a0..502594d66d814 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -53,7 +53,7 @@ int SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_GetWindowSizeInPixels(window, &w, &h); framebuffer = SDL_CreateSurface(w, h, FRAMEBUFFER_FORMAT); - if (framebuffer == NULL) { + if (!framebuffer) { return SDL_OutOfMemory(); } @@ -73,7 +73,7 @@ int SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, u32 bufsize; surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE); - if (surface == NULL) { + if (!surface) { return SDL_SetError("%s: Unable to get the window surface.", __func__); } diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c index 74b52071a0722..409713e77c99d 100644 --- a/src/video/n3ds/SDL_n3dsvideo.c +++ b/src/video/n3ds/SDL_n3dsvideo.c @@ -55,7 +55,7 @@ static void N3DS_DeleteDevice(SDL_VideoDevice *device) static SDL_VideoDevice *N3DS_CreateDevice(void) { SDL_VideoDevice *device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } @@ -104,7 +104,7 @@ static int AddN3DSDisplay(gfxScreen_t screen) SDL_DisplayMode mode; SDL_VideoDisplay display; SDL_DisplayData *display_driver_data = SDL_calloc(1, sizeof(SDL_DisplayData)); - if (display_driver_data == NULL) { + if (!display_driver_data) { return SDL_OutOfMemory(); } @@ -139,7 +139,7 @@ static int N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *displ { SDL_DisplayData *driver_data = display->driverdata; - if (driver_data == NULL) { + if (!driver_data) { return -1; } @@ -154,7 +154,7 @@ static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_DisplayData *display_data; SDL_WindowData *window_data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (window_data == NULL) { + if (!window_data) { return SDL_OutOfMemory(); } display_data = SDL_GetDisplayDriverDataForWindow(window); @@ -166,7 +166,7 @@ static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) { - if (window == NULL) { + if (!window) { return; } SDL_free(window->driverdata); diff --git a/src/video/ngage/SDL_ngageframebuffer.cpp b/src/video/ngage/SDL_ngageframebuffer.cpp index a4072f7fcc283..bc4612a77512e 100644 --- a/src/video/ngage/SDL_ngageframebuffer.cpp +++ b/src/video/ngage/SDL_ngageframebuffer.cpp @@ -57,7 +57,7 @@ int SDL_NGAGE_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window /* Create a new one */ SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); - if (surface == NULL) { + if (!surface) { return -1; } @@ -149,7 +149,7 @@ int SDL_NGAGE_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window SDL_Surface *surface; surface = (SDL_Surface *)SDL_GetWindowData(window, NGAGE_SURFACE); - if (surface == NULL) { + if (!surface) { return SDL_SetError("Couldn't find ngage surface for window"); } diff --git a/src/video/ngage/SDL_ngagevideo.cpp b/src/video/ngage/SDL_ngagevideo.cpp index 739b20106b408..d9af15d27616a 100644 --- a/src/video/ngage/SDL_ngagevideo.cpp +++ b/src/video/ngage/SDL_ngagevideo.cpp @@ -104,14 +104,14 @@ static SDL_VideoDevice *NGAGE_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } /* Initialize internal N-Gage specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (phdata == NULL) { + if (!phdata) { SDL_OutOfMemory(); SDL_free(device); return 0; diff --git a/src/video/ngage/SDL_ngagewindow.cpp b/src/video/ngage/SDL_ngagewindow.cpp index 5772e3e25bdef..d8ee898ae2550 100644 --- a/src/video/ngage/SDL_ngagewindow.cpp +++ b/src/video/ngage/SDL_ngagewindow.cpp @@ -36,7 +36,7 @@ int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) { NGAGE_Window *ngage_window = (NGAGE_Window *)SDL_calloc(1, sizeof(NGAGE_Window)); - if (ngage_window == NULL) { + if (!ngage_window) { return SDL_OutOfMemory(); } diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index 7dea25a905dcd..cd9604f657916 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -43,7 +43,7 @@ int SDL_OFFSCREEN_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi /* Create a new framebuffer */ SDL_GetWindowSizeInPixels(window, &w, &h); surface = SDL_CreateSurface(w, h, surface_format); - if (surface == NULL) { + if (!surface) { return -1; } @@ -62,7 +62,7 @@ int SDL_OFFSCREEN_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi SDL_Surface *surface; surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE); - if (surface == NULL) { + if (!surface) { return SDL_SetError("Couldn't find offscreen surface for window"); } diff --git a/src/video/offscreen/SDL_offscreenvideo.c b/src/video/offscreen/SDL_offscreenvideo.c index 613340843ba0c..f4955862a834d 100644 --- a/src/video/offscreen/SDL_offscreenvideo.c +++ b/src/video/offscreen/SDL_offscreenvideo.c @@ -56,7 +56,7 @@ static SDL_VideoDevice *OFFSCREEN_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } diff --git a/src/video/offscreen/SDL_offscreenwindow.c b/src/video/offscreen/SDL_offscreenwindow.c index d105e8347e21b..7a8ce759ff638 100644 --- a/src/video/offscreen/SDL_offscreenwindow.c +++ b/src/video/offscreen/SDL_offscreenwindow.c @@ -31,7 +31,7 @@ int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *offscreen_window = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (offscreen_window == NULL) { + if (!offscreen_window) { return SDL_OutOfMemory(); } diff --git a/src/video/ps2/SDL_ps2video.c b/src/video/ps2/SDL_ps2video.c index caaab5efa4e86..5d003834c556a 100644 --- a/src/video/ps2/SDL_ps2video.c +++ b/src/video/ps2/SDL_ps2video.c @@ -95,7 +95,7 @@ static SDL_VideoDevice *PS2_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 5cf0d7288d55d..637d9c138570d 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -51,21 +51,21 @@ static SDL_VideoDevice *PSP_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } /* Initialize internal PSP specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (phdata == NULL) { + if (!phdata) { SDL_OutOfMemory(); SDL_free(device); return NULL; } gldata = (SDL_GLDriverData *)SDL_calloc(1, sizeof(SDL_GLDriverData)); - if (gldata == NULL) { + if (!gldata) { SDL_OutOfMemory(); SDL_free(device); SDL_free(phdata); @@ -192,7 +192,7 @@ int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (wdata == NULL) { + if (!wdata) { return SDL_OutOfMemory(); } diff --git a/src/video/qnx/SDL_qnxgl.c b/src/video/qnx/SDL_qnxgl.c index 91df47dfb1e0f..35a4d68ead9c2 100644 --- a/src/video/qnx/SDL_qnxgl.c +++ b/src/video/qnx/SDL_qnxgl.c @@ -84,7 +84,7 @@ int glGetConfig(EGLConfig *pconf, int *pformat) // Allocate enough memory for all configurations. egl_configs = SDL_malloc(egl_num_configs * sizeof(*egl_configs)); - if (egl_configs == NULL) { + if (!egl_configs) { return -1; } diff --git a/src/video/qnx/SDL_qnxvideo.c b/src/video/qnx/SDL_qnxvideo.c index 429f053b49e47..ea32e7d5e6aa8 100644 --- a/src/video/qnx/SDL_qnxvideo.c +++ b/src/video/qnx/SDL_qnxvideo.c @@ -74,7 +74,7 @@ static int createWindow(SDL_VideoDevice *_this, SDL_Window *window) int usage; impl = SDL_calloc(1, sizeof(*impl)); - if (impl == NULL) { + if (!impl) { return -1; } @@ -310,7 +310,7 @@ static SDL_VideoDevice *createDevice() SDL_VideoDevice *device; device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { return NULL; } diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index e188b37c78c00..1d915270c27dd 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -65,12 +65,12 @@ static SDL_Cursor *RPI_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) SDL_assert(surface->pitch == surface->w * 4); cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); - if (cursor == NULL) { + if (!cursor) { SDL_OutOfMemory(); return NULL; } curdata = (RPI_CursorData *)SDL_calloc(1, sizeof(*curdata)); - if (curdata == NULL) { + if (!curdata) { SDL_OutOfMemory(); SDL_free(cursor); return NULL; @@ -113,12 +113,12 @@ static int RPI_ShowCursor(SDL_Cursor *cursor) const char *env; mouse = SDL_GetMouse(); - if (mouse == NULL) { + if (!mouse) { return -1; } if (cursor != global_cursor) { - if (global_cursor != NULL) { + if (global_cursor) { curdata = (RPI_CursorData *)global_cursor->driverdata; if (curdata && curdata->element > DISPMANX_NO_HANDLE) { update = vc_dispmanx_update_start(0); @@ -133,21 +133,21 @@ static int RPI_ShowCursor(SDL_Cursor *cursor) global_cursor = cursor; } - if (cursor == NULL) { + if (!cursor) { return 0; } curdata = (RPI_CursorData *)cursor->driverdata; - if (curdata == NULL) { + if (!curdata) { return -1; } - if (mouse->focus == NULL) { + if (!mouse->focus) { return -1; } data = SDL_GetDisplayDriverDataForWindow(mouse->focus); - if (data == NULL) { + if (!data) { return -1; } @@ -188,10 +188,10 @@ static void RPI_FreeCursor(SDL_Cursor *cursor) DISPMANX_UPDATE_HANDLE_T update; RPI_CursorData *curdata; - if (cursor != NULL) { + if (cursor) { curdata = (RPI_CursorData *)cursor->driverdata; - if (curdata != NULL) { + if (curdata) { if (curdata->element != DISPMANX_NO_HANDLE) { update = vc_dispmanx_update_start(0); SDL_assert(update); @@ -224,7 +224,7 @@ static int RPI_WarpMouseGlobalGraphically(float x, float y) VC_RECT_T src_rect; SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) { + if (!mouse || !mouse->cur_cursor || !mouse->cur_cursor->driverdata) { return 0; } @@ -273,7 +273,7 @@ static int RPI_WarpMouseGlobal(float x, float y) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) { + if (!mouse || !mouse->cur_cursor || !mouse->cur_cursor->driverdata) { return 0; } diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 3d5d0888b4383..e48bc1e68f3bf 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -76,14 +76,14 @@ static SDL_VideoDevice *RPI_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } /* Initialize internal data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (phdata == NULL) { + if (!phdata) { SDL_OutOfMemory(); SDL_free(device); return NULL; @@ -170,7 +170,7 @@ static void AddDispManXDisplay(const int display_id) /* Allocate display internal data */ data = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); - if (data == NULL) { + if (!data) { vc_dispmanx_display_close(handle); return; /* oh well */ } @@ -236,7 +236,7 @@ int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (wdata == NULL) { + if (!wdata) { return SDL_OutOfMemory(); } display = SDL_GetVideoDisplayForWindow(window); diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c index 6fe8ec1a35df1..1f53f85af4b81 100644 --- a/src/video/riscos/SDL_riscosframebuffer.c +++ b/src/video/riscos/SDL_riscosframebuffer.c @@ -80,7 +80,7 @@ int RISCOS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, U regs.r[5] = h; regs.r[6] = sprite_mode; error = _kernel_swi(OS_SpriteOp, ®s, ®s); - if (error != NULL) { + if (error) { SDL_free(driverdata->fb_area); return SDL_SetError("Unable to create sprite: %s (%i)", error->errmess, error->errnum); } @@ -106,7 +106,7 @@ int RISCOS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, c regs.r[6] = 0; regs.r[7] = 0; error = _kernel_swi(OS_SpriteOp, ®s, ®s); - if (error != NULL) { + if (error) { return SDL_SetError("OS_SpriteOp 52 failed: %s (%i)", error->errmess, error->errnum); } diff --git a/src/video/riscos/SDL_riscosmodes.c b/src/video/riscos/SDL_riscosmodes.c index f9d906bb9c739..d5cb447528e1c 100644 --- a/src/video/riscos/SDL_riscosmodes.c +++ b/src/video/riscos/SDL_riscosmodes.c @@ -167,7 +167,7 @@ static void *convert_mode_block(const int *block) } dst = SDL_malloc(40); - if (dst == NULL) { + if (!dst) { return NULL; } @@ -208,7 +208,7 @@ int RISCOS_InitModes(SDL_VideoDevice *_this) regs.r[0] = 1; error = _kernel_swi(OS_ScreenMode, ®s, ®s); - if (error != NULL) { + if (error) { return SDL_SetError("Unable to retrieve the current screen mode: %s (%i)", error->errmess, error->errnum); } @@ -241,19 +241,19 @@ int RISCOS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) regs.r[6] = 0; regs.r[7] = 0; error = _kernel_swi(OS_ScreenMode, ®s, ®s); - if (error != NULL) { + if (error) { return SDL_SetError("Unable to enumerate screen modes: %s (%i)", error->errmess, error->errnum); } block = SDL_malloc(-regs.r[7]); - if (block == NULL) { + if (!block) { return SDL_OutOfMemory(); } regs.r[6] = (int)block; regs.r[7] = -regs.r[7]; error = _kernel_swi(OS_ScreenMode, ®s, ®s); - if (error != NULL) { + if (error) { SDL_free(block); return SDL_SetError("Unable to enumerate screen modes: %s (%i)", error->errmess, error->errnum); } @@ -292,7 +292,7 @@ int RISCOS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL regs.r[0] = 0; regs.r[1] = (int)mode->driverdata; error = _kernel_swi(OS_ScreenMode, ®s, ®s); - if (error != NULL) { + if (error) { return SDL_SetError("Unable to set the current screen mode: %s (%i)", error->errmess, error->errnum); } diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c index a2df367f994df..d132abdb80f9c 100644 --- a/src/video/riscos/SDL_riscosvideo.c +++ b/src/video/riscos/SDL_riscosvideo.c @@ -54,14 +54,14 @@ static SDL_VideoDevice *RISCOS_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } /* Initialize internal data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (phdata == NULL) { + if (!phdata) { SDL_OutOfMemory(); SDL_free(device); return NULL; diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c index b0a3a207a50e3..bd192c3ceaa10 100644 --- a/src/video/riscos/SDL_riscoswindow.c +++ b/src/video/riscos/SDL_riscoswindow.c @@ -33,7 +33,7 @@ int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_WindowData *driverdata; driverdata = (SDL_WindowData *)SDL_calloc(1, sizeof(*driverdata)); - if (driverdata == NULL) { + if (!driverdata) { return SDL_OutOfMemory(); } driverdata->window = window; @@ -51,7 +51,7 @@ void RISCOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *driverdata = window->driverdata; - if (driverdata == NULL) { + if (!driverdata) { return; } diff --git a/src/video/vita/SDL_vitaframebuffer.c b/src/video/vita/SDL_vitaframebuffer.c index ef505d75e2025..7fb566727b7e9 100644 --- a/src/video/vita/SDL_vitaframebuffer.c +++ b/src/video/vita/SDL_vitaframebuffer.c @@ -103,7 +103,7 @@ void VITA_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->driverdata; - if (data == NULL) { + if (!data) { /* The window wasn't fully initialized */ return; } diff --git a/src/video/vita/SDL_vitagl_pvr.c b/src/video/vita/SDL_vitagl_pvr.c index af9897e59aec6..6e34054a9e6b4 100644 --- a/src/video/vita/SDL_vitagl_pvr.c +++ b/src/video/vita/SDL_vitagl_pvr.c @@ -51,8 +51,8 @@ int VITA_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) char *default_path = "app0:module"; char target_path[MAX_PATH]; - if (skip_init == NULL) { // we don't care about actual value - if (override != NULL) { + if (!skip_init) { // we don't care about actual value + if (override) { default_path = override; } diff --git a/src/video/vita/SDL_vitagles_pvr.c b/src/video/vita/SDL_vitagles_pvr.c index c862d6cae6a43..71cd5d92f2a65 100644 --- a/src/video/vita/SDL_vitagles_pvr.c +++ b/src/video/vita/SDL_vitagles_pvr.c @@ -40,9 +40,9 @@ int VITA_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) char *default_path = "app0:module"; char target_path[MAX_PATH]; - if (skip_init == NULL) { // we don't care about actual value + if (!skip_init) { // we don't care about actual value - if (override != NULL) { + if (override) { default_path = override; } diff --git a/src/video/vita/SDL_vitakeyboard.c b/src/video/vita/SDL_vitakeyboard.c index f92762420f6bc..106100a8073aa 100644 --- a/src/video/vita/SDL_vitakeyboard.c +++ b/src/video/vita/SDL_vitakeyboard.c @@ -48,7 +48,7 @@ void VITA_InitKeyboard(void) void VITA_PollKeyboard(void) { // We skip polling keyboard if no window is created - if (Vita_Window == NULL) { + if (!Vita_Window) { return; } diff --git a/src/video/vita/SDL_vitamouse.c b/src/video/vita/SDL_vitamouse.c index 88dd01876bc9a..1030adaa671aa 100644 --- a/src/video/vita/SDL_vitamouse.c +++ b/src/video/vita/SDL_vitamouse.c @@ -42,7 +42,7 @@ void VITA_InitMouse(void) void VITA_PollMouse(void) { // We skip polling mouse if no window is created - if (Vita_Window == NULL) { + if (!Vita_Window) { return; } diff --git a/src/video/vita/SDL_vitatouch.c b/src/video/vita/SDL_vitatouch.c index cef1ffc9cf768..58c2d5f79378e 100644 --- a/src/video/vita/SDL_vitatouch.c +++ b/src/video/vita/SDL_vitatouch.c @@ -84,7 +84,7 @@ void VITA_PollTouch(void) int port; // We skip polling touch if no window is created - if (Vita_Window == NULL) { + if (!Vita_Window) { return; } diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 3b59a3662a7d5..f3fd1f94bc1e2 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -67,14 +67,14 @@ static SDL_VideoDevice *VITA_Create() #endif /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } /* Initialize internal VITA specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (phdata == NULL) { + if (!phdata) { SDL_OutOfMemory(); SDL_free(device); return NULL; @@ -82,7 +82,7 @@ static SDL_VideoDevice *VITA_Create() #ifdef SDL_VIDEO_VITA_PIB gldata = (SDL_GLDriverData *)SDL_calloc(1, sizeof(SDL_GLDriverData)); - if (gldata == NULL) { + if (!gldata) { SDL_OutOfMemory(); SDL_free(device); SDL_free(phdata); @@ -231,7 +231,7 @@ int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (wdata == NULL) { + if (!wdata) { return SDL_OutOfMemory(); } @@ -239,7 +239,7 @@ int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) window->driverdata = wdata; // Vita can only have one window - if (Vita_Window != NULL) { + if (Vita_Window) { return SDL_SetError("Only one window supported"); } diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index 69eef0a349966..fa507571c8a3f 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -48,14 +48,14 @@ static SDL_VideoDevice *VIVANTE_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } /* Initialize internal data */ data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (data == NULL) { + if (!data) { SDL_OutOfMemory(); SDL_free(device); return NULL; @@ -124,7 +124,7 @@ static int VIVANTE_AddVideoDisplays(SDL_VideoDevice *_this) unsigned long pixels = 0; data = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } @@ -248,7 +248,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Allocate window internal data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c index a8fcb0ff65895..29416e6032064 100644 --- a/src/video/vivante/SDL_vivantevulkan.c +++ b/src/video/vivante/SDL_vivantevulkan.c @@ -46,10 +46,10 @@ int VIVANTE_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan loader library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { /* If no path set, try Vivante fb vulkan driver explicitly */ path = "libvulkan-fb.so"; _this->vulkan_config.loader_handle = SDL_LoadObject(path); @@ -83,7 +83,7 @@ int VIVANTE_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) (PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } for (i = 0; i < extensionCount; i++) { diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c index 75c358809c186..097852e8f9990 100644 --- a/src/video/wayland/SDL_waylandclipboard.c +++ b/src/video/wayland/SDL_waylandclipboard.c @@ -35,7 +35,7 @@ int Wayland_SetClipboardData(SDL_VideoDevice *_this) SDL_WaylandDataDevice *data_device = NULL; int status = 0; - if (video_data->input != NULL && video_data->input->data_device != NULL) { + if (video_data->input && video_data->input->data_device) { data_device = video_data->input->data_device; if (_this->clipboard_callback && _this->clipboard_mime_types) { @@ -60,7 +60,7 @@ void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, si SDL_WaylandDataDevice *data_device = NULL; void *buffer = NULL; - if (video_data->input != NULL && video_data->input->data_device != NULL) { + if (video_data->input && video_data->input->data_device) { data_device = video_data->input->data_device; if (data_device->selection_source) { buffer = SDL_GetInternalClipboardData(_this, mime_type, length); @@ -78,9 +78,9 @@ SDL_bool Wayland_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type) SDL_WaylandDataDevice *data_device = NULL; SDL_bool result = SDL_FALSE; - if (video_data->input != NULL && video_data->input->data_device != NULL) { + if (video_data->input && video_data->input->data_device) { data_device = video_data->input->data_device; - if (data_device->selection_source != NULL) { + if (data_device->selection_source) { result = SDL_HasInternalClipboardData(_this, mime_type); } else { result = Wayland_data_offer_has_mime(data_device->selection_offer, mime_type); @@ -109,7 +109,7 @@ int Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text) SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL; int status = -1; - if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) { + if (video_data->input && video_data->input->primary_selection_device) { primary_selection_device = video_data->input->primary_selection_device; if (text[0] != '\0') { SDL_WaylandPrimarySelectionSource *source = Wayland_primary_selection_source_create(_this); @@ -137,16 +137,16 @@ char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this) char *text = NULL; size_t length = 0; - if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) { + if (video_data->input && video_data->input->primary_selection_device) { primary_selection_device = video_data->input->primary_selection_device; - if (primary_selection_device->selection_source != NULL) { + if (primary_selection_device->selection_source) { text = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source, TEXT_MIME, &length); } else if (Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, TEXT_MIME)) { text = Wayland_primary_selection_offer_receive(primary_selection_device->selection_offer, TEXT_MIME, &length); } } - if (text == NULL) { + if (!text) { text = SDL_strdup(""); } @@ -159,9 +159,9 @@ SDL_bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this) SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL; SDL_bool result = SDL_FALSE; - if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) { + if (video_data->input && video_data->input->primary_selection_device) { primary_selection_device = video_data->input->primary_selection_device; - if (primary_selection_device->selection_source != NULL) { + if (primary_selection_device->selection_source) { result = SDL_TRUE; } else { result = Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, TEXT_MIME); diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index ed24ddeab9a4c..00da373058061 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -112,13 +112,13 @@ static ssize_t read_pipe(int fd, void **buffer, size_t *total_length) new_buffer_length = *total_length + sizeof(Uint32); - if (*buffer == NULL) { + if (!*buffer) { output_buffer = SDL_malloc(new_buffer_length); } else { output_buffer = SDL_realloc(*buffer, new_buffer_length); } - if (output_buffer == NULL) { + if (!output_buffer) { bytes_read = SDL_OutOfMemory(); } else { SDL_memcpy((Uint8 *)output_buffer + pos, temp, bytes_read); @@ -155,9 +155,9 @@ static int mime_data_list_add(struct wl_list *list, SDL_MimeDataList *mime_data = NULL; void *internal_buffer = NULL; - if (buffer != NULL) { + if (buffer) { internal_buffer = SDL_malloc(length); - if (internal_buffer == NULL) { + if (!internal_buffer) { return SDL_OutOfMemory(); } SDL_memcpy(internal_buffer, buffer, length); @@ -165,16 +165,16 @@ static int mime_data_list_add(struct wl_list *list, mime_data = mime_data_list_find(list, mime_type); - if (mime_data == NULL) { + if (!mime_data) { mime_data = SDL_calloc(1, sizeof(*mime_data)); - if (mime_data == NULL) { + if (!mime_data) { status = SDL_OutOfMemory(); } else { WAYLAND_wl_list_insert(list, &(mime_data->link)); mime_type_length = SDL_strlen(mime_type) + 1; mime_data->mime_type = SDL_malloc(mime_type_length); - if (mime_data->mime_type == NULL) { + if (!mime_data->mime_type) { status = SDL_OutOfMemory(); } else { SDL_memcpy(mime_data->mime_type, mime_type, mime_type_length); @@ -182,8 +182,8 @@ static int mime_data_list_add(struct wl_list *list, } } - if (mime_data != NULL && buffer != NULL && length > 0) { - if (mime_data->data != NULL) { + if (mime_data && buffer && length > 0) { + if (mime_data->data) { SDL_free(mime_data->data); } mime_data->data = internal_buffer; @@ -202,10 +202,10 @@ static void mime_data_list_free(struct wl_list *list) wl_list_for_each_safe(mime_data, next, list, link) { - if (mime_data->data != NULL) { + if (mime_data->data) { SDL_free(mime_data->data); } - if (mime_data->mime_type != NULL) { + if (mime_data->mime_type) { SDL_free(mime_data->mime_type); } SDL_free(mime_data); @@ -216,7 +216,7 @@ static size_t Wayland_send_data(const void *data, size_t length, int fd) { size_t result = 0; - if (length > 0 && data != NULL) { + if (length > 0 && data) { while (write_pipe(fd, data, length, &result) > 0) { /* Just keep spinning */ } @@ -276,9 +276,9 @@ void Wayland_primary_selection_source_set_callback(SDL_WaylandPrimarySelectionSo static void *Wayland_clone_data_buffer(const void *buffer, size_t *len) { void *clone = NULL; - if (*len > 0 && buffer != NULL) { + if (*len > 0 && buffer) { clone = SDL_malloc((*len)+sizeof(Uint32)); - if (clone == NULL) { + if (!clone) { SDL_OutOfMemory(); } else { SDL_memcpy(clone, buffer, *len); @@ -295,9 +295,9 @@ void *Wayland_data_source_get_data(SDL_WaylandDataSource *source, const void *internal_buffer; *length = 0; - if (source == NULL) { + if (!source) { SDL_SetError("Invalid data source"); - } else if (source->callback != NULL) { + } else if (source->callback) { internal_buffer = source->callback(source->userdata.data, mime_type, length); buffer = Wayland_clone_data_buffer(internal_buffer, length); } @@ -312,7 +312,7 @@ void *Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSourc const void *internal_buffer; *length = 0; - if (source == NULL) { + if (!source) { SDL_SetError("Invalid primary selection source"); } else if (source->callback) { internal_buffer = source->callback(source->userdata.data, mime_type, length); @@ -324,7 +324,7 @@ void *Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSourc void Wayland_data_source_destroy(SDL_WaylandDataSource *source) { - if (source != NULL) { + if (source) { SDL_WaylandDataDevice *data_device = (SDL_WaylandDataDevice *)source->data_device; if (data_device && (data_device->selection_source == source)) { data_device->selection_source = NULL; @@ -341,7 +341,7 @@ void Wayland_data_source_destroy(SDL_WaylandDataSource *source) void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource *source) { - if (source != NULL) { + if (source) { SDL_WaylandPrimarySelectionDevice *primary_selection_device = (SDL_WaylandPrimarySelectionDevice *)source->primary_selection_device; if (primary_selection_device && (primary_selection_device->selection_source == source)) { primary_selection_device->selection_source = NULL; @@ -363,12 +363,12 @@ void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer, void *buffer = NULL; *length = 0; - if (offer == NULL) { + if (!offer) { SDL_SetError("Invalid data offer"); return NULL; } data_device = offer->data_device; - if (data_device == NULL) { + if (!data_device) { SDL_SetError("Data device not initialized"); } else if (pipe2(pipefd, O_CLOEXEC | O_NONBLOCK) == -1) { SDL_SetError("Could not read pipe"); @@ -396,12 +396,12 @@ void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer * void *buffer = NULL; *length = 0; - if (offer == NULL) { + if (!offer) { SDL_SetError("Invalid data offer"); return NULL; } primary_selection_device = offer->primary_selection_device; - if (primary_selection_device == NULL) { + if (!primary_selection_device) { SDL_SetError("Primary selection device not initialized"); } else if (pipe2(pipefd, O_CLOEXEC | O_NONBLOCK) == -1) { SDL_SetError("Could not read pipe"); @@ -437,7 +437,7 @@ SDL_bool Wayland_data_offer_has_mime(SDL_WaylandDataOffer *offer, { SDL_bool found = SDL_FALSE; - if (offer != NULL) { + if (offer) { found = mime_data_list_find(&offer->mimes, mime_type) != NULL; } return found; @@ -448,7 +448,7 @@ SDL_bool Wayland_primary_selection_offer_has_mime(SDL_WaylandPrimarySelectionOff { SDL_bool found = SDL_FALSE; - if (offer != NULL) { + if (offer) { found = mime_data_list_find(&offer->mimes, mime_type) != NULL; } return found; @@ -456,7 +456,7 @@ SDL_bool Wayland_primary_selection_offer_has_mime(SDL_WaylandPrimarySelectionOff void Wayland_data_offer_destroy(SDL_WaylandDataOffer *offer) { - if (offer != NULL) { + if (offer) { wl_data_offer_destroy(offer->offer); mime_data_list_free(&offer->mimes); SDL_free(offer); @@ -465,7 +465,7 @@ void Wayland_data_offer_destroy(SDL_WaylandDataOffer *offer) void Wayland_primary_selection_offer_destroy(SDL_WaylandPrimarySelectionOffer *offer) { - if (offer != NULL) { + if (offer) { zwp_primary_selection_offer_v1_destroy(offer->offer); mime_data_list_free(&offer->mimes); SDL_free(offer); @@ -476,9 +476,9 @@ int Wayland_data_device_clear_selection(SDL_WaylandDataDevice *data_device) { int status = 0; - if (data_device == NULL || data_device->data_device == NULL) { + if (!data_device || !data_device->data_device) { status = SDL_SetError("Invalid Data Device"); - } else if (data_device->selection_source != NULL) { + } else if (data_device->selection_source) { wl_data_device_set_selection(data_device->data_device, NULL, 0); Wayland_data_source_destroy(data_device->selection_source); data_device->selection_source = NULL; @@ -490,9 +490,9 @@ int Wayland_primary_selection_device_clear_selection(SDL_WaylandPrimarySelection { int status = 0; - if (primary_selection_device == NULL || primary_selection_device->primary_selection_device == NULL) { + if (!primary_selection_device || !primary_selection_device->primary_selection_device) { status = SDL_SetError("Invalid Primary Selection Device"); - } else if (primary_selection_device->selection_source != NULL) { + } else if (primary_selection_device->selection_source) { zwp_primary_selection_device_v1_set_selection(primary_selection_device->primary_selection_device, NULL, 0); Wayland_primary_selection_source_destroy(primary_selection_device->selection_source); @@ -508,9 +508,9 @@ int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device, { int status = 0; - if (data_device == NULL) { + if (!data_device) { status = SDL_SetError("Invalid Data Device"); - } else if (source == NULL) { + } else if (!source) { status = SDL_SetError("Invalid source"); } else { size_t index = 0; @@ -532,7 +532,7 @@ int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device, source->source, data_device->selection_serial); } - if (data_device->selection_source != NULL) { + if (data_device->selection_source) { Wayland_data_source_destroy(data_device->selection_source); } data_device->selection_source = source; @@ -550,9 +550,9 @@ int Wayland_primary_selection_device_set_selection(SDL_WaylandPrimarySelectionDe { int status = 0; - if (primary_selection_device == NULL) { + if (!primary_selection_device) { status = SDL_SetError("Invalid Primary Selection Device"); - } else if (source == NULL) { + } else if (!source) { status = SDL_SetError("Invalid source"); } else { size_t index = 0; @@ -573,7 +573,7 @@ int Wayland_primary_selection_device_set_selection(SDL_WaylandPrimarySelectionDe source->source, primary_selection_device->selection_serial); } - if (primary_selection_device->selection_source != NULL) { + if (primary_selection_device->selection_source) { Wayland_primary_selection_source_destroy(primary_selection_device->selection_source); } primary_selection_device->selection_source = source; @@ -588,11 +588,11 @@ int Wayland_data_device_set_serial(SDL_WaylandDataDevice *data_device, uint32_t serial) { int status = -1; - if (data_device != NULL) { + if (data_device) { status = 0; /* If there was no serial and there is a pending selection set it now. */ - if (data_device->selection_serial == 0 && data_device->selection_source != NULL) { + if (data_device->selection_serial == 0 && data_device->selection_source) { wl_data_device_set_selection(data_device->data_device, data_device->selection_source->source, data_device->selection_serial); @@ -608,11 +608,11 @@ int Wayland_primary_selection_device_set_serial(SDL_WaylandPrimarySelectionDevic uint32_t serial) { int status = -1; - if (primary_selection_device != NULL) { + if (primary_selection_device) { status = 0; /* If there was no serial and there is a pending selection set it now. */ - if (primary_selection_device->selection_serial == 0 && primary_selection_device->selection_source != NULL) { + if (primary_selection_device->selection_serial == 0 && primary_selection_device->selection_source) { zwp_primary_selection_device_v1_set_selection(primary_selection_device->primary_selection_device, primary_selection_device->selection_source->source, primary_selection_device->selection_serial); diff --git a/src/video/wayland/SDL_waylanddyn.c b/src/video/wayland/SDL_waylanddyn.c index dde99bf4d3e04..7d4dce5c8a1e1 100644 --- a/src/video/wayland/SDL_waylanddyn.c +++ b/src/video/wayland/SDL_waylanddyn.c @@ -56,23 +56,23 @@ static void *WAYLAND_GetSym(const char *fnname, int *pHasModule, SDL_bool requir void *fn = NULL; waylanddynlib *dynlib; for (dynlib = waylandlibs; dynlib->libname; dynlib++) { - if (dynlib->lib != NULL) { + if (dynlib->lib) { fn = SDL_LoadFunction(dynlib->lib, fnname); - if (fn != NULL) { + if (fn) { break; } } } #if DEBUG_DYNAMIC_WAYLAND - if (fn != NULL) { + if (fn) { SDL_Log("WAYLAND: Found '%s' in %s (%p)\n", fnname, dynlib->libname, fn); } else { SDL_Log("WAYLAND: Symbol '%s' NOT FOUND!\n", fnname); } #endif - if (fn == NULL && required) { + if (!fn && required) { *pHasModule = 0; /* kill this module. */ } @@ -112,7 +112,7 @@ void SDL_WAYLAND_UnloadSymbols(void) #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) { - if (waylandlibs[i].lib != NULL) { + if (waylandlibs[i].lib) { SDL_UnloadObject(waylandlibs[i].lib); waylandlibs[i].lib = NULL; } @@ -133,7 +133,7 @@ int SDL_WAYLAND_LoadSymbols(void) int i; int *thismod = NULL; for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) { - if (waylandlibs[i].libname != NULL) { + if (waylandlibs[i].libname) { waylandlibs[i].lib = SDL_LoadObject(waylandlibs[i].libname); } } diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index e5b0e0a833bc6..7d3fab4efee08 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -360,7 +360,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) WAYLAND_wl_display_flush(d->display); #ifdef SDL_USE_IME - if (d->text_input_manager == NULL && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (!d->text_input_manager && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { SDL_IME_PumpEvents(); } #endif @@ -433,7 +433,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this) int err; #ifdef SDL_USE_IME - if (d->text_input_manager == NULL && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (!d->text_input_manager && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { SDL_IME_PumpEvents(); } #endif @@ -507,7 +507,7 @@ static void pointer_handle_enter(void *data, struct wl_pointer *pointer, struct SDL_WaylandInput *input = data; SDL_WindowData *window; - if (surface == NULL) { + if (!surface) { /* enter event for a window we've just destroyed */ return; } @@ -549,7 +549,7 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer, { struct SDL_WaylandInput *input = data; - if (surface == NULL || !SDL_WAYLAND_own_surface(surface)) { + if (!surface || !SDL_WAYLAND_own_surface(surface)) { return; } @@ -1097,7 +1097,7 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, char *map_str; const char *locale; - if (data == NULL) { + if (!data) { close(fd); return; } @@ -1170,11 +1170,11 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, /* Look up the preferred locale, falling back to "C" as default */ locale = SDL_getenv("LC_ALL"); - if (locale == NULL) { + if (!locale) { locale = SDL_getenv("LC_CTYPE"); - if (locale == NULL) { + if (!locale) { locale = SDL_getenv("LANG"); - if (locale == NULL) { + if (!locale) { locale = "C"; } } @@ -1378,7 +1378,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, SDL_WindowData *window; uint32_t *key; - if (surface == NULL) { + if (!surface) { /* enter event for a window we've just destroyed */ return; } @@ -1431,7 +1431,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, struct SDL_WaylandInput *input = data; SDL_WindowData *window; - if (surface == NULL || !SDL_WAYLAND_own_surface(surface)) { + if (!surface || !SDL_WAYLAND_own_surface(surface)) { return; } @@ -1462,7 +1462,7 @@ static SDL_bool keyboard_input_get_text(char text[8], const struct SDL_WaylandIn const xkb_keysym_t *syms; xkb_keysym_t sym; - if (window == NULL || window->keyboard_device != input || !input->xkb.state) { + if (!window || window->keyboard_device != input || !input->xkb.state) { return SDL_FALSE; } @@ -1682,7 +1682,7 @@ static void data_source_handle_send(void *data, struct wl_data_source *wl_data_s static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source) { SDL_WaylandDataSource *source = data; - if (source != NULL) { + if (source) { Wayland_data_source_destroy(source); } } @@ -1732,21 +1732,21 @@ SDL_WaylandDataSource *Wayland_data_source_create(SDL_VideoDevice *_this) SDL_VideoData *driver_data = NULL; struct wl_data_source *id = NULL; - if (_this == NULL || _this->driverdata == NULL) { + if (!_this || !_this->driverdata) { SDL_SetError("Video driver uninitialized"); } else { driver_data = _this->driverdata; - if (driver_data->data_device_manager != NULL) { + if (driver_data->data_device_manager) { id = wl_data_device_manager_create_data_source( driver_data->data_device_manager); } - if (id == NULL) { + if (!id) { SDL_SetError("Wayland unable to create data source"); } else { data_source = SDL_calloc(1, sizeof(*data_source)); - if (data_source == NULL) { + if (!data_source) { SDL_OutOfMemory(); wl_data_source_destroy(id); } else { @@ -1766,21 +1766,21 @@ SDL_WaylandPrimarySelectionSource *Wayland_primary_selection_source_create(SDL_V SDL_VideoData *driver_data = NULL; struct zwp_primary_selection_source_v1 *id = NULL; - if (_this == NULL || _this->driverdata == NULL) { + if (!_this || !_this->driverdata) { SDL_SetError("Video driver uninitialized"); } else { driver_data = _this->driverdata; - if (driver_data->primary_selection_device_manager != NULL) { + if (driver_data->primary_selection_device_manager) { id = zwp_primary_selection_device_manager_v1_create_source( driver_data->primary_selection_device_manager); } - if (id == NULL) { + if (!id) { SDL_SetError("Wayland unable to create primary selection source"); } else { primary_selection_source = SDL_calloc(1, sizeof(*primary_selection_source)); - if (primary_selection_source == NULL) { + if (!primary_selection_source) { SDL_OutOfMemory(); zwp_primary_selection_source_v1_destroy(id); } else { @@ -1833,7 +1833,7 @@ static void data_device_handle_data_offer(void *data, struct wl_data_device *wl_ SDL_WaylandDataOffer *data_offer = NULL; data_offer = SDL_calloc(1, sizeof(*data_offer)); - if (data_offer == NULL) { + if (!data_offer) { SDL_OutOfMemory(); } else { data_offer->offer = id; @@ -1854,7 +1854,7 @@ static void data_device_handle_enter(void *data, struct wl_data_device *wl_data_ data_device->drag_serial = serial; - if (id != NULL) { + if (id) { data_device->drag_offer = wl_data_offer_get_user_data(id); /* TODO: SDL Support more mime types */ @@ -1900,7 +1900,7 @@ static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_ { SDL_WaylandDataDevice *data_device = data; - if (data_device->drag_offer != NULL) { + if (data_device->drag_offer) { Wayland_data_offer_destroy(data_device->drag_offer); data_device->drag_offer = NULL; } @@ -1911,7 +1911,7 @@ static void data_device_handle_motion(void *data, struct wl_data_device *wl_data { SDL_WaylandDataDevice *data_device = data; - if (data_device->drag_offer != NULL && data_device->dnd_window) { + if (data_device->drag_offer && data_device->dnd_window) { const float dx = (float)wl_fixed_to_double(x); const float dy = (float)wl_fixed_to_double(y); @@ -1942,7 +1942,7 @@ static int Wayland_URIDecode(char *buf, int len) { int ri, wi, di; char decode = '\0'; - if (buf == NULL || len < 0) { + if (!buf || len < 0) { errno = EINVAL; return -1; } @@ -2020,7 +2020,7 @@ static char *Wayland_URIToLocal(char *uri) /* got a hostname? */ if (!local && uri[0] == '/' && uri[2] != '/') { char *hostname_end = SDL_strchr(uri + 1, '/'); - if (hostname_end != NULL) { + if (hostname_end) { char hostname[257]; if (gethostname(hostname, 255) == 0) { hostname[256] = '\0'; @@ -2048,7 +2048,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d { SDL_WaylandDataDevice *data_device = data; - if (data_device->drag_offer != NULL && data_device->dnd_window) { + if (data_device->drag_offer && data_device->dnd_window) { /* TODO: SDL Support more mime types */ size_t length; SDL_bool drop_handled = SDL_FALSE; @@ -2081,13 +2081,13 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d * non paths that are not visible to the application */ if (!drop_handled && Wayland_data_offer_has_mime( - data_device->drag_offer, FILE_MIME)) { + data_device->drag_offer, FILE_MIME)) { void *buffer = Wayland_data_offer_receive(data_device->drag_offer, FILE_MIME, &length); if (buffer) { char *saveptr = NULL; char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr); - while (token != NULL) { + while (token) { char *fn = Wayland_URIToLocal(token); if (fn) { SDL_SendDropFile(data_device->dnd_window, NULL, fn); @@ -2116,7 +2116,7 @@ static void data_device_handle_selection(void *data, struct wl_data_device *wl_d SDL_WaylandDataDevice *data_device = data; SDL_WaylandDataOffer *offer = NULL; - if (id != NULL) { + if (id) { offer = wl_data_offer_get_user_data(id); } @@ -2143,7 +2143,7 @@ static void primary_selection_device_handle_offer(void *data, struct zwp_primary SDL_WaylandPrimarySelectionOffer *primary_selection_offer = NULL; primary_selection_offer = SDL_calloc(1, sizeof(*primary_selection_offer)); - if (primary_selection_offer == NULL) { + if (!primary_selection_offer) { SDL_OutOfMemory(); } else { primary_selection_offer->offer = id; @@ -2160,7 +2160,7 @@ static void primary_selection_device_handle_selection(void *data, struct zwp_pri SDL_WaylandPrimarySelectionDevice *primary_selection_device = data; SDL_WaylandPrimarySelectionOffer *offer = NULL; - if (id != NULL) { + if (id) { offer = zwp_primary_selection_offer_v1_get_user_data(id); } @@ -2270,7 +2270,7 @@ static void Wayland_create_data_device(SDL_VideoData *d) SDL_WaylandDataDevice *data_device = NULL; data_device = SDL_calloc(1, sizeof(*data_device)); - if (data_device == NULL) { + if (!data_device) { return; } @@ -2278,7 +2278,7 @@ static void Wayland_create_data_device(SDL_VideoData *d) d->data_device_manager, d->input->seat); data_device->video_data = d; - if (data_device->data_device == NULL) { + if (!data_device->data_device) { SDL_free(data_device); } else { wl_data_device_set_user_data(data_device->data_device, data_device); @@ -2293,7 +2293,7 @@ static void Wayland_create_primary_selection_device(SDL_VideoData *d) SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL; primary_selection_device = SDL_calloc(1, sizeof(*primary_selection_device)); - if (primary_selection_device == NULL) { + if (!primary_selection_device) { return; } @@ -2301,7 +2301,7 @@ static void Wayland_create_primary_selection_device(SDL_VideoData *d) d->primary_selection_device_manager, d->input->seat); primary_selection_device->video_data = d; - if (primary_selection_device->primary_selection_device == NULL) { + if (!primary_selection_device->primary_selection_device) { SDL_free(primary_selection_device); } else { zwp_primary_selection_device_v1_set_user_data(primary_selection_device->primary_selection_device, @@ -2317,14 +2317,14 @@ static void Wayland_create_text_input(SDL_VideoData *d) SDL_WaylandTextInput *text_input = NULL; text_input = SDL_calloc(1, sizeof(*text_input)); - if (text_input == NULL) { + if (!text_input) { return; } text_input->text_input = zwp_text_input_manager_v3_get_text_input( d->text_input_manager, d->input->seat); - if (text_input->text_input == NULL) { + if (!text_input->text_input) { SDL_free(text_input); } else { zwp_text_input_v3_set_user_data(text_input->text_input, text_input); @@ -2338,7 +2338,7 @@ void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t ver { d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version)); - if (d->input != NULL) { + if (d->input) { Wayland_create_data_device(d); } } @@ -2347,7 +2347,7 @@ void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, { d->primary_selection_device_manager = wl_registry_bind(d->registry, id, &zwp_primary_selection_device_manager_v1_interface, 1); - if (d->input != NULL) { + if (d->input) { Wayland_create_primary_selection_device(d); } } @@ -2356,7 +2356,7 @@ void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t vers { d->text_input_manager = wl_registry_bind(d->registry, id, &zwp_text_input_manager_v3_interface, 1); - if (d->input != NULL) { + if (d->input) { Wayland_create_text_input(d); } } @@ -2396,7 +2396,7 @@ static void tablet_tool_handle_proximity_in(void *data, struct zwp_tablet_tool_v struct SDL_WaylandTabletInput *input = data; SDL_WindowData *window; - if (surface == NULL) { + if (!surface) { return; } @@ -2454,7 +2454,7 @@ static void tablet_tool_handle_down(void *data, struct zwp_tablet_tool_v2 *tool, SDL_WindowData *window = input->tool_focus; input->is_down = SDL_TRUE; Wayland_UpdateImplicitGrabSerial(input->sdlWaylandInput, serial); - if (window == NULL) { + if (!window) { /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd. * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still * received. To prevent SIGSEGV this returns when this is the case. @@ -2472,7 +2472,7 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 *tool) input->is_down = SDL_FALSE; - if (window == NULL) { + if (!window) { /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd. * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still * received. To prevent SIGSEGV this returns when this is the case. @@ -2588,7 +2588,7 @@ static struct SDL_WaylandTabletObjectListNode *tablet_object_list_new_node(void struct SDL_WaylandTabletObjectListNode *node; node = SDL_calloc(1, sizeof(*node)); - if (node == NULL) { + if (!node) { return NULL; } @@ -2600,7 +2600,7 @@ static struct SDL_WaylandTabletObjectListNode *tablet_object_list_new_node(void static void tablet_object_list_append(struct SDL_WaylandTabletObjectListNode *head, void *object) { - if (head->object == NULL) { + if (!head->object) { head->object = object; return; } @@ -2658,12 +2658,12 @@ void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_Wayland { struct SDL_WaylandTabletInput *tablet_input; - if (tablet_manager == NULL || input == NULL || !input->seat) { + if (!tablet_manager || !input || !input->seat) { return; } tablet_input = SDL_calloc(1, sizeof(*tablet_input)); - if (tablet_input == NULL) { + if (!tablet_input) { return; } @@ -2697,7 +2697,7 @@ void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version) struct SDL_WaylandInput *input; input = SDL_calloc(1, sizeof(*input)); - if (input == NULL) { + if (!input) { return; } @@ -2708,13 +2708,13 @@ void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version) input->xkb.current_group = XKB_GROUP_INVALID; d->input = input; - if (d->data_device_manager != NULL) { + if (d->data_device_manager) { Wayland_create_data_device(d); } - if (d->primary_selection_device_manager != NULL) { + if (d->primary_selection_device_manager) { Wayland_create_primary_selection_device(d); } - if (d->text_input_manager != NULL) { + if (d->text_input_manager) { Wayland_create_text_input(d); } @@ -2732,7 +2732,7 @@ void Wayland_display_destroy_input(SDL_VideoData *d) { struct SDL_WaylandInput *input = d->input; - if (input == NULL) { + if (!input) { return; } @@ -2746,15 +2746,15 @@ void Wayland_display_destroy_input(SDL_VideoData *d) zwp_input_timestamps_v1_destroy(input->touch_timestamps); } - if (input->data_device != NULL) { + if (input->data_device) { Wayland_data_device_clear_selection(input->data_device); - if (input->data_device->selection_offer != NULL) { + if (input->data_device->selection_offer) { Wayland_data_offer_destroy(input->data_device->selection_offer); } - if (input->data_device->drag_offer != NULL) { + if (input->data_device->drag_offer) { Wayland_data_offer_destroy(input->data_device->drag_offer); } - if (input->data_device->data_device != NULL) { + if (input->data_device->data_device) { if (wl_data_device_get_version(input->data_device->data_device) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION) { wl_data_device_release(input->data_device->data_device); } else { @@ -2764,20 +2764,20 @@ void Wayland_display_destroy_input(SDL_VideoData *d) SDL_free(input->data_device); } - if (input->primary_selection_device != NULL) { - if (input->primary_selection_device->selection_offer != NULL) { + if (input->primary_selection_device) { + if (input->primary_selection_device->selection_offer) { Wayland_primary_selection_offer_destroy(input->primary_selection_device->selection_offer); } - if (input->primary_selection_device->selection_source != NULL) { + if (input->primary_selection_device->selection_source) { Wayland_primary_selection_source_destroy(input->primary_selection_device->selection_source); } - if (input->primary_selection_device->primary_selection_device != NULL) { + if (input->primary_selection_device->primary_selection_device) { zwp_primary_selection_device_v1_destroy(input->primary_selection_device->primary_selection_device); } SDL_free(input->primary_selection_device); } - if (input->text_input != NULL) { + if (input->text_input) { zwp_text_input_v3_destroy(input->text_input->text_input); SDL_free(input->text_input); } @@ -3078,7 +3078,7 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi &confined_pointer_listener, window); - if (confine_rect != NULL) { + if (confine_rect) { wl_region_destroy(confine_rect); } diff --git a/src/video/wayland/SDL_waylandkeyboard.c b/src/video/wayland/SDL_waylandkeyboard.c index 3aa52f38f5558..17dc4f867e8c5 100644 --- a/src/video/wayland/SDL_waylandkeyboard.c +++ b/src/video/wayland/SDL_waylandkeyboard.c @@ -32,7 +32,7 @@ int Wayland_InitKeyboard(SDL_VideoDevice *_this) { #ifdef SDL_USE_IME SDL_VideoData *driverdata = _this->driverdata; - if (driverdata->text_input_manager == NULL) { + if (!driverdata->text_input_manager) { SDL_IME_Init(); } #endif @@ -45,7 +45,7 @@ void Wayland_QuitKeyboard(SDL_VideoDevice *_this) { #ifdef SDL_USE_IME SDL_VideoData *driverdata = _this->driverdata; - if (driverdata->text_input_manager == NULL) { + if (!driverdata->text_input_manager) { SDL_IME_Quit(); } #endif @@ -57,7 +57,7 @@ void Wayland_StartTextInput(SDL_VideoDevice *_this) if (driverdata->text_input_manager) { struct SDL_WaylandInput *input = driverdata->input; - if (input != NULL && input->text_input) { + if (input && input->text_input) { const SDL_Rect *rect = &input->text_input->cursor_rect; /* Don't re-enable if we're already enabled. */ @@ -98,7 +98,7 @@ void Wayland_StopTextInput(SDL_VideoDevice *_this) if (driverdata->text_input_manager) { struct SDL_WaylandInput *input = driverdata->input; - if (input != NULL && input->text_input) { + if (input && input->text_input) { zwp_text_input_v3_disable(input->text_input->text_input); zwp_text_input_v3_commit(input->text_input->text_input); input->text_input->is_enabled = SDL_FALSE; @@ -117,7 +117,7 @@ int Wayland_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) SDL_VideoData *driverdata = _this->driverdata; if (driverdata->text_input_manager) { struct SDL_WaylandInput *input = driverdata->input; - if (input != NULL && input->text_input) { + if (input && input->text_input) { if (!SDL_RectsEqual(rect, &input->text_input->cursor_rect)) { SDL_copyp(&input->text_input->cursor_rect, rect); zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input, diff --git a/src/video/wayland/SDL_waylandmessagebox.c b/src/video/wayland/SDL_waylandmessagebox.c index 790be39e87fd7..2fda9eef98d9e 100644 --- a/src/video/wayland/SDL_waylandmessagebox.c +++ b/src/video/wayland/SDL_waylandmessagebox.c @@ -91,7 +91,7 @@ static int get_zenity_version(int *major, int *minor) close(fd_pipe[1]); outputfp = fdopen(fd_pipe[0], "r"); - if (outputfp == NULL) { + if (!outputfp) { close(fd_pipe[0]); return SDL_SetError("failed to open pipe for reading: %s", strerror(errno)); } @@ -99,7 +99,7 @@ static int get_zenity_version(int *major, int *minor) version_ptr = fgets(version_str, ZENITY_VERSION_LEN, outputfp); (void)fclose(outputfp); /* will close underlying fd */ - if (version_ptr == NULL) { + if (!version_ptr) { return SDL_SetError("failed to read zenity version string"); } @@ -213,7 +213,7 @@ int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *button char *output = NULL; char *tmp = NULL; - if (buttonid == NULL) { + if (!buttonid) { /* if we don't need buttonid, we can return immediately */ close(fd_pipe[0]); return 0; /* success */ @@ -221,14 +221,14 @@ int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *button *buttonid = -1; output = SDL_malloc(output_len + 1); - if (output == NULL) { + if (!output) { close(fd_pipe[0]); return SDL_OutOfMemory(); } output[0] = '\0'; outputfp = fdopen(fd_pipe[0], "r"); - if (outputfp == NULL) { + if (!outputfp) { SDL_free(output); close(fd_pipe[0]); return SDL_SetError("Couldn't open pipe for reading: %s", strerror(errno)); @@ -236,20 +236,20 @@ int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *button tmp = fgets(output, output_len + 1, outputfp); (void)fclose(outputfp); - if ((tmp == NULL) || (*tmp == '\0') || (*tmp == '\n')) { + if ((!tmp) || (*tmp == '\0') || (*tmp == '\n')) { SDL_free(output); return 0; /* User simply closed the dialog */ } /* It likes to add a newline... */ tmp = SDL_strrchr(output, '\n'); - if (tmp != NULL) { + if (tmp) { *tmp = '\0'; } /* Check which button got pressed */ for (i = 0; i < messageboxdata->numbuttons; i += 1) { - if (messageboxdata->buttons[i].text != NULL) { + if (messageboxdata->buttons[i].text) { if (SDL_strcmp(output, messageboxdata->buttons[i].text) == 0) { *buttonid = messageboxdata->buttons[i].buttonid; break; diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 815c504381b98..8895e4cbc7394 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -215,7 +215,7 @@ static void Wayland_DBusInitCursorProperties(SDL_VideoData *vdata) SDL_DBusContext *dbus = SDL_DBus_GetContext(); SDL_bool add_filter = SDL_FALSE; - if (dbus == NULL) { + if (!dbus) { return; } @@ -279,7 +279,7 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa } /* First, find the appropriate theme based on the current scale... */ focus = SDL_GetMouse()->focus; - if (focus == NULL) { + if (!focus) { /* Nothing to see here, bail. */ return SDL_FALSE; } @@ -294,12 +294,12 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa break; } } - if (theme == NULL) { + if (!theme) { const char *xcursor_theme = dbus_cursor_theme; vdata->cursor_themes = SDL_realloc(vdata->cursor_themes, sizeof(SDL_WaylandCursorTheme) * (vdata->num_cursor_themes + 1)); - if (vdata->cursor_themes == NULL) { + if (!vdata->cursor_themes) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -382,7 +382,7 @@ static int wayland_create_tmp_file(off_t size) int fd; xdg_path = SDL_getenv("XDG_RUNTIME_DIR"); - if (xdg_path == NULL) { + if (!xdg_path) { return -1; } @@ -441,7 +441,7 @@ static int create_buffer_from_shm(Wayland_CursorData *d, return SDL_SetError("mmap() failed."); } - SDL_assert(d->shm_data != NULL); + SDL_assert(d->shm_data); shm_pool = wl_shm_create_pool(data->shm, shm_fd, size); d->buffer = wl_shm_pool_create_buffer(shm_pool, @@ -469,7 +469,7 @@ static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot SDL_VideoDevice *vd = SDL_GetVideoDevice(); SDL_VideoData *wd = vd->driverdata; Wayland_CursorData *data = SDL_calloc(1, sizeof(Wayland_CursorData)); - if (data == NULL) { + if (!data) { SDL_OutOfMemory(); SDL_free(cursor); return NULL; @@ -513,7 +513,7 @@ static SDL_Cursor *Wayland_CreateSystemCursor(SDL_SystemCursor id) cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { Wayland_CursorData *cdata = SDL_calloc(1, sizeof(Wayland_CursorData)); - if (cdata == NULL) { + if (!cdata) { SDL_OutOfMemory(); SDL_free(cursor); return NULL; @@ -556,7 +556,7 @@ static void Wayland_FreeCursorData(Wayland_CursorData *d) static void Wayland_FreeCursor(SDL_Cursor *cursor) { - if (cursor == NULL) { + if (!cursor) { return; } @@ -580,7 +580,7 @@ static int Wayland_ShowCursor(SDL_Cursor *cursor) struct wl_pointer *pointer = d->pointer; float scale = 1.0f; - if (pointer == NULL) { + if (!pointer) { return -1; } @@ -588,7 +588,7 @@ static int Wayland_ShowCursor(SDL_Cursor *cursor) Wayland_CursorData *data = cursor->driverdata; /* TODO: High-DPI custom cursors? -flibit */ - if (data->shm_data == NULL) { + if (!data->shm_data) { if (!wayland_get_system_cursor(d, data, &scale)) { return -1; } diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 96d7f390fd393..dfcf717c65a1c 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -140,13 +140,13 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) } display = WAYLAND_wl_display_connect(NULL); - if (display == NULL) { + if (!display) { SDL_WAYLAND_UnloadSymbols(); return NULL; } data = SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { WAYLAND_wl_display_disconnect(display); SDL_WAYLAND_UnloadSymbols(); SDL_OutOfMemory(); @@ -159,7 +159,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_free(data); WAYLAND_wl_display_disconnect(display); SDL_WAYLAND_UnloadSymbols(); @@ -414,7 +414,7 @@ static void display_handle_geometry(void *data, driverdata->physical_height = physical_height; /* The model is only used for the output name if wl_output or xdg-output haven't provided a description. */ - if (driverdata->display == 0 && driverdata->placeholder.name == NULL) { + if (driverdata->display == 0 && !driverdata->placeholder.name) { driverdata->placeholder.name = SDL_strdup(model); } @@ -573,7 +573,7 @@ static void display_handle_done(void *data, SDL_SetDesktopDisplayMode(dpy, &desktop_mode); /* Expose the unscaled, native resolution if the scale is 1.0 or viewports are available... */ - if (driverdata->scale_factor == 1.0f || video->viewporter != NULL) { + if (driverdata->scale_factor == 1.0f || video->viewporter) { SDL_AddFullscreenDisplayMode(dpy, &native_mode); } else { /* ...otherwise expose the integer scaled variants of the desktop resolution down to 1. */ @@ -650,7 +650,7 @@ static int Wayland_add_display(SDL_VideoData *d, uint32_t id, uint32_t version) SDL_DisplayData *data; output = wl_registry_bind(d->registry, id, &wl_output_interface, version); - if (output == NULL) { + if (!output) { return SDL_SetError("Failed to retrieve output."); } data = (SDL_DisplayData *)SDL_calloc(1, sizeof(*data)); @@ -858,7 +858,7 @@ int Wayland_VideoInit(SDL_VideoDevice *_this) } data->registry = wl_display_get_registry(data->display); - if (data->registry == NULL) { + if (!data->registry) { return SDL_SetError("Failed to get the Wayland registry"); } diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 75cef415f1dd4..a82a5fd9e2925 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -54,10 +54,10 @@ int Wayland_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan loader library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { path = DEFAULT_VULKAN; } _this->vulkan_config.loader_handle = SDL_LoadObject(path); @@ -82,7 +82,7 @@ int Wayland_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) (PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } for (i = 0; i < extensionCount; i++) { diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 7e00c63a3886e..91a82d7619706 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -114,7 +114,7 @@ static SDL_bool WindowNeedsViewport(SDL_Window *window) * - The surface scale is fractional. * - An exclusive fullscreen mode is being emulated and the mode does not match the requested output size. */ - if (video->viewporter != NULL) { + if (video->viewporter) { if (SurfaceScaleIsFractional(window)) { return SDL_TRUE; } else if (window->fullscreen_exclusive) { @@ -157,7 +157,7 @@ static void SetDrawSurfaceViewport(SDL_Window *window, int src_width, int src_he SDL_VideoData *video = wind->waylandData; if (video->viewporter) { - if (wind->draw_viewport == NULL) { + if (!wind->draw_viewport) { wind->draw_viewport = wp_viewporter_get_viewport(video->viewporter, wind->surface); } @@ -201,7 +201,7 @@ static void SetMinMaxDimensions(SDL_Window *window) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (!wind->shell_surface.libdecor.initial_configure_seen || wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.initial_configure_seen || !wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } /* No need to change these values if the window is non-resizable, @@ -417,7 +417,7 @@ static void ConfigureWindowGeometry(SDL_Window *window) /* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */ if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR && - viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) { + viddata->shell.xdg && data->shell_surface.xdg.surface) { xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height); } @@ -430,7 +430,7 @@ static void ConfigureWindowGeometry(SDL_Window *window) } /* Ensure that child popup windows are still in bounds. */ - for (SDL_Window *child = window->first_child; child != NULL; child = child->next_sibling) { + for (SDL_Window *child = window->first_child; child; child = child->next_sibling) { RepositionPopup(child); } @@ -486,7 +486,7 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } if (output) { @@ -570,7 +570,7 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time wind->surface_status = WAYLAND_SURFACE_STATUS_SHOWN; /* If any child windows are waiting on this window to be shown, show them now */ - for (SDL_Window *w = wind->sdlwindow->first_child; w != NULL; w = w->next_sibling) { + for (SDL_Window *w = wind->sdlwindow->first_child; w; w = w->next_sibling) { if (w->driverdata->surface_status == WAYLAND_SURFACE_STATUS_SHOW_PENDING) { Wayland_ShowWindow(SDL_GetVideoDevice(), w); } @@ -876,7 +876,7 @@ static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = { static void OverrideLibdecorLimits(SDL_Window *window) { #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR - if (libdecor_frame_get_min_content_size == NULL) { + if (!libdecor_frame_get_min_content_size) { libdecor_frame_set_min_content_size(window->driverdata->shell_surface.libdecor.frame, window->min_w, window->min_h); } #elif !defined(SDL_HAVE_LIBDECOR_VER_0_2_0) @@ -1287,7 +1287,7 @@ static void SetKeyboardFocus(SDL_Window *window) SDL_Window *topmost = window; /* Find the topmost parent */ - while (topmost->parent != NULL) { + while (topmost->parent) { topmost = topmost->parent; } @@ -1318,10 +1318,10 @@ int Wayland_SetWindowModalFor(SDL_VideoDevice *_this, SDL_Window *modal_window, #ifdef HAVE_LIBDECOR_H if (viddata->shell.libdecor) { - if (modal_data->shell_surface.libdecor.frame == NULL) { + if (!modal_data->shell_surface.libdecor.frame) { return SDL_SetError("Modal window was hidden"); } - if (parent_data->shell_surface.libdecor.frame == NULL) { + if (!parent_data->shell_surface.libdecor.frame) { return SDL_SetError("Parent window was hidden"); } libdecor_frame_set_parent(modal_data->shell_surface.libdecor.frame, @@ -1392,7 +1392,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) data->surface, &libdecor_frame_interface, data); - if (data->shell_surface.libdecor.frame == NULL) { + if (!data->shell_surface.libdecor.frame) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to create libdecor frame!"); } else { libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id); @@ -1572,11 +1572,11 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup) SDL_WindowData *popupdata; /* Basic sanity checks to weed out the weird popup closures */ - if (popup == NULL || popup->magic != &_this->window_magic) { + if (!popup || popup->magic != &_this->window_magic) { return; } popupdata = popup->driverdata; - if (popupdata == NULL) { + if (!popupdata) { return; } @@ -1590,7 +1590,7 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup) SDL_Window *new_focus = popup->parent; /* Find the highest level window that isn't being hidden or destroyed. */ - while (new_focus->parent != NULL && (new_focus->is_hiding || new_focus->is_destroying)) { + while (new_focus->parent && (new_focus->is_hiding || new_focus->is_destroying)) { new_focus = new_focus->parent; } @@ -1705,7 +1705,7 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *target_ struct wl_surface *requesting_surface = focus ? focus->driverdata->surface : NULL; if (data->activation_manager) { - if (target_wind->activation_token != NULL) { + if (target_wind->activation_token) { /* We're about to overwrite this with a new request */ xdg_activation_token_v1_destroy(target_wind->activation_token); } @@ -1722,7 +1722,7 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *target_ * * -flibit */ - if (requesting_surface != NULL) { + if (requesting_surface) { /* This specifies the surface from which the activation request is originating, not the activation target surface. */ xdg_activation_token_v1_set_surface(target_wind->activation_token, requesting_surface); } @@ -1803,7 +1803,7 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } libdecor_frame_unset_maximized(wind->shell_surface.libdecor.frame); @@ -1848,7 +1848,7 @@ void Wayland_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_ const SDL_WindowData *wind = window->driverdata; if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } if (libdecor_frame_has_capability(wind->shell_surface.libdecor.frame, LIBDECOR_ACTION_RESIZE)) { @@ -1883,7 +1883,7 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } libdecor_frame_set_maximized(wind->shell_surface.libdecor.frame); @@ -1914,7 +1914,7 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } libdecor_frame_set_minimized(wind->shell_surface.libdecor.frame); @@ -1981,7 +1981,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_VideoData *c; data = SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } @@ -2182,7 +2182,7 @@ void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (wind->shell_surface.libdecor.frame == NULL) { + if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } libdecor_frame_set_title(wind->shell_surface.libdecor.frame, title); diff --git a/src/video/windows/SDL_windowsclipboard.c b/src/video/windows/SDL_windowsclipboard.c index fabb3d6b3c9d9..bac510aaea17a 100644 --- a/src/video/windows/SDL_windowsclipboard.c +++ b/src/video/windows/SDL_windowsclipboard.c @@ -288,7 +288,7 @@ void *WIN_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t WIN_CloseClipboard(); } } - if (text == NULL) { + if (!text) { text = SDL_strdup(""); } data = text; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index cc6b1f63b0ee4..7a797561af73f 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -721,12 +721,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Get the window data for the window */ data = WIN_GetWindowDataFromHWND(hwnd); #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) - if (data == NULL) { + if (!data) { /* Fallback */ data = (SDL_WindowData *)GetProp(hwnd, TEXT("SDL_WindowData")); } #endif - if (data == NULL) { + if (!data) { return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam); } @@ -1280,7 +1280,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } /* Update the position of any child windows */ - for (win = data->window->first_child; win != NULL; win = win->next_sibling) { + for (win = data->window->first_child; win; win = win->next_sibling) { /* Don't update hidden child windows, their relative position doesn't change */ if (!(win->flags & SDL_WINDOW_HIDDEN)) { WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE); @@ -1783,8 +1783,10 @@ static void WIN_UpdateMouseCapture() SDL_MouseID mouseID = SDL_GetMouse()->mouseID; SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, mouseID, 0, (float)cursorPos.x, (float)cursorPos.y); - SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT); - SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT); + SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, + !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT); + SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, + !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT); SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE); SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1); SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2); @@ -1820,7 +1822,7 @@ int WIN_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) message_result = GetMessage(&msg, 0, 0, 0); } if (message_result) { - if (msg.message == WM_TIMER && msg.hwnd == NULL && msg.wParam == timer_id) { + if (msg.message == WM_TIMER && !msg.hwnd && msg.wParam == timer_id) { return 0; } if (g_WindowsMessageHook) { @@ -1919,7 +1921,7 @@ void WIN_PumpEvents(SDL_VideoDevice *_this) not grabbing the keyboard. Note: If we *are* grabbing the keyboard, GetKeyState() will return inaccurate results for VK_LWIN and VK_RWIN but we don't need it anyway. */ focusWindow = SDL_GetKeyboardFocus(); - if (focusWindow == NULL || !(focusWindow->flags & SDL_WINDOW_KEYBOARD_GRABBED)) { + if (!focusWindow || !(focusWindow->flags & SDL_WINDOW_KEYBOARD_GRABBED)) { if ((keystate[SDL_SCANCODE_LGUI] == SDL_PRESSED) && !(GetKeyState(VK_LWIN) & 0x8000)) { SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LGUI); } @@ -1973,8 +1975,8 @@ int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) ++app_registered; return 0; } - SDL_assert(SDL_Appname == NULL); - if (name == NULL) { + SDL_assert(!SDL_Appname); + if (!name) { name = "SDL_app"; #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC) style = (CS_BYTEALIGNCLIENT | CS_OWNDC); diff --git a/src/video/windows/SDL_windowsframebuffer.c b/src/video/windows/SDL_windowsframebuffer.c index aab98603a9fb9..9be7cc83b4278 100644 --- a/src/video/windows/SDL_windowsframebuffer.c +++ b/src/video/windows/SDL_windowsframebuffer.c @@ -114,7 +114,7 @@ void WIN_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->driverdata; - if (data == NULL) { + if (!data) { /* The window wasn't fully initialized */ return; } diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 3d5589543e37c..7f09c32ec5645 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -693,7 +693,7 @@ static void IME_SetupAPI(SDL_VideoData *videodata) } hime = SDL_LoadObject(ime_file); - if (hime == NULL) { + if (!hime) { return; } @@ -776,7 +776,7 @@ static void IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD length = ImmGetCompositionStringW(himc, string, NULL, 0); if (length > 0 && videodata->ime_composition_length < length) { - if (videodata->ime_composition != NULL) { + if (videodata->ime_composition) { SDL_free(videodata->ime_composition); } @@ -968,11 +968,11 @@ static int IME_ShowCandidateList(SDL_VideoData *videodata) videodata->ime_candcount = 0; candidates = SDL_realloc(videodata->ime_candidates, MAX_CANDSIZE); - if (candidates != NULL) { + if (candidates) { videodata->ime_candidates = (WCHAR *)candidates; } - if (videodata->ime_candidates == NULL) { + if (!videodata->ime_candidates) { return -1; } @@ -1186,7 +1186,7 @@ TSFSink_Release(TSFSink *sink) STDMETHODIMP UIElementSink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv) { - if (ppv == NULL) { + if (!ppv) { return E_INVALIDARG; } @@ -1223,7 +1223,7 @@ STDMETHODIMP UIElementSink_BeginUIElement(TSFSink *sink, DWORD dwUIElementId, BO ITfReadingInformationUIElement *preading = 0; ITfCandidateListUIElement *pcandlist = 0; SDL_VideoData *videodata = (SDL_VideoData *)sink->data; - if (element == NULL) { + if (!element) { return E_INVALIDARG; } @@ -1248,7 +1248,7 @@ STDMETHODIMP UIElementSink_UpdateUIElement(TSFSink *sink, DWORD dwUIElementId) ITfReadingInformationUIElement *preading = 0; ITfCandidateListUIElement *pcandlist = 0; SDL_VideoData *videodata = (SDL_VideoData *)sink->data; - if (element == NULL) { + if (!element) { return E_INVALIDARG; } @@ -1274,7 +1274,7 @@ STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId) ITfReadingInformationUIElement *preading = 0; ITfCandidateListUIElement *pcandlist = 0; SDL_VideoData *videodata = (SDL_VideoData *)sink->data; - if (element == NULL) { + if (!element) { return E_INVALIDARG; } @@ -1296,7 +1296,7 @@ STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId) STDMETHODIMP IPPASink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv) { - if (ppv == NULL) { + if (!ppv) { return E_INVALIDARG; } diff --git a/src/video/windows/SDL_windowsmessagebox.c b/src/video/windows/SDL_windowsmessagebox.c index b5459da5efd3a..689121c2a1e47 100644 --- a/src/video/windows/SDL_windowsmessagebox.c +++ b/src/video/windows/SDL_windowsmessagebox.c @@ -265,7 +265,7 @@ static INT_PTR CALLBACK MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wP if (GetButtonIndex(messageboxdata, SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, &buttonindex)) { /* Focus on the first default return-key button */ HWND buttonctl = GetDlgItem(hDlg, (int)(IDBUTTONINDEX0 + buttonindex)); - if (buttonctl == NULL) { + if (!buttonctl) { EndDialog(hDlg, IDINVALPTRDLGITEM); } PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)buttonctl, TRUE); @@ -276,7 +276,7 @@ static INT_PTR CALLBACK MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wP return FALSE; case WM_SETFOCUS: messageboxdata = (const SDL_MessageBoxData *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if (messageboxdata == NULL) { + if (!messageboxdata) { EndDialog(hDlg, IDINVALPTRSETFOCUS); return TRUE; } @@ -288,7 +288,7 @@ static INT_PTR CALLBACK MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wP return TRUE; case WM_COMMAND: messageboxdata = (const SDL_MessageBoxData *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if (messageboxdata == NULL) { + if (!messageboxdata) { EndDialog(hDlg, IDINVALPTRCOMMAND); return TRUE; } @@ -344,7 +344,7 @@ static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space) if (size > dialog->size) { void *data = SDL_realloc(dialog->data, size); - if (data == NULL) { + if (!data) { SDL_OutOfMemory(); return SDL_FALSE; } @@ -387,12 +387,12 @@ static SDL_bool AddDialogString(WIN_DialogData *dialog, const char *string) size_t count; SDL_bool status; - if (string == NULL) { + if (!string) { string = ""; } wstring = WIN_UTF8ToStringW(string); - if (wstring == NULL) { + if (!wstring) { return SDL_FALSE; } @@ -448,7 +448,7 @@ static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, if (!AddDialogData(dialog, &type, sizeof(type))) { return SDL_FALSE; } - if (type == DLGITEMTYPEBUTTON || (type == DLGITEMTYPESTATIC && caption != NULL)) { + if (type == DLGITEMTYPEBUTTON || (type == DLGITEMTYPESTATIC && caption)) { if (!AddDialogString(dialog, caption)) { return SDL_FALSE; } @@ -521,7 +521,7 @@ static WIN_DialogData *CreateDialogData(int w, int h, const char *caption) Vec2ToDLU(&dialogTemplate.cx, &dialogTemplate.cy); dialog = (WIN_DialogData *)SDL_calloc(1, sizeof(*dialog)); - if (dialog == NULL) { + if (!dialog) { return NULL; } @@ -623,7 +623,7 @@ static const char *EscapeAmpersands(char **dst, size_t *dstlen, const char *src) size_t ampcount = 0; size_t srclen = 0; - if (src == NULL) { + if (!src) { return NULL; } @@ -642,7 +642,7 @@ static const char *EscapeAmpersands(char **dst, size_t *dstlen, const char *src) if (SIZE_MAX - srclen < ampcount) { return NULL; } - if (*dst == NULL || *dstlen < srclen + ampcount) { + if (!*dst || *dstlen < srclen + ampcount) { /* Allocating extra space in case the next strings are a bit longer. */ size_t extraspace = SIZE_MAX - (srclen + ampcount); if (extraspace > 512) { @@ -652,7 +652,7 @@ static const char *EscapeAmpersands(char **dst, size_t *dstlen, const char *src) SDL_free(*dst); *dst = NULL; newdst = SDL_malloc(*dstlen); - if (newdst == NULL) { + if (!newdst) { return NULL; } *dst = newdst; @@ -817,7 +817,7 @@ static int WIN_ShowOldMessageBox(const SDL_MessageBoxData *messageboxdata, int * Size.cy += ButtonHeight + TextMargin; dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->title); - if (dialog == NULL) { + if (!dialog) { return -1; } @@ -858,7 +858,7 @@ static int WIN_ShowOldMessageBox(const SDL_MessageBoxData *messageboxdata, int * buttontext = EscapeAmpersands(&escape, &escapesize, sdlButton->text); /* Make sure to provide the correct ID to keep buttons indexed in the * same order as how they are in messageboxdata. */ - if (buttontext == NULL || !AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttontext, IDBUTTONINDEX0 + (int)(sdlButton - messageboxdata->buttons), isdefault)) { + if (!buttontext || !AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttontext, IDBUTTONINDEX0 + (int)(sdlButton - messageboxdata->buttons), isdefault)) { FreeDialogData(dialog); SDL_free(ampescape); return -1; @@ -932,7 +932,7 @@ int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) /* If we cannot load comctl32.dll use the old messagebox! */ hComctl32 = LoadLibrary(TEXT("comctl32.dll")); - if (hComctl32 == NULL) { + if (!hComctl32) { return WIN_ShowOldMessageBox(messageboxdata, buttonid); } @@ -944,7 +944,7 @@ int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") */ pfnTaskDialogIndirect = (TASKDIALOGINDIRECTPROC)GetProcAddress(hComctl32, "TaskDialogIndirect"); - if (pfnTaskDialogIndirect == NULL) { + if (!pfnTaskDialogIndirect) { FreeLibrary(hComctl32); return WIN_ShowOldMessageBox(messageboxdata, buttonid); } @@ -992,7 +992,7 @@ int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) pButton->nButtonID = IDBUTTONINDEX0 + i; } buttontext = EscapeAmpersands(&escape, &escapesize, messageboxdata->buttons[i].text); - if (buttontext == NULL) { + if (!buttontext) { int j; FreeLibrary(hComctl32); SDL_free(ampescape); diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index 714c6f6387d1e..1845c452bd4ff 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -203,7 +203,7 @@ static SDL_bool WIN_GetDisplayMode(SDL_VideoDevice *_this, HMONITOR hMonitor, LP } data = (SDL_DisplayModeData *)SDL_malloc(sizeof(*data)); - if (data == NULL) { + if (!data) { return SDL_FALSE; } @@ -251,7 +251,7 @@ static char *WIN_GetDisplayNameVista(const WCHAR *deviceName) LONG rc; dll = SDL_LoadObject("USER32.DLL"); - if (dll == NULL) { + if (!dll) { return NULL; } @@ -259,7 +259,7 @@ static char *WIN_GetDisplayNameVista(const WCHAR *deviceName) pQueryDisplayConfig = (SDL_WIN32PROC_QueryDisplayConfig)SDL_LoadFunction(dll, "QueryDisplayConfig"); pDisplayConfigGetDeviceInfo = (SDL_WIN32PROC_DisplayConfigGetDeviceInfo)SDL_LoadFunction(dll, "DisplayConfigGetDeviceInfo"); - if (pGetDisplayConfigBufferSizes == NULL || pQueryDisplayConfig == NULL || pDisplayConfigGetDeviceInfo == NULL) { + if (!pGetDisplayConfigBufferSizes || !pQueryDisplayConfig || !pDisplayConfigGetDeviceInfo) { goto WIN_GetDisplayNameVista_failed; } @@ -274,7 +274,7 @@ static char *WIN_GetDisplayNameVista(const WCHAR *deviceName) paths = (DISPLAYCONFIG_PATH_INFO *)SDL_malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * pathCount); modes = (DISPLAYCONFIG_MODE_INFO *)SDL_malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * modeCount); - if ((paths == NULL) || (modes == NULL)) { + if ((!paths) || (!modes)) { goto WIN_GetDisplayNameVista_failed; } @@ -401,7 +401,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI } displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); - if (displaydata == NULL) { + if (!displaydata) { return; } SDL_memcpy(displaydata->DeviceName, info->szDevice, sizeof(displaydata->DeviceName)); @@ -410,7 +410,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI SDL_zero(display); display.name = WIN_GetDisplayNameVista(info->szDevice); - if (display.name == NULL) { + if (!display.name) { DISPLAY_DEVICEW device; SDL_zero(device); device.cb = sizeof(device); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 46d39136f00df..44491d37abcbb 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -114,7 +114,7 @@ static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h; maskbits = SDL_small_alloc(Uint8, maskbitslen, &isstack); - if (maskbits == NULL) { + if (!maskbits) { SDL_OutOfMemory(); return NULL; } @@ -249,7 +249,7 @@ static void WIN_FreeCursor(SDL_Cursor *cursor) static int WIN_ShowCursor(SDL_Cursor *cursor) { - if (cursor == NULL) { + if (!cursor) { cursor = SDL_blank_cursor; } if (cursor) { diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 08834bc4a19b6..88e274f8d17d9 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -218,7 +218,7 @@ SDL_FunctionPointer WIN_GL_GetProcAddress(SDL_VideoDevice *_this, const char *pr /* This is to pick up extensions */ func = _this->gl_data->wglGetProcAddress(proc); - if (func == NULL) { + if (!func) { /* This is probably a normal GL function */ func = GetProcAddress(_this->gl_config.dll_handle, proc); } @@ -380,7 +380,7 @@ static SDL_bool HasExtension(const char *extension, const char *extensions) return SDL_FALSE; } - if (extensions == NULL) { + if (!extensions) { return SDL_FALSE; } @@ -392,7 +392,7 @@ static SDL_bool HasExtension(const char *extension, const char *extensions) for (;;) { where = SDL_strstr(start, extension); - if (where == NULL) { + if (!where) { break; } @@ -689,7 +689,7 @@ int WIN_GL_SetupWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_bool WIN_GL_UseEGL(SDL_VideoDevice *_this) { - SDL_assert(_this->gl_data != NULL); + SDL_assert(_this->gl_data); SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES); return SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE) || _this->gl_config.major_version == 1 || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor); /* No WGL extension for OpenGL ES 1.x profiles. */ @@ -829,15 +829,15 @@ int WIN_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext } /* sanity check that higher level handled this. */ - SDL_assert(window || (window == NULL && !context)); + SDL_assert(window || (!window && !context)); /* Some Windows drivers freak out if hdc is NULL, even when context is NULL, against spec. Since hdc is _supposed_ to be ignored if context is NULL, we either use the current GL window, or do nothing if we already have no current context. */ - if (window == NULL) { + if (!window) { window = SDL_GL_GetCurrentWindow(); - if (window == NULL) { + if (!window) { SDL_assert(SDL_GL_GetCurrentContext() == NULL); return 0; /* already done. */ } diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index d956eaf25843e..ac5dbc0463a31 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -53,7 +53,7 @@ int WIN_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) #endif } - if (_this->egl_data == NULL) { + if (!_this->egl_data) { return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform); } @@ -111,7 +111,7 @@ int WIN_GLES_SetupWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_Window *current_win = SDL_GL_GetCurrentWindow(); SDL_GLContext current_ctx = SDL_GL_GetCurrentContext(); - if (_this->egl_data == NULL) { + if (!_this->egl_data) { /* !!! FIXME: commenting out this assertion is (I think) incorrect; figure out why driver_loaded is wrong for ANGLE instead. --ryan. */ #if 0 /* When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), _this->gl_config.driver_loaded can be 1, while the below lines function. */ SDL_assert(!_this->gl_config.driver_loaded); diff --git a/src/video/windows/SDL_windowsshape.c b/src/video/windows/SDL_windowsshape.c index 25c3f5e0aeae3..74026601f5585 100644 --- a/src/video/windows/SDL_windowsshape.c +++ b/src/video/windows/SDL_windowsshape.c @@ -28,7 +28,7 @@ SDL_WindowShaper *Win32_CreateShaper(SDL_Window *window) { SDL_WindowShaper *result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper)); - if (result == NULL) { + if (!result) { SDL_OutOfMemory(); return NULL; } @@ -67,14 +67,14 @@ int Win32_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_Windo SDL_ShapeData *data; HRGN mask_region = NULL; - if ((shaper == NULL) || - (shape == NULL) || + if ((!shaper) || + (!shape) || ((shape->format->Amask == 0) && (shape_mode->mode != ShapeModeColorKey))) { return SDL_INVALID_SHAPE_ARGUMENT; } data = (SDL_ShapeData *)shaper->driverdata; - if (data->mask_tree != NULL) { + if (data->mask_tree) { SDL_FreeShapeTree(&data->mask_tree); } data->mask_tree = SDL_CalculateShapeTree(*shape_mode, shape); diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 0bd8fd5b663ef..78bf4236816b9 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -413,7 +413,7 @@ static void WIN_InitDPIAwareness(SDL_VideoDevice *_this) { const char *hint = SDL_GetHint("SDL_WINDOWS_DPI_AWARENESS"); - if (hint == NULL || SDL_strcmp(hint, "permonitorv2") == 0) { + if (!hint || SDL_strcmp(hint, "permonitorv2") == 0) { WIN_DeclareDPIAwarePerMonitorV2(_this); } else if (SDL_strcmp(hint, "permonitor") == 0) { WIN_DeclareDPIAwarePerMonitor(_this); @@ -549,7 +549,7 @@ int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID) SDL_DisplayData *pData = SDL_GetDisplayDriverData(displayID); int adapterIndex = D3DADAPTER_DEFAULT; - if (pData == NULL) { + if (!pData) { SDL_SetError("Invalid display index"); adapterIndex = -1; /* make sure we return something invalid */ } else { @@ -632,12 +632,12 @@ SDL_bool SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int * IDXGIAdapter *pDXGIAdapter; IDXGIOutput *pDXGIOutput; - if (adapterIndex == NULL) { + if (!adapterIndex) { SDL_InvalidParamError("adapterIndex"); return SDL_FALSE; } - if (outputIndex == NULL) { + if (!outputIndex) { SDL_InvalidParamError("outputIndex"); return SDL_FALSE; } @@ -645,7 +645,7 @@ SDL_bool SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int * *adapterIndex = -1; *outputIndex = -1; - if (pData == NULL) { + if (!pData) { SDL_SetError("Invalid display index"); return SDL_FALSE; } diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c index f52892d0f0a2a..5a632421c8962 100644 --- a/src/video/windows/SDL_windowsvulkan.c +++ b/src/video/windows/SDL_windowsvulkan.c @@ -48,10 +48,10 @@ int WIN_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan loader library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { path = "vulkan-1.dll"; } _this->vulkan_config.loader_handle = SDL_LoadObject(path); @@ -76,7 +76,7 @@ int WIN_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) (PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } for (i = 0; i < extensionCount; i++) { diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 95927b74dc785..ebcabd24eac8b 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -188,7 +188,7 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m if (WIN_IsPerMonitorV2DPIAware(SDL_GetVideoDevice())) { /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of AdjustWindowRectEx. */ - if (videodata != NULL) { + if (videodata) { SDL_WindowData *data = window->driverdata; frame_dpi = (data && videodata->GetDpiForWindow) ? videodata->GetDpiForWindow(data->hwnd) : 96; if (videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, frame_dpi) == 0) { @@ -262,7 +262,7 @@ int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags) data->expected_resize = SDL_FALSE; /* Update any child windows */ - for (child_window = window->first_child; child_window != NULL; child_window = child_window->next_sibling) { + for (child_window = window->first_child; child_window; child_window = child_window->next_sibling) { if (WIN_SetWindowPositionInternal(child_window, flags) < 0) { result = -1; } @@ -283,7 +283,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd /* Allocate the window data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } data->window = window; @@ -471,7 +471,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window) } } else { /* Restore any original event handler... */ - if (data->wndproc != NULL) { + if (data->wndproc) { #ifdef GWLP_WNDPROC SetWindowLongPtr(data->hwnd, GWLP_WNDPROC, (LONG_PTR)data->wndproc); @@ -498,7 +498,7 @@ static void WIN_ConstrainPopup(SDL_Window *window) int offset_x = 0, offset_y = 0; /* Calculate the total offset from the parents */ - for (w = window->parent; w->parent != NULL; w = w->parent) { + for (w = window->parent; w->parent; w = w->parent) { offset_x += w->x; offset_y += w->y; } @@ -530,7 +530,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window) SDL_Window *topmost = window; /* Find the topmost parent */ - while (topmost->parent != NULL) { + while (topmost->parent) { topmost = topmost->parent; } @@ -684,7 +684,7 @@ int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void (void)SDL_sscanf(hint, "%p", (void **)&otherWindow); /* Do some error checking on the pointer */ - if (otherWindow != NULL && otherWindow->magic == &_this->window_magic) { + if (otherWindow && otherWindow->magic == &_this->window_magic) { /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */ if (otherWindow->flags & SDL_WINDOW_OPENGL) { window->flags |= SDL_WINDOW_OPENGL; @@ -763,7 +763,7 @@ int WIN_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i SDL_small_free(icon_bmp, isstack); - if (hicon == NULL) { + if (!hicon) { retval = SDL_SetError("SetWindowIcon() failed, error %08X", (unsigned int)GetLastError()); } @@ -916,7 +916,7 @@ void WIN_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_Window *new_focus = window->parent; /* Find the highest level window that isn't being hidden or destroyed. */ - while (new_focus->parent != NULL && (new_focus->is_hiding || new_focus->is_destroying)) { + while (new_focus->parent && (new_focus->is_hiding || new_focus->is_destroying)) { new_focus = new_focus->parent; } @@ -1162,7 +1162,7 @@ void *WIN_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t filename_utf8 = WIN_StringToUTF8(data->ICMFileName); if (filename_utf8) { iccProfileData = SDL_LoadFile(filename_utf8, size); - if (iccProfileData == NULL) { + if (!iccProfileData) { SDL_SetError("Could not open ICC profile"); } SDL_free(filename_utf8); @@ -1285,7 +1285,7 @@ int SDL_HelperWindowCreate(void) CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, hInstance, NULL); - if (SDL_HelperWindow == NULL) { + if (!SDL_HelperWindow) { UnregisterClass(SDL_HelperWindowClassName, hInstance); return WIN_SetError("Unable to create Helper Window"); } @@ -1324,7 +1324,7 @@ void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->driverdata; - if (data == NULL || !data->hwnd) { + if (!data || !data->hwnd) { /* The window wasn't fully initialized */ return; } diff --git a/src/video/winrt/SDL_winrtgamebar.cpp b/src/video/winrt/SDL_winrtgamebar.cpp index f9ffa2c5fce60..00f777a5c3f00 100644 --- a/src/video/winrt/SDL_winrtgamebar.cpp +++ b/src/video/winrt/SDL_winrtgamebar.cpp @@ -115,7 +115,7 @@ static void WINRT_HandleGameBarIsInputRedirected_MainThread() return; } gameBar = WINRT_GetGameBar(); - if (gameBar == NULL) { + if (!gameBar) { /* Shouldn't happen, but just in case... */ return; } @@ -166,11 +166,11 @@ void WINRT_QuitGameBar(SDL_VideoDevice *_this) { SDL_VideoData *driverdata; IGameBarStatics_ *gameBar; - if (_this == NULL || _this->driverdata == NULL) { + if (!_this || !_this->driverdata) { return; } gameBar = WINRT_GetGameBar(); - if (gameBar == NULL) { + if (!gameBar) { return; } driverdata = _this->driverdata; diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 51e10ab31712c..f9877a9ced78b 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -108,13 +108,13 @@ static SDL_VideoDevice *WINRT_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return 0; } data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (data == NULL) { + if (!data) { SDL_OutOfMemory(); SDL_free(device); return 0; @@ -173,7 +173,7 @@ static void SDLCALL WINRT_SetDisplayOrientationsPreference(void *userdata, const * * TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'. */ - if ((oldValue == NULL) && (newValue == NULL)) { + if ((!oldValue) && (!newValue)) { return; } @@ -320,7 +320,7 @@ static int WINRT_AddDisplaysForOutput(SDL_VideoDevice *_this, IDXGIAdapter1 *dxg } dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC)); - if (dxgiModes == NULL) { + if (!dxgiModes) { SDL_OutOfMemory(); goto done; } diff --git a/src/video/x11/SDL_x11clipboard.c b/src/video/x11/SDL_x11clipboard.c index 3bec670980afa..4bb7d395b26f6 100644 --- a/src/video/x11/SDL_x11clipboard.c +++ b/src/video/x11/SDL_x11clipboard.c @@ -99,9 +99,9 @@ static int SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_Clipboar static void *CloneDataBuffer(const void *buffer, size_t *len) { void *clone = NULL; - if (*len > 0 && buffer != NULL) { + if (*len > 0 && buffer) { clone = SDL_malloc((*len)+sizeof(Uint32)); - if (clone == NULL) { + if (!clone) { SDL_OutOfMemory(); } else { SDL_memcpy(clone, buffer, *len); @@ -228,7 +228,7 @@ SDL_bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type) size_t length; void *data; data = X11_GetClipboardData(_this, mime_type, &length); - if (data != NULL) { + if (data) { SDL_free(data); } return length > 0; diff --git a/src/video/x11/SDL_x11dyn.c b/src/video/x11/SDL_x11dyn.c index 18174d1291d9c..5b8a226b927f6 100644 --- a/src/video/x11/SDL_x11dyn.c +++ b/src/video/x11/SDL_x11dyn.c @@ -72,22 +72,22 @@ static void *X11_GetSym(const char *fnname, int *pHasModule) int i; void *fn = NULL; for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { - if (x11libs[i].lib != NULL) { + if (x11libs[i].lib) { fn = SDL_LoadFunction(x11libs[i].lib, fnname); - if (fn != NULL) { + if (fn) { break; } } } #if DEBUG_DYNAMIC_X11 - if (fn != NULL) + if (fn) printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, fn); else printf("X11: Symbol '%s' NOT FOUND!\n", fnname); #endif - if (fn == NULL) { + if (!fn) { *pHasModule = 0; /* kill this module. */ } @@ -133,7 +133,7 @@ void SDL_X11_UnloadSymbols(void) #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { - if (x11libs[i].lib != NULL) { + if (x11libs[i].lib) { SDL_UnloadObject(x11libs[i].lib); x11libs[i].lib = NULL; } @@ -154,7 +154,7 @@ int SDL_X11_LoadSymbols(void) int i; int *thismod = NULL; for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { - if (x11libs[i].libname != NULL) { + if (x11libs[i].libname) { x11libs[i].lib = SDL_LoadObject(x11libs[i].libname); } } diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 1731dc747b882..59a0b969d8a1e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -100,7 +100,7 @@ static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop) int bytes_fetch = 0; do { - if (ret != NULL) { + if (ret) { X11_XFree(ret); } X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret); @@ -222,7 +222,7 @@ static int X11_URIDecode(char *buf, int len) { int ri, wi, di; char decode = '\0'; - if (buf == NULL || len < 0) { + if (!buf || len < 0) { errno = EINVAL; return -1; } @@ -298,7 +298,7 @@ static char *X11_URIToLocal(char *uri) /* got a hostname? */ if (!local && uri[0] == '/' && uri[2] != '/') { char *hostname_end = SDL_strchr(uri + 1, '/'); - if (hostname_end != NULL) { + if (hostname_end) { char hostname[257]; if (gethostname(hostname, 255) == 0) { hostname[256] = '\0'; @@ -685,7 +685,7 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven /* FIXME: We don't support the X11 INCR protocol for large clipboards. Do we want that? - Yes, yes we do. */ /* This is a safe cast, XChangeProperty() doesn't take a const value, but it doesn't modify the data */ seln_data = (unsigned char *)clipboard->callback(clipboard->userdata, mime_type, &seln_length); - if (seln_data != NULL) { + if (seln_data) { X11_XChangeProperty(display, req->requestor, req->property, req->target, 8, PropModeReplace, seln_data, seln_length); @@ -821,7 +821,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) XClientMessageEvent m; int i; - SDL_assert(videodata != NULL); + SDL_assert(videodata); display = videodata->display; /* Save the original keycode for dead keys, which are filtered out by @@ -921,7 +921,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } } } - if (data == NULL) { + if (!data) { /* The window for KeymapNotify, etc events is 0 */ if (xevent->type == KeymapNotify) { #ifdef DEBUG_XEVENTS @@ -1257,7 +1257,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) SDL_IME_UpdateTextRect(NULL); } #endif - for (w = data->window->first_child; w != NULL; w = w->next_sibling) { + for (w = data->window->first_child; w; w = w->next_sibling) { /* Don't update hidden child windows, their relative position doesn't change */ if (!(w->flags & SDL_WINDOW_HIDDEN)) { X11_UpdateWindowPosition(w); @@ -1616,7 +1616,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) char *name = X11_XGetAtomName(display, target); if (name) { char *token = SDL_strtok_r((char *)p.data, "\r\n", &saveptr); - while (token != NULL) { + while (token) { if (SDL_strcmp("text/plain", name) == 0) { SDL_SendDropText(data->window, token); } else if (SDL_strcmp("text/uri-list", name) == 0) { diff --git a/src/video/x11/SDL_x11framebuffer.c b/src/video/x11/SDL_x11framebuffer.c index 9e8da1dd16b83..b4a0ae12a5a5b 100644 --- a/src/video/x11/SDL_x11framebuffer.c +++ b/src/video/x11/SDL_x11framebuffer.c @@ -127,7 +127,7 @@ int X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint #endif /* not NO_SHARED_MEMORY */ *pixels = SDL_malloc((size_t)h * (*pitch)); - if (*pixels == NULL) { + if (!*pixels) { return SDL_OutOfMemory(); } @@ -226,7 +226,7 @@ void X11_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) SDL_WindowData *data = window->driverdata; Display *display; - if (data == NULL) { + if (!data) { /* The window wasn't fully initialized */ return; } diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index cc197227ece4b..7eae41deb788c 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -190,15 +190,15 @@ static int X11_MessageBoxInit(SDL_MessageBoxDataX11 *data, const SDL_MessageBoxD int num_missing = 0; data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont, &missing, &num_missing, NULL); - if (missing != NULL) { + if (missing) { X11_XFreeStringList(missing); } - if (data->font_set == NULL) { + if (!data->font_set) { return SDL_SetError("Couldn't load font %s", g_MessageBoxFont); } } else { data->font_struct = X11_XLoadQueryFont(data->display, g_MessageBoxFontLatin1); - if (data->font_struct == NULL) { + if (!data->font_struct) { return SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1); } } @@ -239,12 +239,12 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data) const SDL_MessageBoxData *messageboxdata = data->messageboxdata; /* Go over text and break linefeeds into separate lines. */ - if (messageboxdata != NULL && messageboxdata->message[0]) { + if (messageboxdata && messageboxdata->message[0]) { const char *text = messageboxdata->message; const int linecount = CountLinesOfText(text); TextLineData *plinedata = (TextLineData *)SDL_malloc(sizeof(TextLineData) * linecount); - if (plinedata == NULL) { + if (!plinedata) { return SDL_OutOfMemory(); } @@ -272,7 +272,7 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data) text += length + 1; /* Break if there are no more linefeeds. */ - if (lf == NULL) { + if (!lf) { break; } } @@ -361,12 +361,12 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data) /* Free SDL_MessageBoxData data. */ static void X11_MessageBoxShutdown(SDL_MessageBoxDataX11 *data) { - if (data->font_set != NULL) { + if (data->font_set) { X11_XFreeFontSet(data->display, data->font_set); data->font_set = NULL; } - if (data->font_struct != NULL) { + if (data->font_struct) { X11_XFreeFont(data->display, data->font_struct); data->font_struct = NULL; } @@ -760,9 +760,9 @@ static int X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int #if SDL_SET_LOCALE origlocale = setlocale(LC_ALL, NULL); - if (origlocale != NULL) { + if (origlocale) { origlocale = SDL_strdup(origlocale); - if (origlocale == NULL) { + if (!origlocale) { return SDL_OutOfMemory(); } (void)setlocale(LC_ALL, ""); diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index e8c0ad331445e..16255c98e092b 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -536,7 +536,7 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen } output_info = X11_XRRGetOutputInfo(dpy, res, outputid); - if (output_info == NULL || !output_info->crtc || output_info->connection == RR_Disconnected) { + if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) { X11_XRRFreeOutputInfo(output_info); return 0; /* ignore this one. */ } @@ -548,7 +548,7 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen X11_XRRFreeOutputInfo(output_info); crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc); - if (crtc == NULL) { + if (!crtc) { return 0; /* oh well, ignore it. */ } @@ -564,12 +564,12 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen X11_XRRFreeCrtcInfo(crtc); displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); - if (displaydata == NULL) { + if (!displaydata) { return SDL_OutOfMemory(); } modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (modedata == NULL) { + if (!modedata) { SDL_free(displaydata); return SDL_OutOfMemory(); } @@ -626,11 +626,11 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput } if (ev->connection == RR_Disconnected) { /* output is going away */ - if (display != NULL) { + if (display) { SDL_DelVideoDisplay(display->id, SDL_TRUE); } } else if (ev->connection == RR_Connected) { /* output is coming online */ - if (display != NULL) { + if (display) { /* !!! FIXME: update rotation or current mode of existing display? */ } else { Display *dpy = ev->display; @@ -638,7 +638,7 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput XVisualInfo vinfo; if (get_visualinfo(dpy, screen, &vinfo) == 0) { XRRScreenResources *res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen)); - if (res == NULL || res->noutput == 0) { + if (!res || res->noutput == 0) { if (res) { X11_XRRFreeScreenResources(res); } @@ -694,13 +694,13 @@ static int X11_InitModes_XRandR(SDL_VideoDevice *_this) } res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen)); - if (res == NULL || res->noutput == 0) { + if (!res || res->noutput == 0) { if (res) { X11_XRRFreeScreenResources(res); } res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen)); - if (res == NULL) { + if (!res) { continue; } } @@ -767,12 +767,12 @@ static int X11_InitModes_StdXlib(SDL_VideoDevice *_this) mode.format = pixelformat; displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); - if (displaydata == NULL) { + if (!displaydata) { return SDL_OutOfMemory(); } modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (modedata == NULL) { + if (!modedata) { SDL_free(displaydata); return SDL_OutOfMemory(); } @@ -861,7 +861,7 @@ int X11_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display) if (output_info && output_info->connection != RR_Disconnected) { for (i = 0; i < output_info->nmode; ++i) { modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (modedata == NULL) { + if (!modedata) { continue; } mode.driverdata = modedata; @@ -914,18 +914,18 @@ int X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SD Status status; res = X11_XRRGetScreenResources(display, RootWindow(display, data->screen)); - if (res == NULL) { + if (!res) { return SDL_SetError("Couldn't get XRandR screen resources"); } output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output); - if (output_info == NULL || output_info->connection == RR_Disconnected) { + if (!output_info || output_info->connection == RR_Disconnected) { X11_XRRFreeScreenResources(res); return SDL_SetError("Couldn't get XRandR output info"); } crtc = X11_XRRGetCrtcInfo(display, res, output_info->crtc); - if (crtc == NULL) { + if (!crtc) { X11_XRRFreeOutputInfo(output_info); X11_XRRFreeScreenResources(res); return SDL_SetError("Couldn't get XRandR crtc info"); diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 7edef6a842019..3f2d3d3dd9f29 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -88,7 +88,7 @@ static Cursor X11_CreateXCursorCursor(SDL_Surface *surface, int hot_x, int hot_y XcursorImage *image; image = X11_XcursorImageCreate(surface->w, surface->h); - if (image == NULL) { + if (!image) { SDL_OutOfMemory(); return None; } @@ -121,13 +121,13 @@ static Cursor X11_CreatePixmapCursor(SDL_Surface *surface, int hot_x, int hot_y) size_t width_bytes = ((surface->w + 7) & ~((size_t)7)) / 8; data_bits = SDL_calloc(1, surface->h * width_bytes); - if (data_bits == NULL) { + if (!data_bits) { SDL_OutOfMemory(); return None; } mask_bits = SDL_calloc(1, surface->h * width_bytes); - if (mask_bits == NULL) { + if (!mask_bits) { SDL_free(data_bits); SDL_OutOfMemory(); return None; @@ -422,7 +422,7 @@ static Uint32 X11_GetGlobalMouseState(float *x, float *y) if (displays) { for (i = 0; displays[i]; ++i) { SDL_DisplayData *data = SDL_GetDisplayDriverData(displays[i]); - if (data != NULL) { + if (data) { Window root, child; int rootx, rooty, winx, winy; unsigned int mask; @@ -481,7 +481,7 @@ void X11_QuitMouse(SDL_VideoDevice *_this) SDL_XInput2DeviceInfo *i; SDL_XInput2DeviceInfo *next; - for (i = data->mouse_device_info; i != NULL; i = next) { + for (i = data->mouse_device_info; i; i = next) { next = i->next; SDL_free(i); } diff --git a/src/video/x11/SDL_x11shape.c b/src/video/x11/SDL_x11shape.c index 1acd33ce0ccd1..373d6eba1ae4b 100644 --- a/src/video/x11/SDL_x11shape.c +++ b/src/video/x11/SDL_x11shape.c @@ -36,7 +36,7 @@ SDL_WindowShaper *X11_CreateShaper(SDL_Window *window) if (SDL_X11_HAVE_XSHAPE) { /* Make sure X server supports it. */ result = SDL_malloc(sizeof(SDL_WindowShaper)); - if (result == NULL) { + if (!result) { SDL_OutOfMemory(); return NULL; } @@ -44,7 +44,7 @@ SDL_WindowShaper *X11_CreateShaper(SDL_Window *window) result->mode.mode = ShapeModeDefault; result->mode.parameters.binarizationCutoff = 1; data = SDL_malloc(sizeof(SDL_ShapeData)); - if (data == NULL) { + if (!data) { SDL_free(result); SDL_OutOfMemory(); return NULL; @@ -67,7 +67,7 @@ int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowS Pixmap shapemask; #endif - if (shaper == NULL || shape == NULL || shaper->driverdata == NULL) { + if (!shaper || !shape || !shaper->driverdata) { return -1; } diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 1e164e84cccd7..a27e409815fe5 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -79,7 +79,7 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e) if (!safety_net_triggered) { safety_net_triggered = SDL_TRUE; device = SDL_GetVideoDevice(); - if (device != NULL) { + if (device) { int i; for (i = 0; i < device->num_displays; i++) { SDL_VideoDisplay *display = device->displays[i]; @@ -90,7 +90,7 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e) } } - if (orig_x11_errhandler != NULL) { + if (orig_x11_errhandler) { return orig_x11_errhandler(d, e); /* probably terminate. */ } @@ -115,19 +115,19 @@ static SDL_VideoDevice *X11_CreateDevice(void) /* Open the display first to be sure that X11 is available */ x11_display = X11_XOpenDisplay(display); - if (x11_display == NULL) { + if (!x11_display) { SDL_X11_UnloadSymbols(); return NULL; } /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device == NULL) { + if (!device) { SDL_OutOfMemory(); return NULL; } data = (struct SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (data == NULL) { + if (!data) { SDL_free(device); SDL_OutOfMemory(); return NULL; @@ -142,7 +142,7 @@ static SDL_VideoDevice *X11_CreateDevice(void) data->display = x11_display; data->request_display = X11_XOpenDisplay(display); - if (data->request_display == NULL) { + if (!data->request_display) { X11_XCloseDisplay(data->display); SDL_free(device->driverdata); SDL_free(device); diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c index a5aa38b9a2e1c..9b9917bf6f302 100644 --- a/src/video/x11/SDL_x11vulkan.c +++ b/src/video/x11/SDL_x11vulkan.c @@ -57,10 +57,10 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) } /* Load the Vulkan loader library */ - if (path == NULL) { + if (!path) { path = SDL_getenv("SDL_VULKAN_LIBRARY"); } - if (path == NULL) { + if (!path) { path = DEFAULT_VULKAN; } _this->vulkan_config.loader_handle = SDL_LoadObject(path); @@ -84,7 +84,7 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) (PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &extensionCount); - if (extensions == NULL) { + if (!extensions) { goto fail; } for (i = 0; i < extensionCount; i++) { @@ -108,7 +108,7 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) goto fail; } else { const char *libX11XCBLibraryName = SDL_getenv("SDL_X11_XCB_LIBRARY"); - if (libX11XCBLibraryName == NULL) { + if (!libX11XCBLibraryName) { libX11XCBLibraryName = "libX11-xcb.so"; } videoData->vulkan_xlib_xcb_library = SDL_LoadObject(libX11XCBLibraryName); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 1820b54c2ca7f..9c2b53e958994 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -169,7 +169,7 @@ static void X11_ConstrainPopup(SDL_Window *window) int offset_x = 0, offset_y = 0; /* Calculate the total offset from the parents */ - for (w = window->parent; w->parent != NULL; w = w->parent) { + for (w = window->parent; w->parent; w = w->parent) { offset_x += w->x; offset_y += w->y; } @@ -201,7 +201,7 @@ static void X11_SetKeyboardFocus(SDL_Window *window) SDL_Window *topmost = window; /* Find the topmost parent */ - while (topmost->parent != NULL) { + while (topmost->parent) { topmost = topmost->parent; } @@ -306,7 +306,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, /* Allocate the window data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); - if (data == NULL) { + if (!data) { return SDL_OutOfMemory(); } data->window = window; @@ -330,7 +330,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, videodata->numwindows++; } else { windowlist = (SDL_WindowData **)SDL_realloc(windowlist, (numwindows + 1) * sizeof(*windowlist)); - if (windowlist == NULL) { + if (!windowlist) { SDL_free(data); return SDL_OutOfMemory(); } @@ -451,7 +451,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; const char *forced_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_WINDOW_VISUALID); - if (forced_visual_id != NULL && forced_visual_id[0] != '\0') { + if (forced_visual_id && forced_visual_id[0] != '\0') { XVisualInfo *vi, template; int nvis; @@ -485,7 +485,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) #endif } - if (vinfo == NULL) { + if (!vinfo) { return -1; } visual = vinfo->visual; @@ -522,7 +522,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) /* OK, we got a colormap, now fill it in as best as we can */ colorcells = SDL_malloc(visual->map_entries * sizeof(XColor)); - if (colorcells == NULL) { + if (!colorcells) { return SDL_OutOfMemory(); } ncolors = visual->map_entries; @@ -669,7 +669,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP"; } else if (window->flags & SDL_WINDOW_POPUP_MENU) { wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU"; - } else if (hint != NULL && *hint) { + } else if (hint && *hint) { wintype_name = hint; } else { wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL"; @@ -984,7 +984,7 @@ int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i X11_XFlush(display); - if (prevHandler != NULL) { + if (prevHandler) { X11_XSetErrorHandler(prevHandler); caught_x11_error = SDL_FALSE; } @@ -1020,7 +1020,7 @@ void X11_UpdateWindowPosition(SDL_Window *window) /* Send MOVED/RESIZED event, if needed. Compare with initial/expected position. Timeout 100 */ X11_WaitAndSendWindowEvents(window, 100, COMPARE_POSITION, orig_x, orig_y, dest_x, dest_y, 0, 0, 0, 0); - for (w = window->first_child; w != NULL; w = w->next_sibling) { + for (w = window->first_child; w; w = w->next_sibling) { X11_UpdateWindowPosition(w); } } @@ -1375,7 +1375,7 @@ void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_Window *new_focus = window->parent; /* Find the highest level window that isn't being hidden or destroyed. */ - while (new_focus->parent != NULL && (new_focus->is_hiding || new_focus->is_destroying)) { + while (new_focus->parent && (new_focus->is_hiding || new_focus->is_destroying)) { new_focus = new_focus->parent; } @@ -1658,7 +1658,7 @@ static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop) int bytes_fetch = 0; do { - if (ret != NULL) { + if (ret) { X11_XFree(ret); } X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret); @@ -1708,7 +1708,7 @@ void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t } ret_icc_profile_data = SDL_malloc(real_nitems); - if (ret_icc_profile_data == NULL) { + if (!ret_icc_profile_data) { SDL_OutOfMemory(); return NULL; } @@ -1725,7 +1725,7 @@ void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool SDL_WindowData *data = window->driverdata; Display *display; - if (data == NULL) { + if (!data) { return; } data->mouse_grabbed = SDL_FALSE; @@ -1780,7 +1780,7 @@ void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_b SDL_WindowData *data = window->driverdata; Display *display; - if (data == NULL) { + if (!data) { return; } @@ -1881,7 +1881,7 @@ int X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperati XWMHints *wmhints; wmhints = X11_XGetWMHints(display, data->xwindow); - if (wmhints == NULL) { + if (!wmhints) { return SDL_SetError("Couldn't get WM hints"); } @@ -1984,7 +1984,7 @@ int X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool XWMHints *wmhints; wmhints = X11_XGetWMHints(display, data->xwindow); - if (wmhints == NULL) { + if (!wmhints) { return SDL_SetError("Couldn't get WM hints"); } diff --git a/src/video/x11/SDL_x11xfixes.c b/src/video/x11/SDL_x11xfixes.c index 28ea7a6adb80a..89952a1008d98 100644 --- a/src/video/x11/SDL_x11xfixes.c +++ b/src/video/x11/SDL_x11xfixes.c @@ -120,7 +120,7 @@ int X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const X11_DestroyPointerBarrier(_this, data->active_cursor_confined_window); } - SDL_assert(window != NULL); + SDL_assert(window); wdata = window->driverdata; /* If user did not specify an area to confine, destroy the barrier that was/is assigned to diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index 7705e957fe8bc..fa7a651be53c1 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -188,10 +188,10 @@ static void xinput2_remove_device_info(SDL_VideoData *videodata, const int devic SDL_XInput2DeviceInfo *prev = NULL; SDL_XInput2DeviceInfo *devinfo; - for (devinfo = videodata->mouse_device_info; devinfo != NULL; devinfo = devinfo->next) { + for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); - if (prev == NULL) { + SDL_assert((devinfo == videodata->mouse_device_info) == (!prev)); + if (!prev) { videodata->mouse_device_info = devinfo->next; } else { prev->next = devinfo->next; @@ -212,10 +212,10 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, int axis = 0; int i; - for (devinfo = videodata->mouse_device_info; devinfo != NULL; devinfo = devinfo->next) { + for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); - if (prev != NULL) { /* move this to the front of the list, assuming we'll get more from this one. */ + SDL_assert((devinfo == videodata->mouse_device_info) == (!prev)); + if (prev) { /* move this to the front of the list, assuming we'll get more from this one. */ prev->next = devinfo->next; devinfo->next = videodata->mouse_device_info; videodata->mouse_device_info = devinfo; @@ -227,13 +227,13 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, /* don't know about this device yet, query and cache it. */ devinfo = (SDL_XInput2DeviceInfo *)SDL_calloc(1, sizeof(SDL_XInput2DeviceInfo)); - if (devinfo == NULL) { + if (!devinfo) { SDL_OutOfMemory(); return NULL; } xidevinfo = X11_XIQueryDevice(videodata->display, device_id, &i); - if (xidevinfo == NULL) { + if (!xidevinfo) { SDL_free(devinfo); return NULL; } @@ -287,7 +287,7 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie } devinfo = xinput2_get_device_info(videodata, rawev->deviceid); - if (devinfo == NULL) { + if (!devinfo) { return 0; /* oh well. */ } diff --git a/test/checkkeys.c b/test/checkkeys.c index cdba94157cf95..5d9ab3e44be72 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } state->window_title = "CheckKeys Test"; diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index cca4740e4c0be..dcb003cc35096 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -267,7 +267,7 @@ int main(int argc, char *argv[]) /* Set 640x480 video mode */ window = SDL_CreateWindow("CheckKeys Test", 640, 480, 0); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n", SDL_GetError()); quit(2); diff --git a/test/gamepadutils.c b/test/gamepadutils.c index c3570aee4f123..28d50e87735dc 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -2658,7 +2658,7 @@ SDL_GamepadType GetMappingType(const char *mapping) char *SetMappingType(char *mapping, SDL_GamepadType type) { const char *type_string = SDL_GetGamepadStringForType(type); - if (type_string == NULL || type == SDL_GAMEPAD_TYPE_UNKNOWN) { + if (!type_string || type == SDL_GAMEPAD_TYPE_UNKNOWN) { return RemoveMappingValue(mapping, "type"); } else { return SetMappingValue(mapping, "type", type_string); diff --git a/test/loopwave.c b/test/loopwave.c index 877fe8f3918ca..071d4cc979464 100644 --- a/test/loopwave.c +++ b/test/loopwave.c @@ -52,7 +52,7 @@ int SDL_AppInit(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -87,7 +87,7 @@ int SDL_AppInit(int argc, char *argv[]) filename = GetResourceFilename(filename, "sample.wav"); - if (filename == NULL) { + if (!filename) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); return -1; } diff --git a/test/testatomic.c b/test/testatomic.c index dbbc38326e1de..599730c9bd46c 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -701,7 +701,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testaudio.c b/test/testaudio.c index 210b9c29b29e7..924924187e5ae 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -146,7 +146,7 @@ static Thing *FindThingAtPoint(const float x, const float y) const SDL_FPoint pt = { x, y }; Thing *retval = NULL; Thing *i; - for (i = things; i != NULL; i = i->next) { + for (i = things; i; i = i->next) { if ((i != dragging_thing) && SDL_PointInRectFloat(&pt, &i->rect)) { retval = i; /* keep going, though, because things drawn on top are later in the list. */ } @@ -188,7 +188,7 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl } if ((w < 0) || (h < 0)) { - SDL_assert(texture != NULL); + SDL_assert(texture); if (w < 0) { w = texture->w; } @@ -213,12 +213,12 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl thing->titlebar = titlebar ? SDL_strdup(titlebar) : NULL; /* if allocation fails, oh well. */ /* insert in list by Z order (furthest from the "camera" first, so they get drawn over; negative Z is not drawn at all). */ - if (things == NULL) { + if (!things) { things = thing; return thing; } - for (i = things; i != NULL; i = i->next) { + for (i = things; i; i = i->next) { if (z > i->z) { /* insert here. */ thing->next = i; thing->prev = i->prev; @@ -389,7 +389,7 @@ static void RepositionRowOfThings(const ThingType what, const float y) float texh = 0.0f; Thing *i; - for (i = things; i != NULL; i = i->next) { + for (i = things; i; i = i->next) { if (i->what == what) { texw = i->rect.w; texh = i->rect.h; @@ -402,7 +402,7 @@ static void RepositionRowOfThings(const ThingType what, const float y) SDL_GetWindowSize(state->windows[0], &w, &h); const float spacing = w / ((float) total_things); float x = (spacing - texw) / 2.0f; - for (i = things; i != NULL; i = i->next) { + for (i = things; i; i = i->next) { if (i->what == what) { i->rect.x = x; i->rect.y = (y >= 0.0f) ? y : ((h + y) - texh); @@ -494,7 +494,7 @@ static void DestroyThingInPoof(Thing *thing) static void TrashThing(Thing *thing) { Thing *i, *next; - for (i = things; i != NULL; i = next) { + for (i = things; i; i = next) { next = i->next; if (i->line_connected_to == thing) { TrashThing(i); @@ -1009,7 +1009,7 @@ static void TickThings(void) Thing *i; Thing *next; const Uint64 now = SDL_GetTicks(); - for (i = things; i != NULL; i = next) { + for (i = things; i; i = next) { next = i->next; /* in case this deletes itself. */ if (i->ontick) { i->ontick(i, now); @@ -1024,7 +1024,7 @@ static void WindowResized(const int newwinw, const int newwinh) const float newh = (float) newwinh; const float oldw = (float) state->window_w; const float oldh = (float) state->window_h; - for (i = things; i != NULL; i = i->next) { + for (i = things; i; i = i->next) { const float halfw = i->rect.w / 2.0f; const float halfh = i->rect.h / 2.0f; const float x = (i->rect.x + halfw) / oldw; @@ -1041,7 +1041,7 @@ int SDL_AppInit(int argc, char *argv[]) int i; state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO); - if (state == NULL) { + if (!state) { return -1; } @@ -1195,7 +1195,7 @@ int SDL_AppEvent(const SDL_Event *event) const SDL_AudioDeviceID which = event->adevice.which; Thing *i, *next; SDL_Log("Removing audio device %u", (unsigned int) which); - for (i = things; i != NULL; i = next) { + for (i = things; i; i = next) { next = i->next; if (((i->what == THING_PHYSDEV) || (i->what == THING_PHYSDEV_CAPTURE)) && (i->data.physdev.devid == which)) { TrashThing(i); @@ -1234,7 +1234,7 @@ int SDL_AppIterate(void) void SDL_AppQuit(void) { - while (things != NULL) { + while (things) { DestroyThing(things); /* make sure all the audio devices are closed, etc. */ } diff --git a/test/testaudiocapture.c b/test/testaudiocapture.c index 9b44b6573540d..dfa22a73ca8a9 100644 --- a/test/testaudiocapture.c +++ b/test/testaudiocapture.c @@ -36,7 +36,7 @@ int SDL_AppInit(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testaudiohotplug.c b/test/testaudiohotplug.c index 6f3198488201d..72a562cfc067d 100644 --- a/test/testaudiohotplug.c +++ b/test/testaudiohotplug.c @@ -72,7 +72,7 @@ static void iteration(void) const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which; const SDL_bool iscapture = e.adevice.iscapture ? SDL_TRUE : SDL_FALSE; char *name = SDL_GetAudioDeviceName(which); - if (name != NULL) { + if (name) { SDL_Log("New %s audio device at id %u: %s", devtypestr(iscapture), (unsigned int)which, name); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device, id %u, but failed to get the name: %s", @@ -119,7 +119,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -154,7 +154,7 @@ int main(int argc, char *argv[]) /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */ window = SDL_CreateWindow("testaudiohotplug", 640, 480, 0); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow failed: %s\n", SDL_GetError()); quit(1); } @@ -162,7 +162,7 @@ int main(int argc, char *argv[]) filename = GetResourceFilename(filename, "sample.wav"); - if (filename == NULL) { + if (!filename) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); quit(1); } diff --git a/test/testaudioinfo.c b/test/testaudioinfo.c index 8034f5623c48a..cb061db1af616 100644 --- a/test/testaudioinfo.c +++ b/test/testaudioinfo.c @@ -22,7 +22,7 @@ print_devices(SDL_bool iscapture) int frames; SDL_AudioDeviceID *devices = iscapture ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n); - if (devices == NULL) { + if (!devices) { SDL_Log(" Driver failed to report %s devices: %s\n\n", typestr, SDL_GetError()); } else if (n == 0) { SDL_Log(" No %s devices found.\n\n", typestr); @@ -31,7 +31,7 @@ print_devices(SDL_bool iscapture) SDL_Log("Found %d %s device%s:\n", n, typestr, n != 1 ? "s" : ""); for (i = 0; i < n; i++) { char *name = SDL_GetAudioDeviceName(devices[i]); - if (name != NULL) { + if (name) { SDL_Log(" %d: %s\n", i, name); SDL_free(name); } else { @@ -60,7 +60,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testaudiostreamdynamicresample.c b/test/testaudiostreamdynamicresample.c index 0c6c2c197f0a1..4e3b8fb0f88c4 100644 --- a/test/testaudiostreamdynamicresample.c +++ b/test/testaudiostreamdynamicresample.c @@ -158,7 +158,7 @@ static void skip_audio(float amount) num_frames = (int)(new_spec.freq * ((speed * amount) / 100.0f)); buf = SDL_malloc(num_frames); - if (buf != NULL) { + if (buf) { retval = SDL_GetAudioStreamData(stream, buf, num_frames); SDL_free(buf); } @@ -374,7 +374,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_AUDIO | SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testautomation.c b/test/testautomation.c index f2bb2e8ebcdf3..9a5bf803db7de 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testautomation_mouse.c b/test/testautomation_mouse.c index 2397b992a581f..af037f02fa77b 100644 --- a/test/testautomation_mouse.c +++ b/test/testautomation_mouse.c @@ -418,7 +418,7 @@ static SDL_Window *createMouseSuiteTestWindow(void) */ static void destroyMouseSuiteTestWindow(SDL_Window *window) { - if (window != NULL) { + if (window) { SDL_DestroyWindow(window); window = NULL; SDLTest_AssertPass("SDL_DestroyWindow()"); @@ -454,7 +454,7 @@ static int mouse_warpMouseInWindow(void *arg) yPositions[5] = (float)h + 1; /* Create test window */ window = createMouseSuiteTestWindow(); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -507,7 +507,7 @@ static int mouse_getMouseFocus(void *arg) /* Create test window */ window = createMouseSuiteTestWindow(); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } diff --git a/test/testautomation_render.c b/test/testautomation_render.c index 5e7ca3579e4c0..9ab7ea4603937 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -76,13 +76,13 @@ static void InitCreateRenderer(void *arg) */ static void CleanupDestroyRenderer(void *arg) { - if (renderer != NULL) { + if (renderer) { SDL_DestroyRenderer(renderer); renderer = NULL; SDLTest_AssertPass("SDL_DestroyRenderer()"); } - if (window != NULL) { + if (window) { SDL_DestroyWindow(window); window = NULL; SDLTest_AssertPass("SDL_DestroyWindow"); @@ -1054,12 +1054,12 @@ loadTestFace(void) SDL_Texture *tface; face = SDLTest_ImageFace(); - if (face == NULL) { + if (!face) { return NULL; } tface = SDL_CreateTextureFromSurface(renderer, face); - if (tface == NULL) { + if (!tface) { SDLTest_LogError("SDL_CreateTextureFromSurface() failed with error: %s", SDL_GetError()); } @@ -1085,7 +1085,7 @@ hasTexColor(void) /* Get test face. */ tface = loadTestFace(); - if (tface == NULL) { + if (!tface) { return 0; } @@ -1128,7 +1128,7 @@ hasTexAlpha(void) /* Get test face. */ tface = loadTestFace(); - if (tface == NULL) { + if (!tface) { return 0; } diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index e797e4824b36f..eab676d795a61 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -453,10 +453,10 @@ static int stdlib_getsetenv(void *arg) text = SDL_getenv(name); SDLTest_AssertPass("Call to SDL_getenv('%s')", name); - if (text != NULL) { + if (text) { SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text)); } - } while (text != NULL); + } while (text); /* Create random values to set */ value1 = SDLTest_RandomAsciiStringOfSize(10); diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index 5567ece46bebd..c75c85d93ecec 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -353,21 +353,21 @@ static int surface_testCompleteSurfaceConversion(void *arg) for (i = 0; i < SDL_arraysize(pixel_formats); ++i) { for (j = 0; j < SDL_arraysize(pixel_formats); ++j) { fmt1 = SDL_CreatePixelFormat(pixel_formats[i]); - SDL_assert(fmt1 != NULL); + SDL_assert(fmt1); cvt1 = SDL_ConvertSurface(face, fmt1); - SDL_assert(cvt1 != NULL); + SDL_assert(cvt1); fmt2 = SDL_CreatePixelFormat(pixel_formats[j]); - SDL_assert(fmt1 != NULL); + SDL_assert(fmt1); cvt2 = SDL_ConvertSurface(cvt1, fmt2); - SDL_assert(cvt2 != NULL); + SDL_assert(cvt2); if (fmt1->BytesPerPixel == face->format->BytesPerPixel && fmt2->BytesPerPixel == face->format->BytesPerPixel && (fmt1->Amask != 0) == (face->format->Amask != 0) && (fmt2->Amask != 0) == (face->format->Amask != 0)) { final = SDL_ConvertSurface(cvt2, face->format); - SDL_assert(final != NULL); + SDL_assert(final); /* Compare surface. */ ret = SDLTest_CompareSurfaces(face, final, 0); diff --git a/test/testautomation_video.c b/test/testautomation_video.c index a05d90267b035..e5fbdee2885c9 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -542,7 +542,7 @@ static int video_getSetWindowGrab(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -703,7 +703,7 @@ static int video_getWindowId(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -758,7 +758,7 @@ static int video_getWindowPixelFormat(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -828,7 +828,7 @@ static int video_getSetWindowPosition(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -1000,7 +1000,7 @@ static int video_getSetWindowSize(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -1183,7 +1183,7 @@ static int video_getSetWindowMinimumSize(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -1325,7 +1325,7 @@ static int video_getSetWindowMaximumSize(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } @@ -1463,30 +1463,30 @@ static int video_getSetWindowData(void *arg) /* Call against new test window */ window = createVideoSuiteTestWindow(title); - if (window == NULL) { + if (!window) { return TEST_ABORTED; } /* Create testdata */ datasize = SDLTest_RandomIntegerInRange(1, 32); referenceUserdata = SDLTest_RandomAsciiStringOfSize(datasize); - if (referenceUserdata == NULL) { + if (!referenceUserdata) { returnValue = TEST_ABORTED; goto cleanup; } userdata = SDL_strdup(referenceUserdata); - if (userdata == NULL) { + if (!userdata) { returnValue = TEST_ABORTED; goto cleanup; } datasize = SDLTest_RandomIntegerInRange(1, 32); referenceUserdata2 = SDLTest_RandomAsciiStringOfSize(datasize); - if (referenceUserdata2 == NULL) { + if (!referenceUserdata2) { returnValue = TEST_ABORTED; goto cleanup; } userdata2 = SDL_strdup(referenceUserdata2); - if (userdata2 == NULL) { + if (!userdata2) { returnValue = TEST_ABORTED; goto cleanup; } diff --git a/test/testbounds.c b/test/testbounds.c index b16a54f960448..cea2b229d4f88 100644 --- a/test/testbounds.c +++ b/test/testbounds.c @@ -22,7 +22,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testcontroller.c b/test/testcontroller.c index 4fd5627ab0962..89b1b4368c730 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -829,7 +829,7 @@ static void AddController(SDL_JoystickID id, SDL_bool verbose) } new_controllers = (Controller *)SDL_realloc(controllers, (num_controllers + 1) * sizeof(*controllers)); - if (new_controllers == NULL) { + if (!new_controllers) { return; } @@ -1092,7 +1092,7 @@ static void OpenVirtualGamepad(void) SDL_Log("Couldn't attach virtual device: %s\n", SDL_GetError()); } else { virtual_joystick = SDL_OpenJoystick(virtual_id); - if (virtual_joystick == NULL) { + if (!virtual_joystick) { SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); } } @@ -1818,7 +1818,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -1890,13 +1890,13 @@ int main(int argc, char *argv[]) screen_width = (int)SDL_ceilf(SCREEN_WIDTH * content_scale); screen_height = (int)SDL_ceilf(SCREEN_HEIGHT * content_scale); window = SDL_CreateWindow("SDL Controller Test", screen_width, screen_height, 0); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return 2; } screen = SDL_CreateRenderer(window, NULL, 0); - if (screen == NULL) { + if (!screen) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); SDL_DestroyWindow(window); return 2; @@ -1923,7 +1923,7 @@ int main(int argc, char *argv[]) type_area.y = (float)TITLE_HEIGHT / 2 - type_area.h / 2; image = CreateGamepadImage(screen); - if (image == NULL) { + if (!image) { SDL_DestroyRenderer(screen); SDL_DestroyWindow(window); return 2; diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index 12d54208caadd..ee90c782dba23 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -248,7 +248,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } for (i = 1; i < argc;) { diff --git a/test/testdisplayinfo.c b/test/testdisplayinfo.c index 009e45c3f2cbf..f11764e48fbe0 100644 --- a/test/testdisplayinfo.c +++ b/test/testdisplayinfo.c @@ -21,7 +21,7 @@ static void print_mode(const char *prefix, const SDL_DisplayMode *mode) { - if (mode == NULL) { + if (!mode) { return; } @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testdraw.c b/test/testdraw.c index d0c102c22a326..eccb8cad4b770 100644 --- a/test/testdraw.c +++ b/test/testdraw.c @@ -229,7 +229,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } for (i = 1; i < argc;) { diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index 375410590c379..e4c9a882d12c6 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -126,13 +126,13 @@ int main(int argc, char *argv[]) /* Create window and renderer for given surface */ window = SDL_CreateWindow("Chess Board", 640, 480, SDL_WINDOW_RESIZABLE); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation fail : %s\n", SDL_GetError()); return 1; } surface = SDL_GetWindowSurface(window); renderer = SDL_CreateSoftwareRenderer(surface); - if (renderer == NULL) { + if (!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Render creation for surface fail : %s\n", SDL_GetError()); return 1; } diff --git a/test/testdropfile.c b/test/testdropfile.c index a24547bb20cbe..9047a4a9d0abb 100644 --- a/test/testdropfile.c +++ b/test/testdropfile.c @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testerror.c b/test/testerror.c index b52c206c8afdd..1f3830f12c45a 100644 --- a/test/testerror.c +++ b/test/testerror.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) alive = 1; thread = SDL_CreateThread(ThreadFunc, NULL, "#1"); - if (thread == NULL) { + if (!thread) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } diff --git a/test/testevdev.c b/test/testevdev.c index 9758bbe246d0a..fbc362b21e1f9 100644 --- a/test/testevdev.c +++ b/test/testevdev.c @@ -1940,7 +1940,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 519ae466f16c1..aa240f49e6a0b 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -1000,7 +1000,7 @@ int main(int argc, char *argv[]) /* Create the sprite */ sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h); - if (sprite == NULL) { + if (!sprite) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture (%s)", SDL_GetError()); return_code = 3; goto quit; @@ -1009,7 +1009,7 @@ int main(int argc, char *argv[]) /* Allocate memory for the sprite info */ positions = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*positions)); velocities = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*velocities)); - if (positions == NULL || velocities == NULL) { + if (!positions || !velocities) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); return_code = 3; goto quit; diff --git a/test/testfile.c b/test/testfile.c index 1561f176d370f..157d6e8bec850 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -123,25 +123,25 @@ int main(int argc, char *argv[]) RWOP_ERR_QUIT(rwops); } rwops = SDL_RWFromFile(FBASENAME2, "wb"); - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } SDL_RWclose(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "wb+"); - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } SDL_RWclose(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "ab"); - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } SDL_RWclose(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "ab+"); - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } SDL_RWclose(rwops); @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) test : w mode, r mode, w+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "wb"); /* write only */ - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } if (10 != SDL_RWwrite(rwops, "1234567890", 10)) { @@ -174,7 +174,7 @@ int main(int argc, char *argv[]) SDL_RWclose(rwops); rwops = SDL_RWFromFile(FBASENAME1, "rb"); /* read mode, file must exist */ - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) { @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) /* test 3: same with w+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "wb+"); /* write + read + truncation */ - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } if (10 != SDL_RWwrite(rwops, "1234567890", 10)) { @@ -263,7 +263,7 @@ int main(int argc, char *argv[]) /* test 4: same in r+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "rb+"); /* write + read + file must exists, no truncation */ - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } if (10 != SDL_RWwrite(rwops, "1234567890", 10)) { @@ -314,7 +314,7 @@ int main(int argc, char *argv[]) /* test5 : append mode */ rwops = SDL_RWFromFile(FBASENAME1, "ab+"); /* write + read + append */ - if (rwops == NULL) { + if (!rwops) { RWOP_ERR_QUIT(rwops); } if (10 != SDL_RWwrite(rwops, "1234567890", 10)) { diff --git a/test/testfilesystem.c b/test/testfilesystem.c index bea7c0cccae72..4792d563e4571 100644 --- a/test/testfilesystem.c +++ b/test/testfilesystem.c @@ -23,7 +23,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) } base_path = SDL_GetBasePath(); - if (base_path == NULL) { + if (!base_path) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find base path: %s\n", SDL_GetError()); } else { @@ -50,7 +50,7 @@ int main(int argc, char *argv[]) } pref_path = SDL_GetPrefPath("libsdl", "test_filesystem"); - if (pref_path == NULL) { + if (!pref_path) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path: %s\n", SDL_GetError()); } else { @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) } pref_path = SDL_GetPrefPath(NULL, "test_filesystem"); - if (pref_path == NULL) { + if (!pref_path) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path without organization: %s\n", SDL_GetError()); } else { diff --git a/test/testgeometry.c b/test/testgeometry.c index d494d95607ba9..46e5a5e341685 100644 --- a/test/testgeometry.c +++ b/test/testgeometry.c @@ -173,7 +173,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -224,7 +224,7 @@ int main(int argc, char *argv[]) /* Create the windows, initialize the renderers, and load the textures */ sprites = (SDL_Texture **)SDL_malloc(state->num_windows * sizeof(*sprites)); - if (sprites == NULL) { + if (!sprites) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/test/testgl.c b/test/testgl.c index 0f592812b3c18..635782e9bc54b 100644 --- a/test/testgl.c +++ b/test/testgl.c @@ -220,7 +220,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testgles.c b/test/testgles.c index 0afae5428e52c..4be391f99a1ba 100644 --- a/test/testgles.c +++ b/test/testgles.c @@ -32,7 +32,7 @@ quit(int rc) { int i; - if (context != NULL) { + if (context) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (context == NULL) { + if (!context) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/test/testgles2.c b/test/testgles2.c index 6975adbafdd49..ad4223c32cb70 100644 --- a/test/testgles2.c +++ b/test/testgles2.c @@ -99,7 +99,7 @@ quit(int rc) { int i; - if (context != NULL) { + if (context) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -681,7 +681,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } for (i = 1; i < argc;) { @@ -749,7 +749,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (context == NULL) { + if (!context) { SDL_Log("Out of memory!\n"); quit(2); } diff --git a/test/testgles2_sdf.c b/test/testgles2_sdf.c index aadb031fd3e63..715ce718df6ca 100644 --- a/test/testgles2_sdf.c +++ b/test/testgles2_sdf.c @@ -91,7 +91,7 @@ quit(int rc) { int i; - if (context != NULL) { + if (context) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -449,7 +449,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } for (i = 1; i < argc;) { @@ -511,7 +511,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (context == NULL) { + if (!context) { SDL_Log("Out of memory!\n"); quit(2); } @@ -552,17 +552,17 @@ int main(int argc, char *argv[]) #if 1 path = GetNearbyFilename(f); - if (path == NULL) { + if (!path) { path = SDL_strdup(f); } - if (path == NULL) { + if (!path) { SDL_Log("out of memory\n"); exit(-1); } tmp = SDL_LoadBMP(path); - if (tmp == NULL) { + if (!tmp) { SDL_Log("missing image file: %s", path); exit(-1); } else { diff --git a/test/testhaptic.c b/test/testhaptic.c index 44fbb152e6232..0ace235403839 100644 --- a/test/testhaptic.c +++ b/test/testhaptic.c @@ -43,7 +43,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -87,7 +87,7 @@ int main(int argc, char **argv) } if (SDL_NumHaptics() > 0) { /* We'll just use index or the first force feedback device found */ - if (name == NULL) { + if (!name) { i = (index != -1) ? index : 0; } /* Try to find matching device */ @@ -106,7 +106,7 @@ int main(int argc, char **argv) } haptic = SDL_HapticOpen(i); - if (haptic == NULL) { + if (!haptic) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n", SDL_GetError()); return 1; @@ -297,7 +297,7 @@ int main(int argc, char **argv) } /* Quit */ - if (haptic != NULL) { + if (haptic) { SDL_HapticClose(haptic); } SDL_Quit(); diff --git a/test/testhittesting.c b/test/testhittesting.c index 955bef0d8a8d8..03b83071e28cb 100644 --- a/test/testhittesting.c +++ b/test/testhittesting.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -140,7 +140,7 @@ int main(int argc, char **argv) if (e.key.keysym.sym == SDLK_ESCAPE) { done = 1; } else if (e.key.keysym.sym == SDLK_x) { - if (areas == NULL) { + if (!areas) { areas = drag_areas; numareas = SDL_arraysize(drag_areas); } else { diff --git a/test/testhotplug.c b/test/testhotplug.c index 24ec6f481072d..82b389de953cc 100644 --- a/test/testhotplug.c +++ b/test/testhotplug.c @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) keepGoing = SDL_FALSE; break; case SDL_EVENT_JOYSTICK_ADDED: - if (joystick != NULL) { + if (joystick) { SDL_Log("Only one joystick supported by this test\n"); } else { joystick = SDL_OpenJoystick(event.jdevice.which); diff --git a/test/testiconv.c b/test/testiconv.c index daabe270ccb28..0fd5cfbfb2eaf 100644 --- a/test/testiconv.c +++ b/test/testiconv.c @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) fname = GetResourceFilename(fname, "utf8.txt"); file = fopen(fname, "rb"); - if (file == NULL) { + if (!file) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to open %s\n", fname); return 1; } diff --git a/test/testime.c b/test/testime.c index 84d3aecbbdee9..4e428a3e9ca74 100644 --- a/test/testime.c +++ b/test/testime.c @@ -97,7 +97,7 @@ static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np) } n = (n << 4) | c; } - if (np != NULL) { + if (np) { *np = n; } return 1; @@ -116,7 +116,7 @@ static int unifont_init(const char *fontname) /* Allocate memory for the glyph data so the file can be closed after initialization. */ unifontGlyph = (struct UnifontGlyph *)SDL_malloc(unifontGlyphSize); - if (unifontGlyph == NULL) { + if (!unifontGlyph) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for glyph data.\n", (int)(unifontGlyphSize + 1023) / 1024); return -1; } @@ -124,20 +124,20 @@ static int unifont_init(const char *fontname) /* Allocate memory for texture pointers for all renderers. */ unifontTexture = (SDL_Texture **)SDL_malloc(unifontTextureSize); - if (unifontTexture == NULL) { + if (!unifontTexture) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for texture pointer data.\n", (int)(unifontTextureSize + 1023) / 1024); return -1; } SDL_memset(unifontTexture, 0, unifontTextureSize); filename = GetResourceFilename(NULL, fontname); - if (filename == NULL) { + if (!filename) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); return -1; } hexFile = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (hexFile == NULL) { + if (!hexFile) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname); return -1; } @@ -279,7 +279,7 @@ static int unifont_load_texture(Uint32 textureID) } textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE); - if (textureRGBA == NULL) { + if (!textureRGBA) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024); return -1; } @@ -334,7 +334,7 @@ static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_FRect *ds } } texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID]; - if (texture != NULL) { + if (texture) { const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE; srcrect.x = (float)(cInTex % UNIFONT_GLYPHS_IN_ROW * 16); srcrect.y = (float)(cInTex / UNIFONT_GLYPHS_IN_ROW * 16); @@ -348,12 +348,12 @@ static void unifont_cleanup(void) int i, j; for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; - if (state->windows[i] == NULL || renderer == NULL) { + if (state->windows[i] == NULL || !renderer) { continue; } for (j = 0; j < UNIFONT_NUM_TEXTURES; j++) { SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j]; - if (tex != NULL) { + if (tex) { SDL_DestroyTexture(tex); } } @@ -538,7 +538,7 @@ static void _Redraw(int rendererID) if (cursor) { char *p = utf8_advance(markedText, cursor); char c = 0; - if (p == NULL) { + if (!p) { p = &markedText[SDL_strlen(markedText)]; } @@ -639,7 +639,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -677,7 +677,7 @@ int main(int argc, char *argv[]) TTF_Init(); font = TTF_OpenFont(fontname, DEFAULT_PTSIZE); - if (font == NULL) { + if (!font) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError()); return -1; } diff --git a/test/testintersections.c b/test/testintersections.c index 41b20ec1694c2..380c8e71026c6 100644 --- a/test/testintersections.c +++ b/test/testintersections.c @@ -292,7 +292,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testkeys.c b/test/testkeys.c index 0db5a4b3dd87e..c64b09b2faf39 100644 --- a/test/testkeys.c +++ b/test/testkeys.c @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testloadso.c b/test/testloadso.c index c938d94157d19..7a55f0a76e08a 100644 --- a/test/testloadso.c +++ b/test/testloadso.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -88,13 +88,13 @@ int main(int argc, char *argv[]) } lib = SDL_LoadObject(libname); - if (lib == NULL) { + if (!lib) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_LoadObject('%s') failed: %s\n", libname, SDL_GetError()); retval = 3; } else { fn = (fntype)SDL_LoadFunction(lib, symname); - if (fn == NULL) { + if (!fn) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_LoadFunction('%s') failed: %s\n", symname, SDL_GetError()); retval = 4; diff --git a/test/testlocale.c b/test/testlocale.c index d0c3239767b36..8e7366bdb5f51 100644 --- a/test/testlocale.c +++ b/test/testlocale.c @@ -16,7 +16,7 @@ static void log_locales(void) { SDL_Locale *locales = SDL_GetPreferredLocales(); - if (locales == NULL) { + if (!locales) { SDL_Log("Couldn't determine locales: %s", SDL_GetError()); } else { SDL_Locale *l; @@ -40,7 +40,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testlock.c b/test/testlock.c index edf259ad4656c..221bd4a708654 100644 --- a/test/testlock.c +++ b/test/testlock.c @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -182,7 +182,7 @@ int main(int argc, char *argv[]) SDL_AtomicSet(&doterminate, 0); mutex = SDL_CreateMutex(); - if (mutex == NULL) { + if (!mutex) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError()); exit(1); } diff --git a/test/testmessage.c b/test/testmessage.c index c490787d318cc..6723a6a7a4dab 100644 --- a/test/testmessage.c +++ b/test/testmessage.c @@ -89,7 +89,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testmouse.c b/test/testmouse.c index 5f5ef10d54eb9..b7852e7442d70 100644 --- a/test/testmouse.c +++ b/test/testmouse.c @@ -87,7 +87,7 @@ static void DrawObject(SDL_Renderer *renderer, Object *object) static void DrawObjects(SDL_Renderer *renderer) { Object *next = objects; - while (next != NULL) { + while (next) { DrawObject(renderer, next); next = next->next; } @@ -97,7 +97,7 @@ static void AppendObject(Object *object) { if (objects) { Object *next = objects; - while (next->next != NULL) { + while (next->next) { next = next->next; } next->next = object; @@ -133,7 +133,7 @@ static void loop(void *arg) break; case SDL_EVENT_MOUSE_MOTION: - if (active == NULL) { + if (!active) { break; } @@ -142,7 +142,7 @@ static void loop(void *arg) break; case SDL_EVENT_MOUSE_BUTTON_DOWN: - if (active == NULL) { + if (!active) { active = SDL_calloc(1, sizeof(*active)); active->x1 = active->x2 = event.button.x; active->y1 = active->y2 = event.button.y; @@ -176,7 +176,7 @@ static void loop(void *arg) break; case SDL_EVENT_MOUSE_BUTTON_UP: - if (active == NULL) { + if (!active) { break; } @@ -259,7 +259,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testmultiaudio.c b/test/testmultiaudio.c index ecf0316cdecb3..45da833513888 100644 --- a/test/testmultiaudio.c +++ b/test/testmultiaudio.c @@ -146,7 +146,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -184,7 +184,7 @@ int main(int argc, char **argv) filename = GetResourceFilename(filename, "sample.wav"); devices = SDL_GetAudioOutputDevices(&devcount); - if (devices == NULL) { + if (!devices) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!"); } else { /* Load the wave file into memory */ diff --git a/test/testnative.c b/test/testnative.c index 166e5d8c9a987..cc5b1b071ad98 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -48,7 +48,7 @@ static void quit(int rc) { SDL_Quit(); - if (native_window != NULL && factory != NULL) { + if (native_window && factory) { factory->DestroyNativeWindow(native_window); } SDLTest_CommonDestroyState(state); @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -135,19 +135,19 @@ int main(int argc, char *argv[]) break; } } - if (factory == NULL) { + if (!factory) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find native window code for %s driver\n", driver); quit(2); } SDL_Log("Creating native window for %s driver\n", driver); native_window = factory->CreateNativeWindow(WINDOW_W, WINDOW_H); - if (native_window == NULL) { + if (!native_window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create native window\n"); quit(3); } window = SDL_CreateWindowFrom(native_window); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window: %s\n", SDL_GetError()); quit(4); } @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) /* Create the renderer */ renderer = SDL_CreateRenderer(window, NULL, 0); - if (renderer == NULL) { + if (!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); quit(5); } @@ -165,7 +165,7 @@ int main(int argc, char *argv[]) SDL_RenderClear(renderer); sprite = LoadTexture(renderer, "icon.bmp", SDL_TRUE, NULL, NULL); - if (sprite == NULL) { + if (!sprite) { quit(6); } @@ -174,7 +174,7 @@ int main(int argc, char *argv[]) SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h); positions = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*positions)); velocities = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*velocities)); - if (positions == NULL || velocities == NULL) { + if (!positions || !velocities) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/test/testnativew32.c b/test/testnativew32.c index 13603b666f042..d3cbe125b3a8b 100644 --- a/test/testnativew32.c +++ b/test/testnativew32.c @@ -68,7 +68,7 @@ CreateWindowNative(int w, int h) CreateWindow("SDL Test", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, w, h, NULL, NULL, GetModuleHandle(NULL), NULL); - if (hwnd == NULL) { + if (!hwnd) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; diff --git a/test/testoffscreen.c b/test/testoffscreen.c index 79852031b6dfb..3c2fc83f85f80 100644 --- a/test/testoffscreen.c +++ b/test/testoffscreen.c @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -125,14 +125,14 @@ int main(int argc, char *argv[]) /* If OPENGL fails to init it will fallback to using a framebuffer for rendering */ window = SDL_CreateWindow("Offscreen Test", width, height, 0); - if (window == NULL) { + if (!window) { SDL_Log("Couldn't create window: %s\n", SDL_GetError()); return SDL_FALSE; } renderer = SDL_CreateRenderer(window, NULL, 0); - if (renderer == NULL) { + if (!renderer) { SDL_Log("Couldn't create renderer: %s\n", SDL_GetError()); return SDL_FALSE; diff --git a/test/testoverlay.c b/test/testoverlay.c index 5d42efc74d7f9..7d693aaaf4c8f 100644 --- a/test/testoverlay.c +++ b/test/testoverlay.c @@ -231,7 +231,7 @@ static void MoveSprites(SDL_Renderer *renderer) } tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]); - if (tmp == NULL) { + if (!tmp) { SDL_Log("Error %s", SDL_GetError()); quit(7); } @@ -326,7 +326,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -430,20 +430,20 @@ int main(int argc, char **argv) } RawMooseData = (Uint8 *)SDL_malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); - if (RawMooseData == NULL) { + if (!RawMooseData) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't allocate memory for movie !\n"); quit(1); } /* load the trojan moose images */ filename = GetResourceFilename(NULL, "moose.dat"); - if (filename == NULL) { + if (!filename) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); quit(2); } handle = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (handle == NULL) { + if (!handle) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); quit(2); } @@ -466,7 +466,7 @@ int main(int argc, char **argv) if (streaming) { MooseTexture = SDL_CreateTexture(renderer, yuv_format, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); - if (MooseTexture == NULL) { + if (!MooseTexture) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); quit(5); } @@ -479,7 +479,7 @@ int main(int argc, char **argv) for (i = 0; i < MOOSEFRAMES_COUNT; i++) { /* Create RGB SDL_Surface */ SDL_Surface *mooseRGBSurface = SDL_CreateSurface(MOOSEPIC_W, MOOSEPIC_H, SDL_PIXELFORMAT_RGB24); - if (mooseRGBSurface == NULL) { + if (!mooseRGBSurface) { quit(6); } diff --git a/test/testplatform.c b/test/testplatform.c index d310fca252d66..a1f5ee06aa2c9 100644 --- a/test/testplatform.c +++ b/test/testplatform.c @@ -365,7 +365,7 @@ static int Test64Bit(SDL_bool verbose) LL_Test *t; int failed = 0; - for (t = LL_Tests; t->routine != NULL; t++) { + for (t = LL_Tests; t->routine; t++) { unsigned long long result = 0; unsigned int *al = (unsigned int *)&t->a; unsigned int *bl = (unsigned int *)&t->b; @@ -447,7 +447,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testpopup.c b/test/testpopup.c index 9631536ffa16d..ec903d3ff58a3 100644 --- a/test/testpopup.c +++ b/test/testpopup.c @@ -194,7 +194,7 @@ static void loop(void) /* Show the tooltip if the delay period has elapsed */ if (SDL_GetTicks() > tooltip_timer) { - if (tooltip.win == NULL) { + if (!tooltip.win) { create_popup(&tooltip, SDL_FALSE); } } @@ -244,7 +244,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testpower.c b/test/testpower.c index f9baefb8ae012..a65334419cb84 100644 --- a/test/testpower.c +++ b/test/testpower.c @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testqsort.c b/test/testqsort.c index b4a17c2dfc8fe..7299e907ec348 100644 --- a/test/testqsort.c +++ b/test/testqsort.c @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testrelative.c b/test/testrelative.c index c02518e89e47a..3ad4d70ea18c8 100644 --- a/test/testrelative.c +++ b/test/testrelative.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testrendercopyex.c b/test/testrendercopyex.c index ffb522957e32c..7ca0b8aae1f1c 100644 --- a/test/testrendercopyex.c +++ b/test/testrendercopyex.c @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testrendertarget.c b/test/testrendertarget.c index abaf09c66b1c5..427351e48c71f 100644 --- a/test/testrendertarget.c +++ b/test/testrendertarget.c @@ -141,7 +141,7 @@ Draw(DrawState *s) SDL_GetRenderViewport(s->renderer, &viewport); target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h); - if (target == NULL) { + if (!target) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create render target texture: %s\n", SDL_GetError()); return SDL_FALSE; } @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } for (i = 1; i < argc;) { diff --git a/test/testresample.c b/test/testresample.c index 83661d3459646..b5c006d4c5ede 100644 --- a/test/testresample.c +++ b/test/testresample.c @@ -41,7 +41,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -116,7 +116,7 @@ int main(int argc, char **argv) /* write out a WAV header... */ io = SDL_RWFromFile(file_out, "wb"); - if (io == NULL) { + if (!io) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fopen('%s') failed: %s\n", file_out, SDL_GetError()); ret = 5; goto end; diff --git a/test/testrumble.c b/test/testrumble.c index 965179e76d347..624fbff51cba2 100644 --- a/test/testrumble.c +++ b/test/testrumble.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -88,7 +88,7 @@ int main(int argc, char **argv) SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics()); if (SDL_NumHaptics() > 0) { /* We'll just use index or the first force feedback device found */ - if (name == NULL) { + if (!name) { i = (index != -1) ? index : 0; } /* Try to find matching device */ @@ -107,7 +107,7 @@ int main(int argc, char **argv) } haptic = SDL_HapticOpen(i); - if (haptic == NULL) { + if (!haptic) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n", SDL_GetError()); return 1; @@ -146,7 +146,7 @@ int main(int argc, char **argv) SDL_Delay(2000); /* Quit */ - if (haptic != NULL) { + if (haptic) { SDL_HapticClose(haptic); } diff --git a/test/testrwlock.c b/test/testrwlock.c index 7952a2ef74aa0..03c76470811d0 100644 --- a/test/testrwlock.c +++ b/test/testrwlock.c @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) SDL_AtomicSet(&doterminate, 0); rwlock = SDL_CreateRWLock(); - if (rwlock == NULL) { + if (!rwlock) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create rwlock: %s\n", SDL_GetError()); SDL_Quit(); SDLTest_CommonDestroyState(state); diff --git a/test/testscale.c b/test/testscale.c index 16acb3f837902..091bb18c16d52 100644 --- a/test/testscale.c +++ b/test/testscale.c @@ -107,7 +107,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testsem.c b/test/testsem.c index 8da58613f18b4..12201cc474b65 100644 --- a/test/testsem.c +++ b/test/testsem.c @@ -261,7 +261,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testsensor.c b/test/testsensor.c index be200fddcb4ad..e9d0e0883047a 100644 --- a/test/testsensor.c +++ b/test/testsensor.c @@ -38,7 +38,7 @@ static const char *GetSensorTypeString(SDL_SensorType type) static void HandleSensorEvent(SDL_SensorEvent *event) { SDL_Sensor *sensor = SDL_GetSensorFromInstanceID(event->which); - if (sensor == NULL) { + if (!sensor) { SDL_Log("Couldn't get sensor for sensor event\n"); return; } @@ -64,7 +64,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -97,7 +97,7 @@ int main(int argc, char **argv) if (SDL_GetSensorInstanceType(sensors[i]) != SDL_SENSOR_UNKNOWN) { SDL_Sensor *sensor = SDL_OpenSensor(sensors[i]); - if (sensor == NULL) { + if (!sensor) { SDL_Log("Couldn't open sensor %" SDL_PRIu32 ": %s\n", sensors[i], SDL_GetError()); } else { ++num_opened; diff --git a/test/testshader.c b/test/testshader.c index 2de2380dfda94..3cb552fca4b51 100644 --- a/test/testshader.c +++ b/test/testshader.c @@ -141,7 +141,7 @@ static SDL_bool CompileShader(GLhandleARB shader, const char *source) glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); - if (info == NULL) { + if (!info) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { glGetInfoLogARB(shader, length, NULL, info); @@ -169,7 +169,7 @@ static SDL_bool LinkProgram(ShaderData *data) glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); - if (info == NULL) { + if (!info) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { glGetInfoLogARB(data->program, length, NULL, info); @@ -327,7 +327,7 @@ SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ image = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_RGBA32); - if (image == NULL) { + if (!image) { return 0; } @@ -454,7 +454,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -489,7 +489,7 @@ int main(int argc, char **argv) /* Create a 640x480 OpenGL screen */ window = SDL_CreateWindow("Shader Demo", 640, 480, SDL_WINDOW_OPENGL); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL window: %s\n", SDL_GetError()); SDL_Quit(); exit(2); @@ -505,7 +505,7 @@ int main(int argc, char **argv) surface = SDL_LoadBMP(filename); SDL_free(filename); - if (surface == NULL) { + if (!surface) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError()); SDL_Quit(); exit(3); diff --git a/test/testshape.c b/test/testshape.c index 6965b3aca73e8..c5950b3f7be54 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -102,18 +102,18 @@ static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_Windo g_shape_surface = NULL; } - if (shape == NULL) { + if (!shape) { return SDL_SetError("shape"); } - if (shape_mode == NULL) { + if (!shape_mode) { return SDL_SetError("shape_mode"); } g_bitmap_w = shape->w; g_bitmap_h = shape->h; g_bitmap = (Uint8*) SDL_malloc(shape->w * shape->h); - if (g_bitmap == NULL) { + if (!g_bitmap) { return SDL_OutOfMemory(); } @@ -170,7 +170,7 @@ static void render(SDL_Renderer *renderer, SDL_Texture *texture) SDL_SetRenderDrawColor(renderer, r, g, b, a); } } else { - if (g_shape_texture == NULL) { + if (!g_shape_texture) { SDL_BlendMode bm; g_shape_texture = SDL_CreateTextureFromSurface(renderer, g_shape_surface); @@ -212,7 +212,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -294,13 +294,13 @@ int main(int argc, char **argv) } window = SDL_CreateWindow("SDL_Shape test", SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, SDL_WINDOW_TRANSPARENT); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create shaped window for SDL_Shape."); rc = -4; goto ret; } renderer = SDL_CreateRenderer(window, NULL, 0); - if (renderer == NULL) { + if (!renderer) { SDL_DestroyWindow(window); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create rendering context for SDL_Shape window."); rc = -4; diff --git a/test/testsprite.c b/test/testsprite.c index 217dc181b4cef..a754314149e5a 100644 --- a/test/testsprite.c +++ b/test/testsprite.c @@ -434,7 +434,7 @@ int SDL_AppInit(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return -1; } @@ -529,7 +529,7 @@ int SDL_AppInit(int argc, char *argv[]) /* Create the windows, initialize the renderers, and load the textures */ sprites = (SDL_Texture **)SDL_malloc(state->num_windows * sizeof(*sprites)); - if (sprites == NULL) { + if (!sprites) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); return -1; } @@ -545,7 +545,7 @@ int SDL_AppInit(int argc, char *argv[]) /* Allocate memory for the sprite info */ positions = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*positions)); velocities = (SDL_FRect *)SDL_malloc(num_sprites * sizeof(*velocities)); - if (positions == NULL || velocities == NULL) { + if (!positions || !velocities) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); return -1; } diff --git a/test/testspriteminimal.c b/test/testspriteminimal.c index 0d89c5e3fbd2c..3981deec23951 100644 --- a/test/testspriteminimal.c +++ b/test/testspriteminimal.c @@ -133,7 +133,7 @@ int main(int argc, char *argv[]) sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h); - if (sprite == NULL) { + if (!sprite) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture (%s)", SDL_GetError()); return_code = 3; goto quit; diff --git a/test/teststreaming.c b/test/teststreaming.c index dcd5b4423ee91..cf99bc4767689 100644 --- a/test/teststreaming.c +++ b/test/teststreaming.c @@ -139,7 +139,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -158,13 +158,13 @@ int main(int argc, char **argv) /* load the moose images */ filename = GetResourceFilename(NULL, "moose.dat"); - if (filename == NULL) { + if (!filename) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); return -1; } handle = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (handle == NULL) { + if (!handle) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); quit(2); } @@ -173,19 +173,19 @@ int main(int argc, char **argv) /* Create the window and renderer */ window = SDL_CreateWindow("Happy Moose", MOOSEPIC_W * 4, MOOSEPIC_H * 4, SDL_WINDOW_RESIZABLE); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); quit(3); } renderer = SDL_CreateRenderer(window, NULL, 0); - if (renderer == NULL) { + if (!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); quit(4); } MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); - if (MooseTexture == NULL) { + if (!MooseTexture) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); quit(5); } diff --git a/test/testsurround.c b/test/testsurround.c index 1edd1faf69719..d263fdcb2c329 100644 --- a/test/testsurround.c +++ b/test/testsurround.c @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) active_channel = 0; stream = SDL_OpenAudioDeviceStream(devices[i], &spec, fill_buffer, NULL); - if (stream == NULL) { + if (!stream) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_OpenAudioDeviceStream() failed: %s\n", SDL_GetError()); continue; } diff --git a/test/testthread.c b/test/testthread.c index 8bcbf4b302d45..c840937d0952e 100644 --- a/test/testthread.c +++ b/test/testthread.c @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -139,7 +139,7 @@ int main(int argc, char *argv[]) alive = 1; thread = SDL_CreateThread(ThreadFunc, "One", "#1"); - if (thread == NULL) { + if (!thread) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) alive = 1; (void)signal(SIGTERM, killed); thread = SDL_CreateThread(ThreadFunc, "Two", "#2"); - if (thread == NULL) { + if (!thread) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } diff --git a/test/testtimer.c b/test/testtimer.c index 76c806b54147e..1901d5cdb3d9b 100644 --- a/test/testtimer.c +++ b/test/testtimer.c @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testutils.c b/test/testutils.c index f49b38e1c4fb6..f6eb3780eeaba 100644 --- a/test/testutils.c +++ b/test/testutils.c @@ -28,13 +28,13 @@ GetNearbyFilename(const char *file) base = SDL_GetBasePath(); - if (base != NULL) { + if (base) { SDL_RWops *rw; size_t len = SDL_strlen(base) + SDL_strlen(file) + 1; path = SDL_malloc(len); - if (path == NULL) { + if (!path) { SDL_free(base); SDL_OutOfMemory(); return NULL; @@ -54,7 +54,7 @@ GetNearbyFilename(const char *file) } path = SDL_strdup(file); - if (path == NULL) { + if (!path) { SDL_OutOfMemory(); } return path; @@ -72,10 +72,10 @@ GetNearbyFilename(const char *file) char * GetResourceFilename(const char *user_specified, const char *def) { - if (user_specified != NULL) { + if (user_specified) { char *ret = SDL_strdup(user_specified); - if (ret == NULL) { + if (!ret) { SDL_OutOfMemory(); } @@ -105,12 +105,12 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, path = GetNearbyFilename(file); - if (path != NULL) { + if (path) { file = path; } temp = SDL_LoadBMP(file); - if (temp == NULL) { + if (!temp) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError()); } else { /* Set transparent pixel as the pixel at (0,0) */ @@ -137,16 +137,16 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, } } - if (width_out != NULL) { + if (width_out) { *width_out = temp->w; } - if (height_out != NULL) { + if (height_out) { *height_out = temp->h; } texture = SDL_CreateTextureFromSurface(renderer, temp); - if (texture == NULL) { + if (!texture) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError()); } } diff --git a/test/testviewport.c b/test/testviewport.c index 006d3c2442ab3..4a900ad908c4b 100644 --- a/test/testviewport.c +++ b/test/testviewport.c @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) sprite = LoadTexture(state->renderers[0], "icon.bmp", SDL_TRUE, &sprite_w, &sprite_h); - if (sprite == NULL) { + if (!sprite) { quit(2); } diff --git a/test/testvulkan.c b/test/testvulkan.c index 4555f8705a2ee..231e644fff710 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -293,7 +293,7 @@ static void findPhysicalDevice(void) quit(2); } physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); - if (physicalDevices == NULL) { + if (!physicalDevices) { SDL_OutOfMemory(); quit(2); } @@ -327,7 +327,7 @@ static void findPhysicalDevice(void) SDL_free(queueFamiliesProperties); queueFamiliesPropertiesAllocatedSize = queueFamiliesCount; queueFamiliesProperties = (VkQueueFamilyProperties *)SDL_malloc(sizeof(VkQueueFamilyProperties) * queueFamiliesPropertiesAllocatedSize); - if (queueFamiliesProperties == NULL) { + if (!queueFamiliesProperties) { SDL_free(physicalDevices); SDL_free(deviceExtensions); SDL_OutOfMemory(); @@ -389,7 +389,7 @@ static void findPhysicalDevice(void) SDL_free(deviceExtensions); deviceExtensionsAllocatedSize = deviceExtensionCount; deviceExtensions = SDL_malloc(sizeof(VkExtensionProperties) * deviceExtensionsAllocatedSize); - if (deviceExtensions == NULL) { + if (!deviceExtensions) { SDL_free(physicalDevices); SDL_free(queueFamiliesProperties); SDL_OutOfMemory(); @@ -918,7 +918,7 @@ static void initVulkan(void) SDL_Vulkan_LoadLibrary(NULL); vulkanContexts = (VulkanContext *)SDL_calloc(state->num_windows, sizeof(VulkanContext)); - if (vulkanContexts == NULL) { + if (!vulkanContexts) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); quit(2); } @@ -1079,7 +1079,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testwm.c b/test/testwm.c index 7de55701ec4a8..6efcb80276eb6 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -205,7 +205,7 @@ static void loop(void) } if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) { SDL_Window *window = SDL_GetMouseFocus(); - if (highlighted_mode != NULL && window != NULL) { + if (highlighted_mode && window) { SDL_memcpy(&state->fullscreen_mode, highlighted_mode, sizeof(state->fullscreen_mode)); SDL_SetWindowFullscreenMode(window, highlighted_mode); } @@ -215,7 +215,7 @@ static void loop(void) for (i = 0; i < state->num_windows; ++i) { SDL_Window *window = state->windows[i]; SDL_Renderer *renderer = state->renderers[i]; - if (window != NULL && renderer != NULL) { + if (window && renderer) { float y = 0.0f; SDL_Rect viewport; SDL_FRect menurect; @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (state == NULL) { + if (!state) { return 1; } diff --git a/test/testyuv.c b/test/testyuv.c index afe3cac518aa3..6ba996fd0ea53 100644 --- a/test/testyuv.c +++ b/test/testyuv.c @@ -73,7 +73,7 @@ static SDL_bool verify_yuv_data(Uint32 format, const Uint8 *yuv, int yuv_pitch, SDL_bool result = SDL_FALSE; rgb = (Uint8 *)SDL_malloc(size); - if (rgb == NULL) { + if (!rgb) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory"); return SDL_FALSE; } @@ -124,7 +124,7 @@ static int run_automated_tests(int pattern_size, int extra_pitch) int yuv1_pitch, yuv2_pitch; int result = -1; - if (pattern == NULL || yuv1 == NULL || yuv2 == NULL) { + if (!pattern || !yuv1 || !yuv2) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate test surfaces"); goto done; } @@ -263,7 +263,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } @@ -372,7 +372,7 @@ int main(int argc, char **argv) bmp = SDL_LoadBMP(filename); original = SDL_ConvertSurfaceFormat(bmp, SDL_PIXELFORMAT_RGB24); SDL_DestroySurface(bmp); - if (original == NULL) { + if (!original) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); return 3; } @@ -384,7 +384,7 @@ int main(int argc, char **argv) pitch = CalculateYUVPitch(yuv_format, original->w); converted = SDL_CreateSurface(original->w, original->h, rgb_format); - if (converted == NULL) { + if (!converted) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create converted surface: %s\n", SDL_GetError()); return 3; } @@ -397,13 +397,13 @@ int main(int argc, char **argv) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%d iterations in %" SDL_PRIu64 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations); window = SDL_CreateWindow("YUV test", original->w, original->h, 0); - if (window == NULL) { + if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return 4; } renderer = SDL_CreateRenderer(window, NULL, 0); - if (renderer == NULL) { + if (!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); return 4; } diff --git a/test/torturethread.c b/test/torturethread.c index c2a0dd1a81865..033952619b44e 100644 --- a/test/torturethread.c +++ b/test/torturethread.c @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); - if (state == NULL) { + if (!state) { return 1; } From 2d6bae70b4374a96e0d69c2396a3182d6973afff Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 9 Nov 2023 23:33:28 +0100 Subject: [PATCH 310/725] Older gcc does not support #pragma GCC diagnostic inside functions --- src/video/x11/SDL_x11sym.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 9fdb205877310..fea44c9b86073 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -194,7 +194,7 @@ SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c #endif /* XKeycodeToKeysym is a deprecated function */ -#if defined(__GNUC__) || defined(__clang__) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif @@ -203,7 +203,7 @@ SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),re #else SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return) #endif -#if defined(__GNUC__) || defined(__clang__) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__) #pragma GCC diagnostic pop #endif From 74f3643bfae613afe2b787ea5e91720064b165a5 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 9 Nov 2023 19:48:56 -0500 Subject: [PATCH 311/725] wayland: Add missing break to switch statement --- src/video/wayland/SDL_waylandwindow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 91a82d7619706..b923c47191f3e 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -661,6 +661,7 @@ static void handle_configure_xdg_toplevel(void *data, break; case XDG_TOPLEVEL_STATE_SUSPENDED: suspended = SDL_TRUE; + break; default: break; } From aa7baf63aa2cb8ca2d92f0bef32388fd7218762b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 9 Nov 2023 20:11:23 -0500 Subject: [PATCH 312/725] Sync wiki -> headers. --- include/SDL3/SDL_properties.h | 8 +++- include/SDL3/SDL_render.h | 7 +-- include/SDL3/SDL_system.h | 10 ++++- include/SDL3/SDL_video.h | 76 ++++++++++++++++---------------- include/SDL3/SDL_video_capture.h | 28 +++++++----- 5 files changed, 74 insertions(+), 55 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 588bdfc4ca497..17b280ae19e0a 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -124,7 +124,8 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value); /** - * Set a property on a set of properties with a cleanup function that is called when the property is deleted + * Set a property on a set of properties with a cleanup function that is + * called when the property is deleted * * \param props the properties to modify * \param name the name of the property to modify @@ -147,7 +148,10 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c /** * Get a property on a set of properties * - * By convention, the names of properties that SDL exposes on objects will start with "SDL.", and properties that SDL uses internally will start with "SDL.internal.". These should be considered read-only and should not be modified by applications. + * By convention, the names of properties that SDL exposes on objects will + * start with "SDL.", and properties that SDL uses internally will start with + * "SDL.internal.". These should be considered read-only and should not be + * modified by applications. * * \param props the properties to query * \param name the name of the property to query diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 5b745b54eac1a..73c2c40cf8bfb 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -309,11 +309,12 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: - * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer + * The following properties are provided by SDL: "SDL.renderer.d3d9.device" - + * the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer + * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with + * the renderer * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index a2cd27d8704cd..04b2cce56f06f 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -47,10 +47,13 @@ extern "C" { typedef struct tagMSG MSG; typedef SDL_bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); + /** * Set a callback for every Windows message, run before TranslateMessage(). * - * The callback may modify the message, and should return SDL_TRUE if the message should continue to be processed, or SDL_FALSE to prevent further processing. + * The callback may modify the message, and should return SDL_TRUE if the + * message should continue to be processed, or SDL_FALSE to prevent further + * processing. * * \param callback The SDL_WindowsMessageHook function to call. * \param userdata a pointer to pass to every iteration of `callback` @@ -106,10 +109,13 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, typedef union _XEvent XEvent; typedef SDL_bool (SDLCALL *SDL_X11EventHook)(void *userdata, XEvent *xevent); + /** * Set a callback for every X11 event * - * The callback may modify the event, and should return SDL_TRUE if the event should continue to be processed, or SDL_FALSE to prevent further processing. + * The callback may modify the event, and should return SDL_TRUE if the event + * should continue to be processed, or SDL_FALSE to prevent further + * processing. * * \param callback The SDL_X11EventHook function to call. * \param userdata a pointer to pass to every iteration of `callback` diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 8c89fae443a25..8a466a68b4c94 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -936,53 +936,53 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following properties are provided by SDL: * - * On Android: - * "SDL.window.android.window" - the ANativeWindow associated with the window - * "SDL.window.android.surface" - the EGLSurface associated with the window + * On Android: "SDL.window.android.window" - the ANativeWindow associated with + * the window "SDL.window.android.surface" - the EGLSurface associated with + * the window * - * On iOS: - * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window - * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * On iOS: "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow + * associated with the window "SDL.window.uikit.metal_view_tag" - the + * NSInteger tag assocated with metal views on the window * - * On KMS/DRM: - * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) - * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window - * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window + * On KMS/DRM: "SDL.window.kmsdrm.dev_index" - the device index associated + * with the window (e.g. the X in /dev/dri/cardX) "SDL.window.kmsdrm.drm_fd" - + * the DRM FD associated with the window "SDL.window.kmsdrm.gbm_dev" - the GBM + * device associated with the window * - * On macOS: - * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window - * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * On macOS: "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow + * associated with the window "SDL.window.cocoa.metal_view_tag" - the + * NSInteger tag assocated with metal views on the window * - * On Vivante: - * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window - * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window - * "SDL.window.vivante.surface" - the EGLSurface associated with the window + * On Vivante: "SDL.window.vivante.display" - the EGLNativeDisplayType + * associated with the window "SDL.window.vivante.window" - the + * EGLNativeWindowType associated with the window "SDL.window.vivante.surface" + * - the EGLSurface associated with the window * - * On UWP: - * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window + * On UWP: "SDL.window.winrt.window" - the IInspectable CoreWindow associated + * with the window * - * On Windows: - * "SDL.window.win32.hwnd" - the HWND associated with the window + * On Windows: "SDL.window.win32.hwnd" - the HWND associated with the window * "SDL.window.win32.hdc" - the HDC associated with the window * "SDL.window.win32.instance" - the HINSTANCE associated with the window * - * On Wayland: - * "SDL.window.wayland.registry" - the wl_registry associated with the window - * "SDL.window.wayland.display" - the wl_display associated with the window - * "SDL.window.wayland.surface" - the wl_surface associated with the window - * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window - * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window - * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window - * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode - * - * Note: The xdg_* window objects do not internally persist across window show/hide calls. - * They will be null if the window is hidden and must be queried each time it is shown. - * - * On X11: - * "SDL.window.x11.display" - the X11 Display associated with the window - * "SDL.window.x11.screen" - the screen number associated with the window - * "SDL.window.x11.window" - the X11 Window associated with the window + * On Wayland: "SDL.window.wayland.registry" - the wl_registry associated with + * the window "SDL.window.wayland.display" - the wl_display associated with + * the window "SDL.window.wayland.surface" - the wl_surface associated with + * the window "SDL.window.wayland.egl_window" - the wl_egl_window associated + * with the window "SDL.window.wayland.xdg_surface" - the xdg_surface + * associated with the window "SDL.window.wayland.xdg_toplevel" - the + * xdg_toplevel role associated with the window "SDL.window.wayland.xdg_popup" + * - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with + * the window, in popup mode + * + * Note: The xdg_* window objects do not internally persist across window + * show/hide calls. They will be null if the window is hidden and must be + * queried each time it is shown. + * + * On X11: "SDL.window.x11.display" - the X11 Display associated with the + * window "SDL.window.x11.screen" - the screen number associated with the + * window "SDL.window.x11.window" - the X11 Window associated with the window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call diff --git a/include/SDL3/SDL_video_capture.h b/include/SDL3/SDL_video_capture.h index 3d3ce7e641981..12baaf5a46057 100644 --- a/include/SDL3/SDL_video_capture.h +++ b/include/SDL3/SDL_video_capture.h @@ -126,8 +126,8 @@ extern DECLSPEC SDL_VideoCaptureDeviceID *SDLCALL SDL_GetVideoCaptureDevices(int * Open a Video Capture device * * \param instance_id the video capture device instance ID - * \returns device, or NULL on failure; call - * SDL_GetError() for more information. + * \returns device, or NULL on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -165,8 +165,8 @@ extern DECLSPEC int SDLCALL SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *devi * \param desired desired video capture spec * \param obtained obtained video capture spec * \param allowed_changes allow changes or not - * \returns device, or NULL on failure; call - * SDL_GetError() for more information. + * \returns device, or NULL on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -178,6 +178,7 @@ extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCaptureWithSpec(SDL const SDL_VideoCaptureSpec *desired, SDL_VideoCaptureSpec *obtained, int allowed_changes); + /** * Get device name * @@ -208,6 +209,7 @@ extern DECLSPEC int SDLCALL SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *devi /** * Get frame format of video capture device. + * * The value can be used to fill SDL_VideoCaptureSpec structure. * * \param device opened video capture device @@ -240,6 +242,7 @@ extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice /** * Get frame sizes of the device and the specified input format. + * * The value can be used to fill SDL_VideoCaptureSpec structure. * * \param device opened video capture device @@ -300,11 +303,13 @@ extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDevice *device /** * Acquire a frame. - * The frame is a memory pointer to the image data, whose size and format - * are given by the the obtained spec. * - * Non blocking API. If there is a frame available, frame->num_planes is non 0. - * If frame->num_planes is 0 and returned code is 0, there is no frame at that time. + * The frame is a memory pointer to the image data, whose size and format are + * given by the the obtained spec. + * + * Non blocking API. If there is a frame available, frame->num_planes is non + * 0. If frame->num_planes is 0 and returned code is 0, there is no frame at + * that time. * * After used, the frame should be released with SDL_ReleaseVideoCaptureFrame * @@ -320,7 +325,9 @@ extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDevice *device extern DECLSPEC int SDLCALL SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame); /** - * Release a frame. Let the back-end re-use the internal buffer for video capture. + * Release a frame. + * + * Let the back-end re-use the internal buffer for video capture. * * All acquired frames should be released before closing the device. * @@ -349,7 +356,8 @@ extern DECLSPEC int SDLCALL SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice extern DECLSPEC int SDLCALL SDL_StopVideoCapture(SDL_VideoCaptureDevice *device); /** - * Use this function to shut down video_capture processing and close the video_capture device. + * Use this function to shut down video_capture processing and close the + * video_capture device. * * \param device opened video capture device * From 89408a97056722fe8f0a836ea6809793c86212f1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 9 Nov 2023 20:27:58 -0500 Subject: [PATCH 313/725] wasapi: ResetWasapiDevice no longer blocks on management thread. It just proxies all its necessary releases and frees to these without blocking, and sets the appropriate fields to NULL so they can be used again immediately, regardless of when the old stuff actually gets released. --- src/audio/wasapi/SDL_wasapi.c | 64 +++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index c7d251d6eb821..934ac4e6e6c2c 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -294,6 +294,14 @@ static SDL_bool WasapiFailed(SDL_AudioDevice *device, const HRESULT err) return SDL_TRUE; } +static int mgmtthrtask_StopAndReleaseClient(void *userdata) +{ + IAudioClient *client = (IAudioClient *) userdata; + IAudioClient_Stop(client); + IAudioClient_Release(client); + return 0; +} + static int mgmtthrtask_ReleaseCaptureClient(void *userdata) { IAudioCaptureClient_Release((IAudioCaptureClient *)userdata); @@ -306,56 +314,68 @@ static int mgmtthrtask_ReleaseRenderClient(void *userdata) return 0; } -static int mgmtthrtask_ResetWasapiDevice(void *userdata) +static int mgmtthrtask_CoTaskMemFree(void *userdata) { - SDL_AudioDevice *device = (SDL_AudioDevice *)userdata; + CoTaskMemFree(userdata); + return 0; +} +static int mgmtthrtask_PlatformDeleteActivationHandler(void *userdata) +{ + WASAPI_PlatformDeleteActivationHandler(userdata); + return 0; +} + +static int mgmtthrtask_CloseHandle(void *userdata) +{ + CloseHandle((HANDLE) userdata); + return 0; +} + +static void ResetWasapiDevice(SDL_AudioDevice *device) +{ if (!device || !device->hidden) { - return 0; + return; } + // just queue up all the tasks in the management thread and don't block. + // We don't care when any of these actually get free'd. + if (device->hidden->client) { - IAudioClient_Stop(device->hidden->client); - IAudioClient_Release(device->hidden->client); + IAudioClient *client = device->hidden->client; device->hidden->client = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_StopAndReleaseClient, client, NULL); } if (device->hidden->render) { - // this is silly, but this will block indefinitely if you call it from SDLMMNotificationClient_OnDefaultDeviceChanged, so - // proxy this to the management thread to be released later. - WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseRenderClient, device->hidden->render, NULL); + IAudioRenderClient *render = device->hidden->render; device->hidden->render = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseRenderClient, render, NULL); } if (device->hidden->capture) { - // this is silly, but this will block indefinitely if you call it from SDLMMNotificationClient_OnDefaultDeviceChanged, so - // proxy this to the management thread to be released later. - WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseCaptureClient, device->hidden->capture, NULL); + IAudioCaptureClient *capture = device->hidden->capture; device->hidden->capture = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseCaptureClient, capture, NULL); } if (device->hidden->waveformat) { - CoTaskMemFree(device->hidden->waveformat); + void *ptr = device->hidden->waveformat; device->hidden->waveformat = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_CoTaskMemFree, ptr, NULL); } if (device->hidden->activation_handler) { - WASAPI_PlatformDeleteActivationHandler(device->hidden->activation_handler); + void *activation_handler = device->hidden->activation_handler; device->hidden->activation_handler = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_PlatformDeleteActivationHandler, activation_handler, NULL); } if (device->hidden->event) { - CloseHandle(device->hidden->event); + HANDLE event = device->hidden->event; device->hidden->event = NULL; + WASAPI_ProxyToManagementThread(mgmtthrtask_CloseHandle, (void *) event, NULL); } - - return 0; -} - -static void ResetWasapiDevice(SDL_AudioDevice *device) -{ - int rc; - WASAPI_ProxyToManagementThread(mgmtthrtask_ResetWasapiDevice, device, &rc); } static int mgmtthrtask_ActivateDevice(void *userdata) From e54c5e02042083b4b126dd81bf6057890b8a1913 Mon Sep 17 00:00:00 2001 From: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:58:56 +0100 Subject: [PATCH 314/725] Fix condition in SDLTest_TrackAllocations() --- src/test/SDL_test_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/SDL_test_memory.c b/src/test/SDL_test_memory.c index 5ec92cfc5e94b..75d535a1d2328 100644 --- a/src/test/SDL_test_memory.c +++ b/src/test/SDL_test_memory.c @@ -307,7 +307,7 @@ void SDLTest_TrackAllocations(void) #else dbghelp_SymGetLineFromAddr = (dbghelp_SymGetLineFromAddr_fn)SDL_LoadFunction(s_dbghelp, "SymGetLineFromAddr"); #endif - if (!dbghelp_SymFromAddr || !dbghelp_SymFromAddr || !dbghelp_SymGetLineFromAddr) { + if (!dbghelp_SymInitialize || !dbghelp_SymFromAddr || !dbghelp_SymGetLineFromAddr) { SDL_UnloadObject(s_dbghelp); s_dbghelp = NULL; } else { From dfb87e1099668ce3b4dd504c5105ae207f030cea Mon Sep 17 00:00:00 2001 From: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:54:21 +0100 Subject: [PATCH 315/725] Fix uninitialised variable 'properties' If SDL_CreateHashTable() fails, properties->lock is not initialised, SDL_FreeProperties() is called and destroys the uninitialised lock. --- src/SDL_properties.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 31da31d320433..de54ee8c30090 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -119,7 +119,7 @@ SDL_PropertiesID SDL_CreateProperties(void) return 0; } - properties = SDL_malloc(sizeof(*properties)); + properties = SDL_calloc(1, sizeof(*properties)); if (!properties) { goto error; } From 36b2d2e463059345af5fadee608e535e58f61a89 Mon Sep 17 00:00:00 2001 From: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:01:57 +0100 Subject: [PATCH 316/725] Fix memory leak in SDL_SendDrop() --- src/events/SDL_dropevents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index b6544dc80685b..b029bd2d5c7d6 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -65,6 +65,7 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch size_t size = SDL_strlen(data) + 1; event.drop.data = (char *)SDL_AllocateEventMemory(size); if (!event.drop.data) { + SDL_free(event.drop.source); return 0; } SDL_memcpy(event.drop.data, data, size); From 8708ba7393d80de3bfb108d5a0ba159931b2be1b Mon Sep 17 00:00:00 2001 From: meyraud705 Date: Fri, 10 Nov 2023 13:25:54 +0100 Subject: [PATCH 317/725] Don't leak if realloc fails --- src/joystick/SDL_gamepad.c | 8 ++++++-- src/joystick/windows/SDL_rawinputjoystick.c | 14 ++++++++------ src/thread/SDL_thread.c | 6 ++++-- src/video/kmsdrm/SDL_kmsdrmvideo.c | 11 ++++++----- src/video/wayland/SDL_waylandmouse.c | 7 ++++--- src/video/wayland/SDL_waylandwindow.c | 9 +++++++-- src/video/x11/SDL_x11window.c | 5 +++-- 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 7bba99801086a..bb7e55c84b97f 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1124,6 +1124,7 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa SDL_bool invert_input = SDL_FALSE; char half_axis_input = 0; char half_axis_output = 0; + SDL_GamepadBinding *new_bindings; SDL_AssertJoysticksLocked(); @@ -1198,11 +1199,14 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa } ++gamepad->num_bindings; - gamepad->bindings = (SDL_GamepadBinding *)SDL_realloc(gamepad->bindings, gamepad->num_bindings * sizeof(*gamepad->bindings)); - if (!gamepad->bindings) { + new_bindings = (SDL_GamepadBinding *)SDL_realloc(gamepad->bindings, gamepad->num_bindings * sizeof(*gamepad->bindings)); + if (!new_bindings) { + SDL_free(gamepad->bindings); gamepad->num_bindings = 0; + gamepad->bindings = NULL; return SDL_OutOfMemory(); } + gamepad->bindings = new_bindings; gamepad->bindings[gamepad->num_bindings - 1] = bind; return 0; } diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index e9f8636d6c166..67dcb9d7b2ad8 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -615,16 +615,18 @@ static int RAWINPUT_UpdateWindowsGamingInput() if (!found) { /* New device, add it */ WindowsGamingInputGamepadState *gamepad_state; - - wgi_state.per_gamepad_count++; - wgi_state.per_gamepad = SDL_realloc(wgi_state.per_gamepad, sizeof(wgi_state.per_gamepad[0]) * wgi_state.per_gamepad_count); - if (!wgi_state.per_gamepad) { - return SDL_OutOfMemory(); - } + WindowsGamingInputGamepadState **new_per_gamepad; gamepad_state = SDL_calloc(1, sizeof(*gamepad_state)); if (!gamepad_state) { return SDL_OutOfMemory(); } + new_per_gamepad = SDL_realloc(wgi_state.per_gamepad, sizeof(wgi_state.per_gamepad[0]) * (wgi_state.per_gamepad_count + 1)); + if (!new_per_gamepad) { + SDL_free(gamepad_state); + return SDL_OutOfMemory(); + } + wgi_state.per_gamepad = new_per_gamepad; + wgi_state.per_gamepad_count++; wgi_state.per_gamepad[wgi_state.per_gamepad_count - 1] = gamepad_state; gamepad_state->gamepad = gamepad; gamepad_state->connected = SDL_TRUE; diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index c03fc41301c27..49f24d47e1d7d 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -54,13 +54,15 @@ int SDL_SetTLS(SDL_TLSID id, const void *value, void(SDLCALL *destructor)(void * storage = SDL_SYS_GetTLSData(); if (!storage || (id > storage->limit)) { unsigned int i, oldlimit, newlimit; + SDL_TLSData *new_storage; oldlimit = storage ? storage->limit : 0; newlimit = (id + TLS_ALLOC_CHUNKSIZE); - storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage) + (newlimit - 1) * sizeof(storage->array[0])); - if (!storage) { + new_storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage) + (newlimit - 1) * sizeof(storage->array[0])); + if (!new_storage) { return SDL_OutOfMemory(); } + storage = new_storage; storage->limit = newlimit; for (i = oldlimit; i < newlimit; ++i) { storage->array[i].data = NULL; diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 9aee16dae53ca..544cbff075478 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1555,13 +1555,14 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) extra window as a dummy surface when working with multiple contexts */ if (viddata->num_windows >= viddata->max_windows) { unsigned int new_max_windows = viddata->max_windows + 1; - viddata->windows = (SDL_Window **)SDL_realloc(viddata->windows, - new_max_windows * sizeof(SDL_Window *)); - viddata->max_windows = new_max_windows; - - if (!viddata->windows) { + SDL_Window **new_windows = (SDL_Window **)SDL_realloc(viddata->windows, + new_max_windows * sizeof(SDL_Window *)); + if (!new_windows) { return SDL_OutOfMemory(); } + viddata->windows = new_windows; + viddata->max_windows = new_max_windows; + } viddata->windows[viddata->num_windows++] = window; diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 8895e4cbc7394..02d30b25db57f 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -297,12 +297,13 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa if (!theme) { const char *xcursor_theme = dbus_cursor_theme; - vdata->cursor_themes = SDL_realloc(vdata->cursor_themes, - sizeof(SDL_WaylandCursorTheme) * (vdata->num_cursor_themes + 1)); - if (!vdata->cursor_themes) { + SDL_WaylandCursorTheme *new_cursor_themes = SDL_realloc(vdata->cursor_themes, + sizeof(SDL_WaylandCursorTheme) * (vdata->num_cursor_themes + 1)); + if (!new_cursor_themes) { SDL_OutOfMemory(); return SDL_FALSE; } + vdata->cursor_themes = new_cursor_themes; /* Fallback envvar if the DBus properties don't exist */ if (!xcursor_theme) { diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index b923c47191f3e..d7acd64bac0a7 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1196,13 +1196,18 @@ static void handle_surface_enter(void *data, struct wl_surface *surface, { SDL_WindowData *window = data; SDL_DisplayData *driverdata = wl_output_get_user_data(output); + SDL_DisplayData **new_outputs; if (!SDL_WAYLAND_own_output(output) || !SDL_WAYLAND_own_surface(surface)) { return; } - window->outputs = SDL_realloc(window->outputs, - sizeof(SDL_DisplayData *) * (window->num_outputs + 1)); + new_outputs = SDL_realloc(window->outputs, + sizeof(SDL_DisplayData *) * (window->num_outputs + 1)); + if (!new_outputs) { + return; + } + window->outputs = new_outputs; window->outputs[window->num_outputs++] = driverdata; /* Update the scale factor after the move so that fullscreen outputs are updated. */ diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 9c2b53e958994..459a55a55fc89 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -329,11 +329,12 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, windowlist[numwindows] = data; videodata->numwindows++; } else { - windowlist = (SDL_WindowData **)SDL_realloc(windowlist, (numwindows + 1) * sizeof(*windowlist)); - if (!windowlist) { + SDL_WindowData ** new_windowlist = (SDL_WindowData **)SDL_realloc(windowlist, (numwindows + 1) * sizeof(*windowlist)); + if (!new_windowlist) { SDL_free(data); return SDL_OutOfMemory(); } + windowlist = new_windowlist; windowlist[numwindows] = data; videodata->numwindows++; videodata->windowlistlength++; From 2991b9f6ac9b48cdb079ce36e62d1ccac935090f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 13:07:12 -0800 Subject: [PATCH 318/725] SDL now represents gamepad buttons as positional elements with a separate label This gives applications and binding systems a clearer view of what the hardware is so they can make intelligent decisions about how to present things to the user. Gamepad mappings continue to use abxy for the face buttons for simplicity and compatibility with earlier versions of SDL, however the "SDL_GAMECONTROLLER_USE_BUTTON_LABELS" hint no longer has any effect. Fixes https://github.com/libsdl-org/SDL/issues/6117 --- docs/README-migration.md | 15 +- include/SDL3/SDL_gamepad.h | 54 +++- include/SDL3/SDL_hints.h | 23 -- include/SDL3/SDL_joystick.h | 2 +- include/SDL3/SDL_oldnames.h | 16 +- src/dynapi/SDL_dynapi.sym | 2 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/joystick/SDL_gamepad.c | 295 ++++++++++++++++++-- src/joystick/SDL_gamepad_db.h | 117 -------- src/joystick/android/SDL_sysjoystick.c | 14 +- src/joystick/apple/SDL_mfijoystick.m | 28 +- src/joystick/hidapi/SDL_hidapi_gamecube.c | 39 +-- src/joystick/hidapi/SDL_hidapi_luna.c | 16 +- src/joystick/hidapi/SDL_hidapi_ps3.c | 56 ++-- src/joystick/hidapi/SDL_hidapi_ps4.c | 8 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 16 +- src/joystick/hidapi/SDL_hidapi_shield.c | 16 +- src/joystick/hidapi/SDL_hidapi_stadia.c | 8 +- src/joystick/hidapi/SDL_hidapi_steam.c | 8 +- src/joystick/hidapi/SDL_hidapi_switch.c | 99 +++---- src/joystick/hidapi/SDL_hidapi_wii.c | 107 +------ src/joystick/hidapi/SDL_hidapi_xbox360.c | 8 +- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 8 +- src/joystick/hidapi/SDL_hidapi_xboxone.c | 24 +- src/joystick/virtual/SDL_virtualjoystick.c | 8 +- src/joystick/windows/SDL_rawinputjoystick.c | 24 +- src/test/SDL_test_common.c | 8 +- test/gamepadutils.c | 262 ++++++++++++----- test/gamepadutils.h | 12 +- test/testautomation_joystick.c | 61 +++- test/testcontroller.c | 105 ++++--- 32 files changed, 852 insertions(+), 611 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 3bd20f135b1f8..6e64bf126099c 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -390,6 +390,8 @@ The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the w The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads. +The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications will now need to provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. Using South as the accept button and East as the cancel button is a good default. + SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events. SDL_CONTROLLER_TYPE_VIRTUAL has been removed, so virtual controllers can emulate other gamepad types. If you need to know whether a controller is virtual, you can use SDL_IsJoystickVirtual(). @@ -502,8 +504,8 @@ The following symbols have been renamed: * SDL_CONTROLLER_BINDTYPE_BUTTON => SDL_GAMEPAD_BINDTYPE_BUTTON * SDL_CONTROLLER_BINDTYPE_HAT => SDL_GAMEPAD_BINDTYPE_HAT * SDL_CONTROLLER_BINDTYPE_NONE => SDL_GAMEPAD_BINDTYPE_NONE -* SDL_CONTROLLER_BUTTON_A => SDL_GAMEPAD_BUTTON_A -* SDL_CONTROLLER_BUTTON_B => SDL_GAMEPAD_BUTTON_B +* SDL_CONTROLLER_BUTTON_A => SDL_GAMEPAD_BUTTON_SOUTH +* SDL_CONTROLLER_BUTTON_B => SDL_GAMEPAD_BUTTON_EAST * SDL_CONTROLLER_BUTTON_BACK => SDL_GAMEPAD_BUTTON_BACK * SDL_CONTROLLER_BUTTON_DPAD_DOWN => SDL_GAMEPAD_BUTTON_DPAD_DOWN * SDL_CONTROLLER_BUTTON_DPAD_LEFT => SDL_GAMEPAD_BUTTON_DPAD_LEFT @@ -523,8 +525,8 @@ The following symbols have been renamed: * SDL_CONTROLLER_BUTTON_RIGHTSTICK => SDL_GAMEPAD_BUTTON_RIGHT_STICK * SDL_CONTROLLER_BUTTON_START => SDL_GAMEPAD_BUTTON_START * SDL_CONTROLLER_BUTTON_TOUCHPAD => SDL_GAMEPAD_BUTTON_TOUCHPAD -* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_X -* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_Y +* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_WEST +* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_NORTH * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT @@ -552,14 +554,15 @@ SDL_AddHintCallback() now returns a standard int result instead of void, returni Calling SDL_GetHint() with the name of the hint being changed from within a hint callback will now return the new value rather than the old value. The old value is still passed as a parameter to the hint callback. The following hints have been removed: -* SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled +* SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional * SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver instead +* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer * SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() +* SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend -* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 04b27671805da..ccbd5d8baaf1b 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -81,10 +81,10 @@ typedef enum typedef enum { SDL_GAMEPAD_BUTTON_INVALID = -1, - SDL_GAMEPAD_BUTTON_A, - SDL_GAMEPAD_BUTTON_B, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_Y, + SDL_GAMEPAD_BUTTON_SOUTH, + SDL_GAMEPAD_BUTTON_EAST, + SDL_GAMEPAD_BUTTON_WEST, + SDL_GAMEPAD_BUTTON_NORTH, SDL_GAMEPAD_BUTTON_BACK, SDL_GAMEPAD_BUTTON_GUIDE, SDL_GAMEPAD_BUTTON_START, @@ -105,6 +105,26 @@ typedef enum SDL_GAMEPAD_BUTTON_MAX } SDL_GamepadButton; +/** + * The set of gamepad button labels + * + * This isn't a complete set, just the face buttons to make it easy to show button prompts. + * + * For a complete set, you should look at the button and gamepad type and have a set of symbols that work well with your art style. + */ +typedef enum +{ + SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN, + SDL_GAMEPAD_BUTTON_LABEL_A, /**< The south button for Xbox controllers, the east button for Nintendo controllers */ + SDL_GAMEPAD_BUTTON_LABEL_B, /**< The east button for Xbox controllers, the south button for Nintendo controllers */ + SDL_GAMEPAD_BUTTON_LABEL_X, /**< The west button for Xbox controllers, the north button for Nintendo controllers */ + SDL_GAMEPAD_BUTTON_LABEL_Y, /**< The north button for Xbox controllers, the west button for Nintendo controllers */ + SDL_GAMEPAD_BUTTON_LABEL_CROSS, /**< The south button for Playstation controllers */ + SDL_GAMEPAD_BUTTON_LABEL_CIRCLE, /**< The east button for Playstation controllers */ + SDL_GAMEPAD_BUTTON_LABEL_SQUARE, /**< The west button for Playstation controllers */ + SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE /**< The north button for Playstation controllers */ +} SDL_GamepadButtonLabel; + /** * The list of axes available on a gamepad * @@ -990,6 +1010,32 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_ */ extern DECLSPEC Uint8 SDLCALL SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button); +/** + * Get the label of a button on a gamepad. + * + * \param type the type of gamepad to check + * \param button a button index (one of the SDL_GamepadButton values) + * \returns the SDL_GamepadButtonLabel enum corresponding to the button label + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadButtonLabel + */ +extern DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabelForType(SDL_GamepadType type, SDL_GamepadButton button); + +/** + * Get the label of a button on a gamepad. + * + * \param gamepad a gamepad + * \param button a button index (one of the SDL_GamepadButton values) + * \returns the SDL_GamepadButtonLabel enum corresponding to the button label + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadButtonLabelForType + */ +extern DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabel(SDL_Gamepad *gamepad, SDL_GamepadButton button); + /** * Get the number of touchpads on a gamepad. * diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index a2d06b2b18fb0..0e4bf7565231d 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -537,29 +537,6 @@ extern "C" { */ #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT" -/** - * If set, game controller face buttons report their values according to their labels instead of their positional layout. - * - * For example, on Nintendo Switch controllers, normally you'd get: - * - * (Y) - * (X) (B) - * (A) - * - * but if this hint is set, you'll get: - * - * (X) - * (Y) (A) - * (B) - * - * The variable can be set to the following values: - * "0" - Report the face buttons by position, as though they were on an Xbox controller. - * "1" - Report the face buttons by label instead of position - * - * The default value is "1". This hint may be set at any time. - */ -#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS" - /** * Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. * diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index efb7d629ed52f..6fa5d171deaeb 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -343,7 +343,7 @@ typedef struct SDL_VirtualJoystickDesc Uint16 product_id; /**< the USB product ID of this joystick */ Uint16 padding; /**< unused */ Uint32 button_mask; /**< A mask of which buttons are valid for this controller - e.g. (1 << SDL_GAMEPAD_BUTTON_A) */ + e.g. (1 << SDL_GAMEPAD_BUTTON_SOUTH) */ Uint32 axis_mask; /**< A mask of which axes are valid for this controller e.g. (1 << SDL_GAMEPAD_AXIS_LEFTX) */ const char *name; /**< the name of the joystick */ diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 805921292bbba..39b1a61598cd2 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -160,8 +160,8 @@ #define SDL_CONTROLLER_BINDTYPE_BUTTON SDL_GAMEPAD_BINDTYPE_BUTTON #define SDL_CONTROLLER_BINDTYPE_HAT SDL_GAMEPAD_BINDTYPE_HAT #define SDL_CONTROLLER_BINDTYPE_NONE SDL_GAMEPAD_BINDTYPE_NONE -#define SDL_CONTROLLER_BUTTON_A SDL_GAMEPAD_BUTTON_A -#define SDL_CONTROLLER_BUTTON_B SDL_GAMEPAD_BUTTON_B +#define SDL_CONTROLLER_BUTTON_A SDL_GAMEPAD_BUTTON_SOUTH +#define SDL_CONTROLLER_BUTTON_B SDL_GAMEPAD_BUTTON_EAST #define SDL_CONTROLLER_BUTTON_BACK SDL_GAMEPAD_BUTTON_BACK #define SDL_CONTROLLER_BUTTON_DPAD_DOWN SDL_GAMEPAD_BUTTON_DPAD_DOWN #define SDL_CONTROLLER_BUTTON_DPAD_LEFT SDL_GAMEPAD_BUTTON_DPAD_LEFT @@ -181,8 +181,8 @@ #define SDL_CONTROLLER_BUTTON_RIGHTSTICK SDL_GAMEPAD_BUTTON_RIGHT_STICK #define SDL_CONTROLLER_BUTTON_START SDL_GAMEPAD_BUTTON_START #define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_GAMEPAD_BUTTON_TOUCHPAD -#define SDL_CONTROLLER_BUTTON_X SDL_GAMEPAD_BUTTON_X -#define SDL_CONTROLLER_BUTTON_Y SDL_GAMEPAD_BUTTON_Y +#define SDL_CONTROLLER_BUTTON_X SDL_GAMEPAD_BUTTON_WEST +#define SDL_CONTROLLER_BUTTON_Y SDL_GAMEPAD_BUTTON_NORTH #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT @@ -603,8 +603,8 @@ #define SDL_CONTROLLER_BINDTYPE_BUTTON SDL_CONTROLLER_BINDTYPE_BUTTON_renamed_SDL_GAMEPAD_BINDTYPE_BUTTON #define SDL_CONTROLLER_BINDTYPE_HAT SDL_CONTROLLER_BINDTYPE_HAT_renamed_SDL_GAMEPAD_BINDTYPE_HAT #define SDL_CONTROLLER_BINDTYPE_NONE SDL_CONTROLLER_BINDTYPE_NONE_renamed_SDL_GAMEPAD_BINDTYPE_NONE -#define SDL_CONTROLLER_BUTTON_A SDL_CONTROLLER_BUTTON_A_renamed_SDL_GAMEPAD_BUTTON_A -#define SDL_CONTROLLER_BUTTON_B SDL_CONTROLLER_BUTTON_B_renamed_SDL_GAMEPAD_BUTTON_B +#define SDL_CONTROLLER_BUTTON_A SDL_CONTROLLER_BUTTON_A_renamed_SDL_GAMEPAD_BUTTON_SOUTH +#define SDL_CONTROLLER_BUTTON_B SDL_CONTROLLER_BUTTON_B_renamed_SDL_GAMEPAD_BUTTON_EAST #define SDL_CONTROLLER_BUTTON_BACK SDL_CONTROLLER_BUTTON_BACK_renamed_SDL_GAMEPAD_BUTTON_BACK #define SDL_CONTROLLER_BUTTON_DPAD_DOWN SDL_CONTROLLER_BUTTON_DPAD_DOWN_renamed_SDL_GAMEPAD_BUTTON_DPAD_DOWN #define SDL_CONTROLLER_BUTTON_DPAD_LEFT SDL_CONTROLLER_BUTTON_DPAD_LEFT_renamed_SDL_GAMEPAD_BUTTON_DPAD_LEFT @@ -624,8 +624,8 @@ #define SDL_CONTROLLER_BUTTON_RIGHTSTICK SDL_CONTROLLER_BUTTON_RIGHTSTICK_renamed_SDL_GAMEPAD_BUTTON_RIGHT_STICK #define SDL_CONTROLLER_BUTTON_START SDL_CONTROLLER_BUTTON_START_renamed_SDL_GAMEPAD_BUTTON_START #define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_CONTROLLER_BUTTON_TOUCHPAD_renamed_SDL_GAMEPAD_BUTTON_TOUCHPAD -#define SDL_CONTROLLER_BUTTON_X SDL_CONTROLLER_BUTTON_X_renamed_SDL_GAMEPAD_BUTTON_X -#define SDL_CONTROLLER_BUTTON_Y SDL_CONTROLLER_BUTTON_Y_renamed_SDL_GAMEPAD_BUTTON_Y +#define SDL_CONTROLLER_BUTTON_X SDL_CONTROLLER_BUTTON_X_renamed_SDL_GAMEPAD_BUTTON_WEST +#define SDL_CONTROLLER_BUTTON_Y SDL_CONTROLLER_BUTTON_Y_renamed_SDL_GAMEPAD_BUTTON_NORTH #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR #define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 96e662f2c51e5..51e67d6e54add 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -939,6 +939,8 @@ SDL3_0.0.0 { SDL_StopVideoCapture; SDL_CloseVideoCapture; SDL_GetVideoCaptureDevices; + SDL_GetGamepadButtonLabelForType; + SDL_GetGamepadButtonLabel; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index adb202523cbcb..ac3e1623326fd 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -964,3 +964,5 @@ #define SDL_StopVideoCapture SDL_StopVideoCapture_REAL #define SDL_CloseVideoCapture SDL_CloseVideoCapture_REAL #define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL +#define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL +#define SDL_GetGamepadButtonLabel SDL_GetGamepadButtonLabel_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 7f3b0e5211258..dd9d7802b6633 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -997,3 +997,5 @@ SDL_DYNAPI_PROC(int,SDL_ReleaseVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL SDL_DYNAPI_PROC(int,SDL_StopVideoCapture,(SDL_VideoCaptureDevice *a),(a),return) SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),) SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return) +SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabelForType,(SDL_GamepadType a, SDL_GamepadButton b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index bb7e55c84b97f..9db1c31c2db23 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -45,6 +45,8 @@ #define SDL_GAMEPAD_CRC_FIELD_SIZE 4 /* hard-coded for speed */ #define SDL_GAMEPAD_TYPE_FIELD "type:" #define SDL_GAMEPAD_TYPE_FIELD_SIZE SDL_strlen(SDL_GAMEPAD_TYPE_FIELD) +#define SDL_GAMEPAD_FACE_FIELD "face:" +#define SDL_GAMEPAD_FACE_FIELD_SIZE 5 /* hard-coded for speed */ #define SDL_GAMEPAD_PLATFORM_FIELD "platform:" #define SDL_GAMEPAD_PLATFORM_FIELD_SIZE SDL_strlen(SDL_GAMEPAD_PLATFORM_FIELD) #define SDL_GAMEPAD_HINT_FIELD "hint:" @@ -57,6 +59,15 @@ static SDL_bool SDL_gamepads_initialized; static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +/* The face button style of a gamepad */ +typedef enum +{ + SDL_GAMEPAD_FACE_STYLE_UNKNOWN, + SDL_GAMEPAD_FACE_STYLE_ABXY, + SDL_GAMEPAD_FACE_STYLE_BAYX, + SDL_GAMEPAD_FACE_STYLE_SONY, +} SDL_GamepadFaceStyle; + /* our hard coded list of mapping support */ typedef enum { @@ -107,6 +118,8 @@ struct SDL_Gamepad int ref_count _guarded; const char *name _guarded; + SDL_GamepadType type _guarded; + SDL_GamepadFaceStyle face_style _guarded; GamepadMapping_t *mapping _guarded; int num_bindings _guarded; SDL_GamepadBinding *bindings _guarded; @@ -576,10 +589,10 @@ static void PopMappingChangeTracking(void) */ static GamepadMapping_t *SDL_CreateMappingForAndroidGamepad(SDL_JoystickGUID guid) { - const int face_button_mask = ((1 << SDL_GAMEPAD_BUTTON_A) | - (1 << SDL_GAMEPAD_BUTTON_B) | - (1 << SDL_GAMEPAD_BUTTON_X) | - (1 << SDL_GAMEPAD_BUTTON_Y)); + const int face_button_mask = ((1 << SDL_GAMEPAD_BUTTON_SOUTH) | + (1 << SDL_GAMEPAD_BUTTON_EAST) | + (1 << SDL_GAMEPAD_BUTTON_WEST) | + (1 << SDL_GAMEPAD_BUTTON_NORTH)); SDL_bool existing; char mapping_string[1024]; int button_mask; @@ -598,20 +611,20 @@ static GamepadMapping_t *SDL_CreateMappingForAndroidGamepad(SDL_JoystickGUID gui SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string)); - if (button_mask & (1 << SDL_GAMEPAD_BUTTON_A)) { + if (button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH)) { SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string)); } - if (button_mask & (1 << SDL_GAMEPAD_BUTTON_B)) { + if (button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST)) { SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string)); } else if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { /* Use the back button as "B" for easy UI navigation with TV remotes */ SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string)); button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_BACK); } - if (button_mask & (1 << SDL_GAMEPAD_BUTTON_X)) { + if (button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST)) { SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string)); } - if (button_mask & (1 << SDL_GAMEPAD_BUTTON_Y)) { + if (button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH)) { SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string)); } if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { @@ -1059,10 +1072,10 @@ const char *SDL_GetGamepadStringForAxis(SDL_GamepadAxis axis) } static const char *map_StringForGamepadButton[] = { - "a", - "b", - "x", - "y", + "s", + "e", + "w", + "n", "back", "guide", "start", @@ -1086,7 +1099,7 @@ SDL_COMPILE_TIME_ASSERT(map_StringForGamepadButton, SDL_arraysize(map_StringForG /* * convert a string to its enum equivalent */ -SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str) +SDL_GamepadButton SDL_PrivateGetGamepadButtonFromString(const char *str, SDL_bool baxy) { int i; @@ -1099,8 +1112,46 @@ SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str) return (SDL_GamepadButton)i; } } + + if (SDL_strcasecmp(str, "a") == 0) { + if (baxy) { + return SDL_GAMEPAD_BUTTON_EAST; + } else { + return SDL_GAMEPAD_BUTTON_SOUTH; + } + } else if (SDL_strcasecmp(str, "b") == 0) { + if (baxy) { + return SDL_GAMEPAD_BUTTON_SOUTH; + } else { + return SDL_GAMEPAD_BUTTON_EAST; + } + } else if (SDL_strcasecmp(str, "x") == 0) { + if (baxy) { + return SDL_GAMEPAD_BUTTON_NORTH; + } else { + return SDL_GAMEPAD_BUTTON_WEST; + } + } else if (SDL_strcasecmp(str, "y") == 0) { + if (baxy) { + return SDL_GAMEPAD_BUTTON_WEST; + } else { + return SDL_GAMEPAD_BUTTON_NORTH; + } + } else if (SDL_strcasecmp(str, "cross") == 0) { + return SDL_GAMEPAD_BUTTON_SOUTH; + } else if (SDL_strcasecmp(str, "circle") == 0) { + return SDL_GAMEPAD_BUTTON_EAST; + } else if (SDL_strcasecmp(str, "square") == 0) { + return SDL_GAMEPAD_BUTTON_WEST; + } else if (SDL_strcasecmp(str, "triangle") == 0) { + return SDL_GAMEPAD_BUTTON_NORTH; + } return SDL_GAMEPAD_BUTTON_INVALID; } +SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str) +{ + return SDL_PrivateGetGamepadButtonFromString(str, SDL_FALSE); +} /* * convert an enum to its string equivalent @@ -1116,7 +1167,7 @@ const char *SDL_GetGamepadStringForButton(SDL_GamepadButton button) /* * given a gamepad button name and a joystick name update our mapping structure with it */ -static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGameButton, const char *szJoystickButton) +static SDL_bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGameButton, const char *szJoystickButton) { SDL_GamepadBinding bind; SDL_GamepadButton button; @@ -1124,16 +1175,24 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa SDL_bool invert_input = SDL_FALSE; char half_axis_input = 0; char half_axis_output = 0; + int i; SDL_GamepadBinding *new_bindings; + SDL_bool baxy_mapping = SDL_FALSE; SDL_AssertJoysticksLocked(); + SDL_zero(bind); + if (*szGameButton == '+' || *szGameButton == '-') { half_axis_output = *szGameButton++; } + if (SDL_strstr(gamepad->mapping->mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + baxy_mapping = SDL_TRUE; + } + axis = SDL_GetGamepadAxisFromString(szGameButton); - button = SDL_GetGamepadButtonFromString(szGameButton); + button = SDL_PrivateGetGamepadButtonFromString(szGameButton, baxy_mapping); if (axis != SDL_GAMEPAD_AXIS_INVALID) { bind.outputType = SDL_GAMEPAD_BINDTYPE_AXIS; bind.output.axis.axis = axis; @@ -1156,7 +1215,7 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa bind.outputType = SDL_GAMEPAD_BINDTYPE_BUTTON; bind.output.button = button; } else { - return SDL_SetError("Unexpected gamepad element %s", szGameButton); + return SDL_FALSE; } if (*szJoystickButton == '+' || *szJoystickButton == '-') { @@ -1195,7 +1254,14 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa bind.input.hat.hat = hat; bind.input.hat.hat_mask = mask; } else { - return SDL_SetError("Unexpected joystick element: %s", szJoystickButton); + return SDL_FALSE; + } + + for (i = 0; i < gamepad->num_bindings; ++i) { + if (SDL_memcmp(&gamepad->bindings[i], &bind, sizeof(bind)) == 0) { + /* We already have this binding, could be different face button names? */ + return SDL_TRUE; + } } ++gamepad->num_bindings; @@ -1204,11 +1270,11 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa SDL_free(gamepad->bindings); gamepad->num_bindings = 0; gamepad->bindings = NULL; - return SDL_OutOfMemory(); + return SDL_FALSE; } gamepad->bindings = new_bindings; gamepad->bindings[gamepad->num_bindings - 1] = bind; - return 0; + return SDL_TRUE; } /* @@ -1261,6 +1327,93 @@ static int SDL_PrivateParseGamepadConfigString(SDL_Gamepad *gamepad, const char return 0; } +static void SDL_UpdateGamepadType(SDL_Gamepad *gamepad) +{ + char *type_string, *comma; + + SDL_AssertJoysticksLocked(); + + gamepad->type = SDL_GAMEPAD_TYPE_UNKNOWN; + + type_string = SDL_strstr(gamepad->mapping->mapping, SDL_GAMEPAD_TYPE_FIELD); + if (type_string) { + type_string += SDL_GAMEPAD_TYPE_FIELD_SIZE; + comma = SDL_strchr(type_string, ','); + if (comma) { + *comma = '\0'; + gamepad->type = SDL_GetGamepadTypeFromString(type_string); + *comma = ','; + } else { + gamepad->type = SDL_GetGamepadTypeFromString(type_string); + } + } + if (gamepad->type == SDL_GAMEPAD_TYPE_UNKNOWN) { + gamepad->type = SDL_GetRealGamepadInstanceType(gamepad->joystick->instance_id); + } +} + +static SDL_GamepadFaceStyle SDL_GetGamepadFaceStyleFromString(const char *string) +{ + if (SDL_strcmp(string, "abxy") == 0) { + return SDL_GAMEPAD_FACE_STYLE_ABXY; + } else if (SDL_strcmp(string, "bayx") == 0) { + return SDL_GAMEPAD_FACE_STYLE_BAYX; + } else if (SDL_strcmp(string, "sony") == 0) { + return SDL_GAMEPAD_FACE_STYLE_SONY; + } else { + return SDL_GAMEPAD_FACE_STYLE_UNKNOWN; + } +} + +static SDL_GamepadFaceStyle SDL_GetGamepadFaceStyleForGamepadType(SDL_GamepadType type) +{ + switch (type) { + case SDL_GAMEPAD_TYPE_PS3: + case SDL_GAMEPAD_TYPE_PS4: + case SDL_GAMEPAD_TYPE_PS5: + return SDL_GAMEPAD_FACE_STYLE_SONY; + case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO: + case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: + case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: + case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + return SDL_GAMEPAD_FACE_STYLE_BAYX; + default: + return SDL_GAMEPAD_FACE_STYLE_ABXY; + } +} + +static void SDL_UpdateGamepadFaceStyle(SDL_Gamepad *gamepad) +{ + char *face_string, *comma; + + SDL_AssertJoysticksLocked(); + + gamepad->face_style = SDL_GAMEPAD_FACE_STYLE_UNKNOWN; + + face_string = SDL_strstr(gamepad->mapping->mapping, SDL_GAMEPAD_FACE_FIELD); + if (face_string) { + face_string += SDL_GAMEPAD_TYPE_FIELD_SIZE; + comma = SDL_strchr(face_string, ','); + if (comma) { + *comma = '\0'; + gamepad->face_style = SDL_GetGamepadFaceStyleFromString(face_string); + *comma = ','; + } else { + gamepad->face_style = SDL_GetGamepadFaceStyleFromString(face_string); + } + } + + if (gamepad->face_style == SDL_GAMEPAD_FACE_STYLE_UNKNOWN && + SDL_strstr(gamepad->mapping->mapping, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS") != NULL) { + /* This controller uses Nintendo button style */ + gamepad->face_style = SDL_GAMEPAD_FACE_STYLE_BAYX; + } + if (gamepad->face_style == SDL_GAMEPAD_FACE_STYLE_UNKNOWN) { + gamepad->face_style = SDL_GetGamepadFaceStyleForGamepadType(gamepad->type); + } +} + + /* * Make a new button mapping struct */ @@ -1277,6 +1430,9 @@ static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t SDL_memset(gamepad->last_match_axis, 0, gamepad->joystick->naxes * sizeof(*gamepad->last_match_axis)); } + SDL_UpdateGamepadType(gamepad); + SDL_UpdateGamepadFaceStyle(gamepad); + SDL_PrivateParseGamepadConfigString(gamepad, pGamepadMapping->mapping); /* Set the zero point for triggers */ @@ -2246,7 +2402,6 @@ SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id) *comma = ','; } } - } } SDL_UnlockJoysticks(); @@ -2658,6 +2813,100 @@ Uint8 SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) return retval; } +/** + * Get the label of a button on a gamepad. + */ +SDL_GamepadButtonLabel SDL_GetGamepadButtonLabelForFaceStyle(SDL_GamepadFaceStyle face_style, SDL_GamepadButton button) +{ + SDL_GamepadButtonLabel label = SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN; + + switch (face_style) { + case SDL_GAMEPAD_FACE_STYLE_ABXY: + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + label = SDL_GAMEPAD_BUTTON_LABEL_A; + break; + case SDL_GAMEPAD_BUTTON_EAST: + label = SDL_GAMEPAD_BUTTON_LABEL_B; + break; + case SDL_GAMEPAD_BUTTON_WEST: + label = SDL_GAMEPAD_BUTTON_LABEL_X; + break; + case SDL_GAMEPAD_BUTTON_NORTH: + label = SDL_GAMEPAD_BUTTON_LABEL_Y; + break; + default: + break; + } + break; + case SDL_GAMEPAD_FACE_STYLE_BAYX: + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + label = SDL_GAMEPAD_BUTTON_LABEL_B; + break; + case SDL_GAMEPAD_BUTTON_EAST: + label = SDL_GAMEPAD_BUTTON_LABEL_A; + break; + case SDL_GAMEPAD_BUTTON_WEST: + label = SDL_GAMEPAD_BUTTON_LABEL_Y; + break; + case SDL_GAMEPAD_BUTTON_NORTH: + label = SDL_GAMEPAD_BUTTON_LABEL_X; + break; + default: + break; + } + break; + case SDL_GAMEPAD_FACE_STYLE_SONY: + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + label = SDL_GAMEPAD_BUTTON_LABEL_CROSS; + break; + case SDL_GAMEPAD_BUTTON_EAST: + label = SDL_GAMEPAD_BUTTON_LABEL_CIRCLE; + break; + case SDL_GAMEPAD_BUTTON_WEST: + label = SDL_GAMEPAD_BUTTON_LABEL_SQUARE; + break; + case SDL_GAMEPAD_BUTTON_NORTH: + label = SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE; + break; + default: + break; + } + break; + default: + break; + } + return label; +} + +/** + * Get the label of a button on a gamepad. + */ +SDL_GamepadButtonLabel SDL_GetGamepadButtonLabelForType(SDL_GamepadType type, SDL_GamepadButton button) +{ + return SDL_GetGamepadButtonLabelForFaceStyle(SDL_GetGamepadFaceStyleForGamepadType(type), button); +} + +/** + * Get the label of a button on a gamepad. + */ +SDL_GamepadButtonLabel SDL_GetGamepadButtonLabel(SDL_Gamepad *gamepad, SDL_GamepadButton button) +{ + SDL_GamepadFaceStyle face_style; + + SDL_LockJoysticks(); + { + CHECK_GAMEPAD_MAGIC(gamepad, SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN); + + face_style = gamepad->face_style; + } + SDL_UnlockJoysticks(); + + return SDL_GetGamepadButtonLabelForFaceStyle(face_style, button); +} + /** * Get the number of touchpads on a gamepad. */ @@ -2979,17 +3228,17 @@ const char *SDL_GetGamepadPath(SDL_Gamepad *gamepad) SDL_GamepadType SDL_GetGamepadType(SDL_Gamepad *gamepad) { - SDL_JoystickID instance_id = 0; + SDL_GamepadType type; SDL_LockJoysticks(); { CHECK_GAMEPAD_MAGIC(gamepad, SDL_GAMEPAD_TYPE_UNKNOWN); - instance_id = gamepad->joystick->instance_id; + type = gamepad->type; } SDL_UnlockJoysticks(); - return SDL_GetGamepadInstanceType(instance_id); + return type; } SDL_GamepadType SDL_GetRealGamepadType(SDL_Gamepad *gamepad) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index bbeb0260c7700..4253e498f3914 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -35,7 +35,6 @@ static const char *s_GamepadMappings[] = { #ifdef SDL_JOYSTICK_WGI "03000000491900001904000000007700,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,", "03000000d11800000094000000007700,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", - "030000007e0500000920000000007701,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000007e0500000920000000007701,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000004c050000c405000000007701,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000004c050000e60c000000007700,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -44,53 +43,30 @@ static const char *s_GamepadMappings[] = { #endif #ifdef SDL_JOYSTICK_DINPUT "03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,", - "03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001038000000000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001038000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000650000000000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000650000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000003512000012ab000000000000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000003512000012ab000000000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000022000000090000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000203800000900000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000660000000000000,8BitDo Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001290000000000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001290000000000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00006228000000000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00006228000000000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000003512000020ab000000000000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000003512000020ab000000000000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001130000000000000,8BitDo Ultimate Wired Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "03000000c82d00001330000000000000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", - "03000000c82d00001890000000000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00003032000000000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000a00500003232000000000000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000a00500003232000000000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000050b00000579000000000000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "03000000050b00000679000000000000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", @@ -224,10 +200,8 @@ static const char *s_GamepadMappings[] = { "03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,", "030000005509000000b4000000000000,NVIDIA Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000004b120000014d000000000000,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,", - "03000000790000004318000000000000,Nintendo GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000790000004318000000000000,Nintendo GameCube Controller,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,", "03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,", - "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,", "03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", @@ -293,7 +267,6 @@ static const char *s_GamepadMappings[] = { "030000000d0f00005c00000000000000,Real Arcade Pro.V4,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:a3,start:b9,x:b0,y:b3,", "0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,", "0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,", - "03000000790000001100000000000000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -356,51 +329,31 @@ static const char *s_GamepadMappings[] = { "03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", - "03000000830500006020000000000000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", #endif #ifdef __MACOS__ - "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000650000001000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000650000001000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000022000000090000001000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000203800000900000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000660000000020000,8BitDo Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001130000000020000,8BitDo Ultimate Wired Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "03000000c82d00001330000000020000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", - "03000000c82d00001890000001000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00003032000000010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b2,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000a00500003232000009010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000a00500003232000009010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000050b00000579000000010000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,", "03000000050b00000679000000010000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,", @@ -452,7 +405,6 @@ static const char *s_GamepadMappings[] = { "03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,", "030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", - "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", @@ -473,7 +425,6 @@ static const char *s_GamepadMappings[] = { "03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", "0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", "03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,", - "03000000790000001100000006010000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -515,67 +466,40 @@ static const char *s_GamepadMappings[] = { "03000000c0160000e105000000040000,Xin-Mo Dual Arcade,crc:82d5,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,", /* Ultimate Atari Fight Stick */ "03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", - "03000000830500006020000000010000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,", #endif #if defined(SDL_JOYSTICK_LINUX) || defined(__OpenBSD__) - "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000650000011010000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000003512000012ab000010010000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000003512000012ab000010010000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000022000000090000011010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000203800000900000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000020000000000000,8BitDo Pro 2 Wired Controller for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "06000000c82d00000020000006010000,8BitDo Pro 2 Wired Controller for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "03000000c82d00000660000011010000,8BitDo Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00000660000000010000,8BitDo Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000102800000900000000010000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000102800000900000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00003028000000010000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00003028000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000003512000020ab000010010000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000003512000020ab000010010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001130000011010000,8BitDo Ultimate Wired Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "03000000c82d00001330000011010000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", - "03000000c82d00001890000011010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00003032000000010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000031000011010000,8Bitdo Receiver,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,", - "03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,", "05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,", @@ -697,32 +621,19 @@ static const char *s_GamepadMappings[] = { "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", "030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,", "03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", - "03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,", - "050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b15,b:b16,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b17,y:b14,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:b1,b:b0,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:b2,y:b3,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:b1,b:b0,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:b2,y:b3,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,", - "050000007e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b2,b:b1,guide:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b1,b:b2,guide:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000004c69632050726f20436f6e00,Nintendo Switch Pro Controller,crc:15b7,a:b1,b:b0,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000004c69632050726f20436f6e00,Nintendo Switch Pro Controller,crc:15b7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,", - "050000007e0500000603000000060000,Nintendo Wii Remote Classic Controller,crc:0d8a,a:b0,b:b1,back:b10,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500000603000000060000,Nintendo Wii Remote Classic Controller,crc:0d8a,a:b1,b:b0,back:b10,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e0500000603000000060000,Nintendo Wii Remote,crc:60be,a:b1,b:b0,back:b4,dpdown:b8,dpleft:b6,dpright:b7,dpup:b5,guide:b2,start:b3,x:b9,y:b10,", "05000000010000000100000003000000,Nintendo Wiimote,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:a2,righty:a3,start:b9,x:b2,y:b3,", @@ -785,7 +696,6 @@ static const char *s_GamepadMappings[] = { "050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", "0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,", - "03000000790000001100000010010000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -858,7 +768,6 @@ static const char *s_GamepadMappings[] = { "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", "030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,", - "03000000830500006020000010010000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,", @@ -871,37 +780,21 @@ static const char *s_GamepadMappings[] = { "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4~,start:b7,x:b2,y:b3,", #endif #ifdef __ANDROID__ - "05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b20,b:b21,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b23,y:b24,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,", "0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", @@ -909,9 +802,7 @@ static const char *s_GamepadMappings[] = { "050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "050000005509000014720000df7f3f80,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,", - "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,sdk>=:29,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,sdk>=:29,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,sdk<=:28,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", /* Extremely slow in Bluetooth mode on Android */ "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b2,y:b17,sdk<=:28,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", /* Extremely slow in Bluetooth mode on Android */ "050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", @@ -939,7 +830,6 @@ static const char *s_GamepadMappings[] = { "050000005e040000130b0000ffff3f00,Xbox Series X Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "050000005e04000091020000ff073f80,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", /* The DPAD doesn't seem to work on this controller on Android TV? */ "050000001727000044310000ffff3f80,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a4,righty:a5,start:b6,x:b2,y:b3,", - "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", #endif #ifdef SDL_JOYSTICK_MFI @@ -950,19 +840,12 @@ static const char *s_GamepadMappings[] = { "05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", "050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", - "050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 7333b18d8437a..1e1003aea4822 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -73,16 +73,16 @@ static int keycode_to_SDL(int keycode) switch (keycode) { /* Some gamepad buttons (API 9) */ case AKEYCODE_BUTTON_A: - button = SDL_GAMEPAD_BUTTON_A; + button = SDL_GAMEPAD_BUTTON_SOUTH; break; case AKEYCODE_BUTTON_B: - button = SDL_GAMEPAD_BUTTON_B; + button = SDL_GAMEPAD_BUTTON_EAST; break; case AKEYCODE_BUTTON_X: - button = SDL_GAMEPAD_BUTTON_X; + button = SDL_GAMEPAD_BUTTON_WEST; break; case AKEYCODE_BUTTON_Y: - button = SDL_GAMEPAD_BUTTON_Y; + button = SDL_GAMEPAD_BUTTON_NORTH; break; case AKEYCODE_BUTTON_L1: button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; @@ -136,7 +136,7 @@ static int keycode_to_SDL(int keycode) case AKEYCODE_DPAD_CENTER: /* This is handled better by applications as the A button */ /*button = 19;*/ - button = SDL_GAMEPAD_BUTTON_A; + button = SDL_GAMEPAD_BUTTON_SOUTH; break; /* More gamepad buttons (API 12), these get mapped to 20...35*/ @@ -174,9 +174,9 @@ static int keycode_to_SDL(int keycode) static SDL_Scancode button_to_scancode(int button) { switch (button) { - case SDL_GAMEPAD_BUTTON_A: + case SDL_GAMEPAD_BUTTON_SOUTH: return SDL_SCANCODE_RETURN; - case SDL_GAMEPAD_BUTTON_B: + case SDL_GAMEPAD_BUTTON_EAST: return SDL_SCANCODE_ESCAPE; case SDL_GAMEPAD_BUTTON_BACK: return SDL_SCANCODE_ESCAPE; diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index b2daeac609825..1d45799e16505 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -298,10 +298,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle #endif /* These buttons are part of the original MFi spec */ - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_A); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_B); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_X); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_Y); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_WEST); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_NORTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); nbuttons += 6; @@ -472,10 +472,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } /* These buttons are part of the original MFi spec */ - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_A); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_B); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_X); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_Y); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_WEST); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_NORTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); #if TARGET_OS_TV @@ -495,8 +495,8 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle else if (controller.microGamepad) { int nbuttons = 0; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_A); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_B); /* Button X on microGamepad */ + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); /* Button X on microGamepad */ nbuttons += 2; device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_START); @@ -1748,16 +1748,16 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * if ([controller respondsToSelector:@selector(physicalInputProfile)]) { NSDictionary *elements = controller.physicalInputProfile.elements; switch (button) { - case SDL_GAMEPAD_BUTTON_A: + case SDL_GAMEPAD_BUTTON_SOUTH: GetAppleSFSymbolsNameForElement(elements[GCInputButtonA], elementName); break; - case SDL_GAMEPAD_BUTTON_B: + case SDL_GAMEPAD_BUTTON_EAST: GetAppleSFSymbolsNameForElement(elements[GCInputButtonB], elementName); break; - case SDL_GAMEPAD_BUTTON_X: + case SDL_GAMEPAD_BUTTON_WEST: GetAppleSFSymbolsNameForElement(elements[GCInputButtonX], elementName); break; - case SDL_GAMEPAD_BUTTON_Y: + case SDL_GAMEPAD_BUTTON_NORTH: GetAppleSFSymbolsNameForElement(elements[GCInputButtonY], elementName); break; case SDL_GAMEPAD_BUTTON_BACK: diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 182f00b1be427..397a77f05749b 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -46,7 +46,6 @@ typedef struct Uint8 rumble[1 + MAX_CONTROLLERS]; /* Without this variable, hid_write starts to lag a TON */ SDL_bool rumbleUpdate; - SDL_bool m_bUseButtonLabels; SDL_bool useRumbleBrake; } SDL_DriverGameCube_Context; @@ -90,12 +89,6 @@ static void ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index) ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_MAX + SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = 40; } -static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata; - ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE); -} - static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { if (hint) { @@ -104,22 +97,6 @@ static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, c } } -static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button) -{ - if (!ctx->m_bUseButtonLabels) { - /* Use button positions */ - switch (button) { - case SDL_GAMEPAD_BUTTON_B: - return SDL_GAMEPAD_BUTTON_X; - case SDL_GAMEPAD_BUTTON_X: - return SDL_GAMEPAD_BUTTON_B; - default: - break; - } - } - return button; -} - static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) { SDL_DriverGameCube_Context *ctx; @@ -203,8 +180,6 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) SDL_AddHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx); - SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller"); @@ -251,15 +226,15 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device } #define READ_BUTTON(off, flag, button) \ - SDL_SendJoystickButton( \ + SDL_SendJoystickButton( \ timestamp, \ joystick, \ - RemapButton(ctx, button), \ + button, \ (packet[off] & flag) ? SDL_PRESSED : SDL_RELEASED); READ_BUTTON(1, 0x02, 0) /* A */ READ_BUTTON(1, 0x04, 1) /* B */ - READ_BUTTON(1, 0x01, 2) /* X */ READ_BUTTON(1, 0x08, 3) /* Y */ + READ_BUTTON(1, 0x01, 2) /* X */ READ_BUTTON(2, 0x80, 4) /* DPAD_LEFT */ READ_BUTTON(2, 0x20, 5) /* DPAD_RIGHT */ READ_BUTTON(2, 0x40, 6) /* DPAD_DOWN */ @@ -334,15 +309,15 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device } #define READ_BUTTON(off, flag, button) \ - SDL_SendJoystickButton( \ + SDL_SendJoystickButton( \ timestamp, \ joystick, \ - RemapButton(ctx, button), \ + button, \ (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED); READ_BUTTON(1, 0x01, 0) /* A */ READ_BUTTON(1, 0x04, 1) /* B */ - READ_BUTTON(1, 0x02, 2) /* X */ READ_BUTTON(1, 0x08, 3) /* Y */ + READ_BUTTON(1, 0x02, 2) /* X */ READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */ READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */ READ_BUTTON(1, 0x40, 6) /* DPAD_DOWN */ @@ -523,8 +498,6 @@ static void HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device) { SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; - SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx); } diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index d4ee4ada86b58..57f2a11a69a77 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -169,10 +169,10 @@ static void HIDAPI_DriverLuna_HandleUSBStatePacket(SDL_Joystick *joystick, SDL_D Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[1] != data[1]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[1] & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -332,10 +332,10 @@ static void HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick, } if (ctx->last_state[14] != data[14]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index da309f7eff84b..eb49d8018e254 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -357,10 +357,10 @@ static void HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_D SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } if (ctx->last_state[5] != data[5]) { @@ -405,10 +405,10 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive if (ctx->last_state[3] != data[3]) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } if (ctx->last_state[4] != data[4]) { @@ -431,10 +431,10 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive /* Buttons are mapped as axes in the order they appear in the button enumeration */ { static int button_axis_offsets[] = { - 24, /* SDL_GAMEPAD_BUTTON_A */ - 23, /* SDL_GAMEPAD_BUTTON_B */ - 25, /* SDL_GAMEPAD_BUTTON_X */ - 22, /* SDL_GAMEPAD_BUTTON_Y */ + 24, /* SDL_GAMEPAD_BUTTON_SOUTH */ + 23, /* SDL_GAMEPAD_BUTTON_EAST */ + 25, /* SDL_GAMEPAD_BUTTON_WEST */ + 22, /* SDL_GAMEPAD_BUTTON_NORTH */ 0, /* SDL_GAMEPAD_BUTTON_BACK */ 0, /* SDL_GAMEPAD_BUTTON_GUIDE */ 0, /* SDL_GAMEPAD_BUTTON_START */ @@ -684,10 +684,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[0] != data[0]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED); } @@ -757,10 +757,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic /* Buttons are mapped as axes in the order they appear in the button enumeration */ { static int button_axis_offsets[] = { - 12, /* SDL_GAMEPAD_BUTTON_A */ - 11, /* SDL_GAMEPAD_BUTTON_B */ - 13, /* SDL_GAMEPAD_BUTTON_X */ - 10, /* SDL_GAMEPAD_BUTTON_Y */ + 12, /* SDL_GAMEPAD_BUTTON_SOUTH */ + 11, /* SDL_GAMEPAD_BUTTON_EAST */ + 13, /* SDL_GAMEPAD_BUTTON_WEST */ + 10, /* SDL_GAMEPAD_BUTTON_NORTH */ 0, /* SDL_GAMEPAD_BUTTON_BACK */ 0, /* SDL_GAMEPAD_BUTTON_GUIDE */ 0, /* SDL_GAMEPAD_BUTTON_START */ @@ -797,10 +797,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[0] != data[0]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED); } @@ -881,10 +881,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic /* Buttons are mapped as axes in the order they appear in the button enumeration */ { static int button_axis_offsets[] = { - 13, /* SDL_GAMEPAD_BUTTON_A */ - 12, /* SDL_GAMEPAD_BUTTON_B */ - 14, /* SDL_GAMEPAD_BUTTON_X */ - 11, /* SDL_GAMEPAD_BUTTON_Y */ + 13, /* SDL_GAMEPAD_BUTTON_SOUTH */ + 12, /* SDL_GAMEPAD_BUTTON_EAST */ + 14, /* SDL_GAMEPAD_BUTTON_WEST */ + 11, /* SDL_GAMEPAD_BUTTON_NORTH */ 0, /* SDL_GAMEPAD_BUTTON_BACK */ 0, /* SDL_GAMEPAD_BUTTON_GUIDE */ 0, /* SDL_GAMEPAD_BUTTON_START */ diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index d43e35604ddae..cec3b2dc33fc0 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -970,10 +970,10 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d { Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); } { Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F); diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 35712a47dd69f..37b15991b6dff 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -1114,10 +1114,10 @@ static void HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL { Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); } { Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F); @@ -1215,10 +1215,10 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL { Uint8 data = (packet->rgucButtonsAndHat[0] >> 4); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); } { Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F); diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 77b16da4929dd..5821c2d6f0bad 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -333,10 +333,10 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD } if (ctx->last_state[1] != data[1]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[1] & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -435,10 +435,10 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD } if (ctx->last_state[3] != data[3]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index d2d4fcc0e5113..b5959cbb56437 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -232,10 +232,10 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr } if (ctx->last_state[3] != data[3]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED); diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 0576a4496e013..5fc99fbef5e75 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1120,16 +1120,16 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) Uint64 timestamp = SDL_GetTicksNS(); if (ctx->m_state.ulButtons != ctx->m_last_state.ulButtons) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (ctx->m_state.ulButtons & STEAM_BUTTON_1_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (ctx->m_state.ulButtons & STEAM_BUTTON_2_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (ctx->m_state.ulButtons & STEAM_BUTTON_0_MASK) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 124bb5f5c0cf6..e9ad734d9adc6 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -931,38 +931,21 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt SDL_MIN_SINT16, SDL_MAX_SINT16); } -static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata; - ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE); -} - static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button) { - if (!ctx->m_bUseButtonLabels) { - /* Use button positions */ - if (ctx->m_bIsGameCube) { - switch (button) { - case SDL_GAMEPAD_BUTTON_B: - return SDL_GAMEPAD_BUTTON_X; - case SDL_GAMEPAD_BUTTON_X: - return SDL_GAMEPAD_BUTTON_B; - default: - break; - } - } else { - switch (button) { - case SDL_GAMEPAD_BUTTON_A: - return SDL_GAMEPAD_BUTTON_B; - case SDL_GAMEPAD_BUTTON_B: - return SDL_GAMEPAD_BUTTON_A; - case SDL_GAMEPAD_BUTTON_X: - return SDL_GAMEPAD_BUTTON_Y; - case SDL_GAMEPAD_BUTTON_Y: - return SDL_GAMEPAD_BUTTON_X; - default: - break; - } + if (ctx->m_bUseButtonLabels) { + /* Use button labels instead of positions, e.g. Nintendo Online Classic controllers */ + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + return SDL_GAMEPAD_BUTTON_EAST; + case SDL_GAMEPAD_BUTTON_EAST: + return SDL_GAMEPAD_BUTTON_SOUTH; + case SDL_GAMEPAD_BUTTON_WEST: + return SDL_GAMEPAD_BUTTON_NORTH; + case SDL_GAMEPAD_BUTTON_NORTH: + return SDL_GAMEPAD_BUTTON_WEST; + default: + break; } } return button; @@ -1067,6 +1050,7 @@ static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInf static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id) { +#if 0 static Uint32 gamecube_formfactor[] = { MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */ @@ -1079,6 +1063,7 @@ static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id) return SDL_TRUE; } } +#endif return SDL_FALSE; } @@ -1416,9 +1401,6 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ if (AlwaysUsesLabels(device->vendor_id, device->product_id, ctx->m_eControllerType)) { ctx->m_bUseButtonLabels = SDL_TRUE; - } else { - SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); } /* Initialize player index (needed for setting LEDs) */ @@ -1647,10 +1629,10 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) { Uint8 data = packet->rgucButtons[0]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); @@ -1745,10 +1727,10 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) { Uint8 data = packet->rgucButtons[0]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); @@ -1917,10 +1899,10 @@ static void HandleMiniControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) { Uint8 data = packet->controllerState.rgucButtons[2]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -1942,10 +1924,10 @@ static void HandleCombinedControllerStateR(Uint64 timestamp, SDL_Joystick *joyst if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) { Uint8 data = packet->controllerState.rgucButtons[0]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -1975,10 +1957,10 @@ static void HandleMiniControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) { Uint8 data = packet->controllerState.rgucButtons[0]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -2022,10 +2004,10 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) { Uint8 data = packet->controllerState.rgucButtons[0]; - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); axis = (data & 0x80) ? 32767 : -32768; SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); @@ -2279,9 +2261,6 @@ static void HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joy SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState); } - SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); - if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft || ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED, diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 836f54dcd9eed..4a529de76d63e 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -135,7 +135,6 @@ typedef struct Uint64 timestamp; EWiiCommunicationState m_eCommState; EWiiExtensionControllerType m_eExtensionControllerType; - SDL_bool m_bUseButtonLabels; SDL_bool m_bPlayerLights; int m_nPlayerIndex; SDL_bool m_bRumbleActive; @@ -610,12 +609,6 @@ static void InitializeExtension(SDL_DriverWii_Context *ctx) ResetButtonPacketType(ctx); } -static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)userdata; - ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE); -} - static void UpdateSlotLED(SDL_DriverWii_Context *ctx) { Uint8 leds; @@ -786,9 +779,6 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy } } - SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); - /* Initialize player index (needed for setting LEDs) */ ctx->m_nPlayerIndex = SDL_GetJoystickPlayerIndex(joystick); ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_TRUE); @@ -940,43 +930,10 @@ static const Uint8 GAMEPAD_BUTTON_DEFS[3][8] = { SDL_GAMEPAD_BUTTON_DPAD_UP, SDL_GAMEPAD_BUTTON_DPAD_LEFT, 0xFF /* ZR */, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_A, - SDL_GAMEPAD_BUTTON_Y, - SDL_GAMEPAD_BUTTON_B, - 0xFF /*ZL*/, - }, - { - SDL_GAMEPAD_BUTTON_RIGHT_STICK, - SDL_GAMEPAD_BUTTON_LEFT_STICK, - 0xFF /* Charging */, - 0xFF /* Plugged In */, - 0xFF /* Unused */, - 0xFF /* Unused */, - 0xFF /* Unused */, - 0xFF /* Unused */, - } -}; - -static const Uint8 GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = { - { - 0xFF /* Unused */, - SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, - SDL_GAMEPAD_BUTTON_START, - SDL_GAMEPAD_BUTTON_GUIDE, - SDL_GAMEPAD_BUTTON_BACK, - SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, - SDL_GAMEPAD_BUTTON_DPAD_DOWN, - SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - }, - { - SDL_GAMEPAD_BUTTON_DPAD_UP, - SDL_GAMEPAD_BUTTON_DPAD_LEFT, - 0xFF /* ZR */, - SDL_GAMEPAD_BUTTON_Y, - SDL_GAMEPAD_BUTTON_B, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_A, + SDL_GAMEPAD_BUTTON_NORTH, + SDL_GAMEPAD_BUTTON_EAST, + SDL_GAMEPAD_BUTTON_WEST, + SDL_GAMEPAD_BUTTON_SOUTH, 0xFF /*ZL*/, }, { @@ -1006,43 +963,10 @@ static const Uint8 MP_GAMEPAD_BUTTON_DEFS[3][8] = { 0xFF /* Motion Plus data */, 0xFF /* Motion Plus data */, 0xFF /* ZR */, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_A, - SDL_GAMEPAD_BUTTON_Y, - SDL_GAMEPAD_BUTTON_B, - 0xFF /*ZL*/, - }, - { - SDL_GAMEPAD_BUTTON_RIGHT_STICK, - SDL_GAMEPAD_BUTTON_LEFT_STICK, - 0xFF /* Charging */, - 0xFF /* Plugged In */, - 0xFF /* Unused */, - 0xFF /* Unused */, - 0xFF /* Unused */, - 0xFF /* Unused */, - } -}; - -static const Uint8 MP_GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = { - { - 0xFF /* Unused */, - SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, - SDL_GAMEPAD_BUTTON_START, - SDL_GAMEPAD_BUTTON_GUIDE, - SDL_GAMEPAD_BUTTON_BACK, - SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, - SDL_GAMEPAD_BUTTON_DPAD_DOWN, - SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - }, - { - 0xFF /* Motion Plus data */, - 0xFF /* Motion Plus data */, - 0xFF /* ZR */, - SDL_GAMEPAD_BUTTON_Y, - SDL_GAMEPAD_BUTTON_B, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_A, + SDL_GAMEPAD_BUTTON_NORTH, + SDL_GAMEPAD_BUTTON_EAST, + SDL_GAMEPAD_BUTTON_WEST, + SDL_GAMEPAD_BUTTON_SOUTH, 0xFF /*ZL*/, }, { @@ -1083,7 +1007,7 @@ static const Uint8 MP_FIXUP_DPAD_BUTTON_DEFS[2][8] = { static void HandleWiiUProButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data) { static const Uint8 axes[] = { SDL_GAMEPAD_AXIS_LEFTX, SDL_GAMEPAD_AXIS_RIGHTX, SDL_GAMEPAD_AXIS_LEFTY, SDL_GAMEPAD_AXIS_RIGHTY }; - const Uint8(*buttons)[8] = ctx->m_bUseButtonLabels ? GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS_POSITIONAL; + const Uint8(*buttons)[8] = GAMEPAD_BUTTON_DEFS; Uint8 zl, zr; int i; @@ -1112,7 +1036,7 @@ static void HandleWiiUProButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *jo static void HandleGamepadControllerButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data) { - const Uint8(*buttons)[8] = ctx->m_bUseButtonLabels ? ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS) : ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS_POSITIONAL : GAMEPAD_BUTTON_DEFS_POSITIONAL); + const Uint8(*buttons)[8] = (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS; Uint8 lx, ly, rx, ry, zl, zr; if (data->ucNExtensionBytes < 6) { @@ -1194,10 +1118,10 @@ static void HandleWiiRemoteButtonDataAsMainController(SDL_DriverWii_Context *ctx 0xFF /* Unused */, }, { - SDL_GAMEPAD_BUTTON_Y, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_A, - SDL_GAMEPAD_BUTTON_B, + SDL_GAMEPAD_BUTTON_NORTH, + SDL_GAMEPAD_BUTTON_WEST, + SDL_GAMEPAD_BUTTON_SOUTH, + SDL_GAMEPAD_BUTTON_EAST, SDL_GAMEPAD_BUTTON_BACK, 0xFF /* Unused */, 0xFF /* Unused */, @@ -1637,9 +1561,6 @@ static void HIDAPI_DriverWii_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joysti { SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; - SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, - SDL_GameControllerButtonReportingHintChanged, ctx); - SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_PlayerLEDHintChanged, ctx); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index c83cc3dcd066f..bd9565303c4a5 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -284,10 +284,10 @@ static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_D SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } axis = ((int)data[4] * 257) - 32768; diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 04e8010ae91b7..954e16c09b6c5 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -251,10 +251,10 @@ static void HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_ SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } axis = ((int)data[4] * 257) - 32768; diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index b1a1af2085295..d21881548c2df 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -659,10 +659,10 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D if (ctx->last_state[0] != data[0]) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } if (ctx->last_state[1] != data[1]) { @@ -848,10 +848,10 @@ static void HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, SDL_Dr static void HIDAPI_DriverXboxOneBluetooth_HandleButtons16(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, const Uint8 *data, int size) { if (ctx->last_state[14] != data[14]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED); @@ -875,10 +875,10 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons16(Uint64 timestamp, SDL_ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size) { if (ctx->last_state[14] != data[14]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index d8ce2f8315041..b6dbb5c41b30d 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -589,22 +589,22 @@ static SDL_bool VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadM return SDL_FALSE; } - if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_A))) { + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH))) { out->a.kind = EMappingKind_Button; out->a.target = current_button++; } - if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_B))) { + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST))) { out->b.kind = EMappingKind_Button; out->b.target = current_button++; } - if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_X))) { + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST))) { out->x.kind = EMappingKind_Button; out->x.target = current_button++; } - if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_Y))) { + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH))) { out->y.kind = EMappingKind_Button; out->y.target = current_button++; } diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 67dcb9d7b2ad8..3fd7b7fcf2788 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -249,10 +249,10 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint64 match_state /* Bitwise map .RLDUWVQTS.KYXBA -> YXBA..WVQTKSRLDU */ (WORD)(match_state << 12 | (match_state & 0x0780) >> 1 | (match_state & 0x0010) << 1 | (match_state & 0x0040) >> 2 | (match_state & 0x7800) >> 11); /* Explicit - ((match_state & (1<> 5 | (match_state & 0x000F) << 2 | (match_state & 0x0010) >> 3 | (match_state & 0x0040) >> 6; /* Explicit - ((match_state & (1<showing_front = showing_front; } -void SetGamepadImageFaceStyle(GamepadImage *ctx, GamepadImageFaceStyle face_style) +void SetGamepadImageFaceButtonType(GamepadImage *ctx, SDL_GamepadType type) { if (!ctx) { return; } - ctx->face_style = face_style; + ctx->type = type; } -GamepadImageFaceStyle GetGamepadImageFaceStyle(GamepadImage *ctx) +SDL_GamepadType GetGamepadImageType(GamepadImage *ctx) { if (!ctx) { - return GAMEPAD_IMAGE_FACE_BLANK; + return SDL_GAMEPAD_TYPE_UNKNOWN; } - return ctx->face_style; + return ctx->type; } void SetGamepadImageDisplayMode(GamepadImage *ctx, ControllerDisplayMode display_mode) @@ -407,7 +384,7 @@ int GetGamepadImageElementAt(GamepadImage *ctx, float x, float y) rect.w = (float)ctx->button_width; rect.h = (float)ctx->button_height; if (SDL_PointInRectFloat(&point, &rect)) { - return GetRemappedButton(ctx->face_style, (SDL_GamepadButton)i); + return (SDL_GamepadButton)i; } } } @@ -440,29 +417,15 @@ void UpdateGamepadImageFromGamepad(GamepadImage *ctx, SDL_Gamepad *gamepad) return; } + ctx->type = SDL_GetGamepadType(gamepad); char *mapping = SDL_GetGamepadMapping(gamepad); - SDL_GamepadType gamepad_type = SDL_GetGamepadType(gamepad); - switch (gamepad_type) { - case SDL_GAMEPAD_TYPE_PS3: - case SDL_GAMEPAD_TYPE_PS4: - case SDL_GAMEPAD_TYPE_PS5: - ctx->face_style = GAMEPAD_IMAGE_FACE_SONY; - break; - case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO: - case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: - case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: - case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: - ctx->face_style = GAMEPAD_IMAGE_FACE_BAYX; - break; - default: - if (mapping && SDL_strstr(mapping, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS")) { - ctx->face_style = GAMEPAD_IMAGE_FACE_BAYX; - } else { - ctx->face_style = GAMEPAD_IMAGE_FACE_ABXY; + if (mapping) { + if (SDL_strstr(mapping, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS")) { + /* Just for display purposes */ + ctx->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO; } - break; + SDL_free(mapping); } - SDL_free(mapping); for (i = 0; i < SDL_GAMEPAD_BUTTON_TOUCHPAD; ++i) { const SDL_GamepadButton button = (SDL_GamepadButton)i; @@ -557,7 +520,7 @@ void RenderGamepadImage(GamepadImage *ctx) for (i = 0; i < SDL_arraysize(button_positions); ++i) { if (ctx->elements[i]) { - SDL_GamepadButton button_position = GetRemappedButton(ctx->face_style, (SDL_GamepadButton)i); + SDL_GamepadButton button_position = (SDL_GamepadButton)i; SDL_bool on_front = SDL_TRUE; if (i >= SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 && i <= SDL_GAMEPAD_BUTTON_LEFT_PADDLE2) { @@ -579,14 +542,14 @@ void RenderGamepadImage(GamepadImage *ctx) dst.w = (float)ctx->face_width; dst.h = (float)ctx->face_height; - switch (ctx->face_style) { - case GAMEPAD_IMAGE_FACE_ABXY: + switch (SDL_GetGamepadButtonLabelForType(ctx->type, SDL_GAMEPAD_BUTTON_SOUTH)) { + case SDL_GAMEPAD_BUTTON_LABEL_A: SDL_RenderTexture(ctx->renderer, ctx->face_abxy_texture, NULL, &dst); break; - case GAMEPAD_IMAGE_FACE_BAYX: + case SDL_GAMEPAD_BUTTON_LABEL_B: SDL_RenderTexture(ctx->renderer, ctx->face_bayx_texture, NULL, &dst); break; - case GAMEPAD_IMAGE_FACE_SONY: + case SDL_GAMEPAD_BUTTON_LABEL_CROSS: SDL_RenderTexture(ctx->renderer, ctx->face_sony_texture, NULL, &dst); break; default: @@ -665,10 +628,10 @@ void DestroyGamepadImage(GamepadImage *ctx) static const char *gamepad_button_names[] = { - "A", - "B", - "X", - "Y", + "South", + "East", + "West", + "North", "Back", "Guide", "Start", @@ -801,9 +764,45 @@ static SDL_bool GetBindingString(const char *label, char *mapping, char *text, s static SDL_bool GetButtonBindingString(SDL_GamepadButton button, char *mapping, char *text, size_t size) { char label[32]; + SDL_bool baxy_mapping = SDL_FALSE; SDL_snprintf(label, sizeof(label), ",%s:", SDL_GetGamepadStringForButton(button)); - return GetBindingString(label, mapping, text, size); + if (GetBindingString(label, mapping, text, size)) { + return SDL_TRUE; + } + + /* Try the legacy button names */ + if (SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + baxy_mapping = SDL_TRUE; + } + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + if (baxy_mapping) { + return GetBindingString(",b:", mapping, text, size); + } else { + return GetBindingString(",a:", mapping, text, size); + } + case SDL_GAMEPAD_BUTTON_EAST: + if (baxy_mapping) { + return GetBindingString(",a:", mapping, text, size); + } else { + return GetBindingString(",b:", mapping, text, size); + } + case SDL_GAMEPAD_BUTTON_WEST: + if (baxy_mapping) { + return GetBindingString(",y:", mapping, text, size); + } else { + return GetBindingString(",x:", mapping, text, size); + } + case SDL_GAMEPAD_BUTTON_NORTH: + if (baxy_mapping) { + return GetBindingString(",x:", mapping, text, size); + } else { + return GetBindingString(",y:", mapping, text, size); + } + default: + return SDL_FALSE; + } } static SDL_bool GetAxisBindingString(SDL_GamepadAxis axis, int direction, char *mapping, char *text, size_t size) @@ -2224,9 +2223,11 @@ static int FindMappingKey(const MappingParts *parts, const char *key) { int i; - for (i = 0; i < parts->num_elements; ++i) { - if (SDL_strcmp(key, parts->keys[i]) == 0) { - return i; + if (key) { + for (i = 0; i < parts->num_elements; ++i) { + if (SDL_strcmp(key, parts->keys[i]) == 0) { + return i; + } } } return -1; @@ -2243,6 +2244,79 @@ static void RemoveMappingValueAt(MappingParts *parts, int index) } } +static void ConvertBAXYMapping(MappingParts *parts) +{ + int i; + SDL_bool baxy_mapping = SDL_FALSE; + + for (i = 0; i < parts->num_elements; ++i) { + const char *key = parts->keys[i]; + const char *value = parts->values[i]; + + if (SDL_strcmp(key, "hint") == 0 && + SDL_strcmp(value, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") == 0) { + baxy_mapping = SDL_TRUE; + } + } + + if (!baxy_mapping) { + return; + } + + /* Swap buttons, invert hint */ + for (i = 0; i < parts->num_elements; ++i) { + char *key = parts->keys[i]; + char *value = parts->values[i]; + + if (SDL_strcmp(key, "a") == 0) { + parts->keys[i] = SDL_strdup("b"); + SDL_free(key); + } else if (SDL_strcmp(key, "b") == 0) { + parts->keys[i] = SDL_strdup("a"); + SDL_free(key); + } else if (SDL_strcmp(key, "x") == 0) { + parts->keys[i] = SDL_strdup("y"); + SDL_free(key); + } else if (SDL_strcmp(key, "y") == 0) { + parts->keys[i] = SDL_strdup("x"); + SDL_free(key); + } else if (SDL_strcmp(key, "hint") == 0 && + SDL_strcmp(value, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") == 0) { + parts->values[i] = SDL_strdup("!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1"); + SDL_free(value); + } + } +} + +static void UseLegacyButtonNames(MappingParts *parts) +{ + int i; + + for (i = 0; i < parts->num_elements; ++i) { + char *key = parts->keys[i]; + + if (SDL_strcmp(key, "s") == 0) { + parts->keys[i] = SDL_strdup("a"); + SDL_free(key); + } else if (SDL_strcmp(key, "e") == 0) { + parts->keys[i] = SDL_strdup("b"); + SDL_free(key); + } else if (SDL_strcmp(key, "w") == 0) { + parts->keys[i] = SDL_strdup("x"); + SDL_free(key); + } else if (SDL_strcmp(key, "n") == 0) { + parts->keys[i] = SDL_strdup("y"); + SDL_free(key); + } + } +} + +static void UpdateLegacyElements(MappingParts *parts) +{ + ConvertBAXYMapping(parts); + UseLegacyButtonNames(parts); +} + static SDL_bool CombineMappingAxes(MappingParts *parts) { int i, matching, axis; @@ -2337,6 +2411,7 @@ static char *JoinMapping(MappingParts *parts) const char *name; MappingSortEntry *sort_order; + UpdateLegacyElements(parts); CombineMappingAxes(parts); guid = parts->guid; @@ -2420,6 +2495,43 @@ static char *RecreateMapping(MappingParts *parts, char *mapping) return mapping; } +static const char *GetLegacyKey(const char *key, SDL_bool baxy) +{ + if (SDL_strcmp(key, SDL_GetGamepadStringForButton(SDL_GAMEPAD_BUTTON_SOUTH)) == 0) { + if (baxy) { + return "b"; + } else { + return "a"; + } + } + + if (SDL_strcmp(key, SDL_GetGamepadStringForButton(SDL_GAMEPAD_BUTTON_EAST)) == 0) { + if (baxy) { + return "a"; + } else { + return "b"; + } + } + + if (SDL_strcmp(key, SDL_GetGamepadStringForButton(SDL_GAMEPAD_BUTTON_WEST)) == 0) { + if (baxy) { + return "y"; + } else { + return "x"; + } + } + + if (SDL_strcmp(key, SDL_GetGamepadStringForButton(SDL_GAMEPAD_BUTTON_NORTH)) == 0) { + if (baxy) { + return "y"; + } else { + return "x"; + } + } + + return key; +} + static SDL_bool MappingHasKey(const char *mapping, const char *key) { int i; @@ -2428,6 +2540,14 @@ static SDL_bool MappingHasKey(const char *mapping, const char *key) SplitMapping(mapping, &parts); i = FindMappingKey(&parts, key); + if (i < 0) { + SDL_bool baxy_mapping = SDL_FALSE; + + if (SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + baxy_mapping = SDL_TRUE; + } + i = FindMappingKey(&parts, GetLegacyKey(key, baxy_mapping)); + } if (i >= 0) { result = SDL_TRUE; } @@ -2444,6 +2564,14 @@ static char *GetMappingValue(const char *mapping, const char *key) SplitMapping(mapping, &parts); i = FindMappingKey(&parts, key); + if (i < 0) { + SDL_bool baxy_mapping = SDL_FALSE; + + if (SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + baxy_mapping = SDL_TRUE; + } + i = FindMappingKey(&parts, GetLegacyKey(key, baxy_mapping)); + } if (i >= 0) { value = parts.values[i]; parts.values[i] = NULL; /* So we don't free it */ diff --git a/test/gamepadutils.h b/test/gamepadutils.h index f0b62f9faf761..77ebe1bcb58a0 100644 --- a/test/gamepadutils.h +++ b/test/gamepadutils.h @@ -20,14 +20,6 @@ typedef enum CONTROLLER_MODE_BINDING, } ControllerDisplayMode; -typedef enum -{ - GAMEPAD_IMAGE_FACE_BLANK, - GAMEPAD_IMAGE_FACE_ABXY, - GAMEPAD_IMAGE_FACE_BAYX, - GAMEPAD_IMAGE_FACE_SONY, -} GamepadImageFaceStyle; - enum { SDL_GAMEPAD_ELEMENT_INVALID = -1, @@ -63,8 +55,8 @@ extern GamepadImage *CreateGamepadImage(SDL_Renderer *renderer); extern void SetGamepadImagePosition(GamepadImage *ctx, int x, int y); extern void GetGamepadImageArea(GamepadImage *ctx, SDL_Rect *area); extern void SetGamepadImageShowingFront(GamepadImage *ctx, SDL_bool showing_front); -extern void SetGamepadImageFaceStyle(GamepadImage *ctx, GamepadImageFaceStyle face_style); -extern GamepadImageFaceStyle GetGamepadImageFaceStyle(GamepadImage *ctx); +extern void SetGamepadImageType(GamepadImage *ctx, SDL_GamepadType type); +extern SDL_GamepadType GetGamepadImageType(GamepadImage *ctx); extern void SetGamepadImageDisplayMode(GamepadImage *ctx, ControllerDisplayMode display_mode); extern int GetGamepadImageButtonWidth(GamepadImage *ctx); extern int GetGamepadImageButtonHeight(GamepadImage *ctx); diff --git a/test/testautomation_joystick.c b/test/testautomation_joystick.c index d1c76831e44ee..d3cc0793fe8ec 100644 --- a/test/testautomation_joystick.c +++ b/test/testautomation_joystick.c @@ -20,6 +20,7 @@ static int TestVirtualJoystick(void *arg) { SDL_VirtualJoystickDesc desc; SDL_Joystick *joystick = NULL; + SDL_Gamepad *gamepad = NULL; SDL_JoystickID device_id; SDLTest_AssertCheck(SDL_InitSubSystem(SDL_INIT_GAMEPAD) == 0, "SDL_InitSubSystem(SDL_INIT_GAMEPAD)"); @@ -52,13 +53,65 @@ static int TestVirtualJoystick(void *arg) SDLTest_AssertCheck(SDL_GetNumJoystickHats(joystick) == desc.nhats, "SDL_GetNumJoystickHats()"); SDLTest_AssertCheck(SDL_GetNumJoystickButtons(joystick) == desc.nbuttons, "SDL_GetNumJoystickButtons()"); - SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_A, SDL_PRESSED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_A, SDL_PRESSED)"); + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED)"); SDL_UpdateJoysticks(); - SDLTest_AssertCheck(SDL_GetJoystickButton(joystick, SDL_GAMEPAD_BUTTON_A) == SDL_PRESSED, "SDL_GetJoystickButton(SDL_GAMEPAD_BUTTON_A) == SDL_PRESSED"); - SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_A, SDL_RELEASED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_A, SDL_RELEASED)"); + SDLTest_AssertCheck(SDL_GetJoystickButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED, "SDL_GetJoystickButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED"); + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED)"); SDL_UpdateJoysticks(); - SDLTest_AssertCheck(SDL_GetJoystickButton(joystick, SDL_GAMEPAD_BUTTON_A) == SDL_RELEASED, "SDL_GetJoystickButton(SDL_GAMEPAD_BUTTON_A) == SDL_RELEASED"); + SDLTest_AssertCheck(SDL_GetJoystickButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED, "SDL_GetJoystickButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED"); + + gamepad = SDL_OpenGamepad(SDL_GetJoystickInstanceID(joystick)); + SDLTest_AssertCheck(gamepad != NULL, "SDL_OpenGamepad() succeeded"); + if (gamepad) { + SDLTest_AssertCheck(SDL_strcmp(SDL_GetGamepadName(gamepad), desc.name) == 0, "SDL_GetGamepadName()"); + SDLTest_AssertCheck(SDL_GetGamepadVendor(gamepad) == desc.vendor_id, "SDL_GetGamepadVendor()"); + SDLTest_AssertCheck(SDL_GetGamepadProduct(gamepad) == desc.product_id, "SDL_GetGamepadProduct()"); + + /* Set an explicit mapping with a different name */ + SDL_SetGamepadMapping(SDL_GetJoystickInstanceID(joystick), "ff0013db5669727475616c2043007601,Virtual Gamepad,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,"); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetGamepadName(gamepad), "Virtual Gamepad") == 0, "SDL_GetGamepadName() == Virtual Gamepad"); + SDLTest_AssertCheck(SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_A, "SDL_GetGamepadButtonLabel(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_A"); + + /* Set the south button and verify that the gamepad responds */ + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED"); + + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED"); + + /* Set an explicit mapping with legacy Nintendo style buttons */ + SDL_SetGamepadMapping(SDL_GetJoystickInstanceID(joystick), "ff0013db5669727475616c2043007601,Virtual Nintendo Gamepad,a:b1,b:b0,x:b3,y:b2,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,"); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetGamepadName(gamepad), "Virtual Nintendo Gamepad") == 0, "SDL_GetGamepadName() == Virtual Nintendo Gamepad"); + SDLTest_AssertCheck(SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B, "SDL_GetGamepadButtonLabel(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B"); + + /* Set the south button and verify that the gamepad responds */ + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED"); + + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED"); + + /* Set an explicit mapping with PS4 style buttons */ + SDL_SetGamepadMapping(SDL_GetJoystickInstanceID(joystick), "ff0013db5669727475616c2043007601,Virtual PS4 Gamepad,type:ps4,cross:b0,circle:b1,square:b2,triangle:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,"); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetGamepadName(gamepad), "Virtual PS4 Gamepad") == 0, "SDL_GetGamepadName() == Virtual PS4 Gamepad"); + SDLTest_AssertCheck(SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_CROSS, "SDL_GetGamepadButtonLabel(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_CROSS"); + + /* Set the south button and verify that the gamepad responds */ + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_PRESSED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_PRESSED"); + + SDLTest_AssertCheck(SDL_SetJoystickVirtualButton(joystick, SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED) == 0, "SDL_SetJoystickVirtualButton(SDL_GAMEPAD_BUTTON_SOUTH, SDL_RELEASED)"); + SDL_UpdateJoysticks(); + SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED"); + + SDL_CloseGamepad(gamepad); + } SDL_CloseJoystick(joystick); } diff --git a/test/testcontroller.c b/test/testcontroller.c index 89b1b4368c730..a8b8bfa38d88e 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -102,10 +102,10 @@ static SDL_GamepadButton virtual_button_active = SDL_GAMEPAD_BUTTON_INVALID; static int s_arrBindingOrder[] = { /* Standard sequence */ - SDL_GAMEPAD_BUTTON_A, - SDL_GAMEPAD_BUTTON_B, - SDL_GAMEPAD_BUTTON_X, - SDL_GAMEPAD_BUTTON_Y, + SDL_GAMEPAD_BUTTON_SOUTH, + SDL_GAMEPAD_BUTTON_EAST, + SDL_GAMEPAD_BUTTON_WEST, + SDL_GAMEPAD_BUTTON_NORTH, SDL_GAMEPAD_BUTTON_DPAD_LEFT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, SDL_GAMEPAD_BUTTON_DPAD_UP, @@ -336,7 +336,7 @@ static void SetCurrentBindingElement(int element, SDL_bool flow) last_binding_element = binding_element; } binding_element = element; - binding_flow = flow || (element == SDL_GAMEPAD_BUTTON_A); + binding_flow = flow || (element == SDL_GAMEPAD_BUTTON_SOUTH); binding_advance_time = 0; for (i = 0; i < controller->num_axes; ++i) { @@ -498,8 +498,10 @@ static void CommitBindingElement(const char *binding, SDL_bool force) if (!ignore_binding && binding_flow && !force) { int existing = GetElementForBinding(mapping, binding); if (existing != SDL_GAMEPAD_ELEMENT_INVALID) { - if (existing == SDL_GAMEPAD_BUTTON_A) { - if (binding_element == SDL_GAMEPAD_BUTTON_A) { + SDL_GamepadButton action_forward = SDL_GAMEPAD_BUTTON_SOUTH; + SDL_GamepadButton action_backward = SDL_GAMEPAD_BUTTON_EAST; + if (existing == action_forward) { + if (binding_element == action_forward) { /* Just move on to the next one */ ignore_binding = SDL_TRUE; SetNextBindingElement(); @@ -509,9 +511,9 @@ static void CommitBindingElement(const char *binding, SDL_bool force) direction = 1; force = SDL_TRUE; } - } else if (existing == SDL_GAMEPAD_BUTTON_B) { - if (binding_element != SDL_GAMEPAD_BUTTON_A && - last_binding_element != SDL_GAMEPAD_BUTTON_A) { + } else if (existing == action_backward) { + if (binding_element != action_forward && + last_binding_element != action_forward) { /* Clear the current binding and move to the previous one */ binding = NULL; direction = -1; @@ -521,8 +523,8 @@ static void CommitBindingElement(const char *binding, SDL_bool force) /* We're rebinding the same thing, just move to the next one */ ignore_binding = SDL_TRUE; SetNextBindingElement(); - } else if (binding_element != SDL_GAMEPAD_BUTTON_A && - binding_element != SDL_GAMEPAD_BUTTON_B) { + } else if (binding_element != action_forward && + binding_element != action_backward) { ignore_binding = SDL_TRUE; } } @@ -572,7 +574,7 @@ static void SetDisplayMode(ControllerDisplayMode mode) if (MappingHasBindings(backup_mapping)) { SetCurrentBindingElement(SDL_GAMEPAD_ELEMENT_INVALID, SDL_FALSE); } else { - SetCurrentBindingElement(SDL_GAMEPAD_BUTTON_A, SDL_TRUE); + SetCurrentBindingElement(SDL_GAMEPAD_BUTTON_SOUTH, SDL_TRUE); } } else { if (backup_mapping) { @@ -701,30 +703,31 @@ static const char *GetBindingInstruction(void) switch (binding_element) { case SDL_GAMEPAD_ELEMENT_INVALID: return "Select an element to bind from the list on the left"; - case SDL_GAMEPAD_BUTTON_A: - if (GetGamepadImageFaceStyle(image) == GAMEPAD_IMAGE_FACE_SONY) { - return "Press the Cross (X) button"; - } else { + case SDL_GAMEPAD_BUTTON_SOUTH: + case SDL_GAMEPAD_BUTTON_EAST: + case SDL_GAMEPAD_BUTTON_WEST: + case SDL_GAMEPAD_BUTTON_NORTH: + switch (SDL_GetGamepadButtonLabelForType(GetGamepadImageType(image), (SDL_GamepadButton)binding_element)) { + case SDL_GAMEPAD_BUTTON_LABEL_A: return "Press the A button"; - } - case SDL_GAMEPAD_BUTTON_B: - if (GetGamepadImageFaceStyle(image) == GAMEPAD_IMAGE_FACE_SONY) { - return "Press the Circle button"; - } else { + case SDL_GAMEPAD_BUTTON_LABEL_B: return "Press the B button"; - } - case SDL_GAMEPAD_BUTTON_X: - if (GetGamepadImageFaceStyle(image) == GAMEPAD_IMAGE_FACE_SONY) { - return "Press the Square button"; - } else { + case SDL_GAMEPAD_BUTTON_LABEL_X: return "Press the X button"; - } - case SDL_GAMEPAD_BUTTON_Y: - if (GetGamepadImageFaceStyle(image) == GAMEPAD_IMAGE_FACE_SONY) { - return "Press the Triangle button"; - } else { + case SDL_GAMEPAD_BUTTON_LABEL_Y: return "Press the Y button"; + case SDL_GAMEPAD_BUTTON_LABEL_CROSS: + return "Press the Cross (X) button"; + case SDL_GAMEPAD_BUTTON_LABEL_CIRCLE: + return "Press the Circle button"; + case SDL_GAMEPAD_BUTTON_LABEL_SQUARE: + return "Press the Square button"; + case SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE: + return "Press the Triangle button"; + default: + return ""; } + break; case SDL_GAMEPAD_BUTTON_BACK: return "Press the left center button (Back/View/Share)"; case SDL_GAMEPAD_BUTTON_GUIDE: @@ -1298,6 +1301,30 @@ static void DrawGamepadInfo(SDL_Renderer *renderer) } } +static const char *GetButtonLabel(SDL_GamepadType type, SDL_GamepadButton button) +{ + switch (SDL_GetGamepadButtonLabelForType(type, button)) { + case SDL_GAMEPAD_BUTTON_LABEL_A: + return "A"; + case SDL_GAMEPAD_BUTTON_LABEL_B: + return "B"; + case SDL_GAMEPAD_BUTTON_LABEL_X: + return "X"; + case SDL_GAMEPAD_BUTTON_LABEL_Y: + return "Y"; + case SDL_GAMEPAD_BUTTON_LABEL_CROSS: + return "Cross (X)"; + case SDL_GAMEPAD_BUTTON_LABEL_CIRCLE: + return "Circle"; + case SDL_GAMEPAD_BUTTON_LABEL_SQUARE: + return "Square"; + case SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE: + return "Triangle"; + default: + return "UNKNOWN"; + } +} + static void DrawBindingTips(SDL_Renderer *renderer) { const char *text; @@ -1317,7 +1344,6 @@ static void DrawBindingTips(SDL_Renderer *renderer) } else { Uint8 r, g, b, a; SDL_FRect rect; - SDL_bool bound_A, bound_B; y -= (FONT_CHARACTER_SIZE + BUTTON_MARGIN) / 2; @@ -1339,10 +1365,15 @@ static void DrawBindingTips(SDL_Renderer *renderer) } else if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) { text = "(press ESC to cancel)"; } else { - bound_A = MappingHasElement(controller->mapping, SDL_GAMEPAD_BUTTON_A); - bound_B = MappingHasElement(controller->mapping, SDL_GAMEPAD_BUTTON_B); - if (binding_flow && bound_A && bound_B) { - text = "(press A to skip, B to go back, and ESC to cancel)"; + SDL_GamepadType type = GetGamepadImageType(image); + SDL_GamepadButton action_forward = SDL_GAMEPAD_BUTTON_SOUTH; + SDL_bool bound_forward = MappingHasElement(controller->mapping, action_forward); + SDL_GamepadButton action_backward = SDL_GAMEPAD_BUTTON_EAST; + SDL_bool bound_backward = MappingHasElement(controller->mapping, action_backward); + if (binding_flow && bound_forward && bound_backward) { + static char dynamic_text[128]; + SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward)); + text = dynamic_text; } else { text = "(press SPACE to clear binding and ESC to cancel)"; } From 312faf930525198ed502d4aeca89c27d9bb0a877 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 15:37:21 -0800 Subject: [PATCH 319/725] Updated documentation for the controller face buttons --- include/SDL3/SDL_gamepad.h | 53 +++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index ccbd5d8baaf1b..9d11b8efc5d23 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -77,14 +77,31 @@ typedef enum /** * The list of buttons available on a gamepad + * + * For controllers that use a diamond pattern for the face buttons, + * the south/east/west/north buttons below correspond to the locations + * in the diamond pattern. For Xbox controllers, this would be A/B/X/Y, + * for Nintendo Switch controllers, this would be B/A/Y/X, for + * PlayStation controllers this would be Cross/Circle/Square/Triangle. + * + * For controllers that don't use a diamond pattern for the face buttons, + * the south/east/west/north buttons indicate the buttons labeled A, B, + * C, D, or 1, 2, 3, 4, or for controllers that aren't labeled, they are + * the primary, secondary, etc. buttons. + * + * The activate action is often the south button and the cancel action + * is often the east button, but in some regions this is reversed, so + * your game should allow remapping actions based on user preferences. + * + * You can query the labels for the face buttons using SDL_GetGamepadButtonLabel() */ typedef enum { SDL_GAMEPAD_BUTTON_INVALID = -1, - SDL_GAMEPAD_BUTTON_SOUTH, - SDL_GAMEPAD_BUTTON_EAST, - SDL_GAMEPAD_BUTTON_WEST, - SDL_GAMEPAD_BUTTON_NORTH, + SDL_GAMEPAD_BUTTON_SOUTH, /* Bottom face button (e.g. Xbox A button) */ + SDL_GAMEPAD_BUTTON_EAST, /* Right face button (e.g. Xbox B button) */ + SDL_GAMEPAD_BUTTON_WEST, /* Left face button (e.g. Xbox X button) */ + SDL_GAMEPAD_BUTTON_NORTH, /* Top face button (e.g. Xbox Y button) */ SDL_GAMEPAD_BUTTON_BACK, SDL_GAMEPAD_BUTTON_GUIDE, SDL_GAMEPAD_BUTTON_START, @@ -96,12 +113,12 @@ typedef enum SDL_GAMEPAD_BUTTON_DPAD_DOWN, SDL_GAMEPAD_BUTTON_DPAD_LEFT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button) */ - SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /* Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1) */ - SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /* Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3) */ - SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /* Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2) */ - SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /* Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4) */ - SDL_GAMEPAD_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */ + SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button) */ + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /* Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1) */ + SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /* Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3) */ + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /* Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2) */ + SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /* Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4) */ + SDL_GAMEPAD_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */ SDL_GAMEPAD_BUTTON_MAX } SDL_GamepadButton; @@ -115,14 +132,14 @@ typedef enum typedef enum { SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN, - SDL_GAMEPAD_BUTTON_LABEL_A, /**< The south button for Xbox controllers, the east button for Nintendo controllers */ - SDL_GAMEPAD_BUTTON_LABEL_B, /**< The east button for Xbox controllers, the south button for Nintendo controllers */ - SDL_GAMEPAD_BUTTON_LABEL_X, /**< The west button for Xbox controllers, the north button for Nintendo controllers */ - SDL_GAMEPAD_BUTTON_LABEL_Y, /**< The north button for Xbox controllers, the west button for Nintendo controllers */ - SDL_GAMEPAD_BUTTON_LABEL_CROSS, /**< The south button for Playstation controllers */ - SDL_GAMEPAD_BUTTON_LABEL_CIRCLE, /**< The east button for Playstation controllers */ - SDL_GAMEPAD_BUTTON_LABEL_SQUARE, /**< The west button for Playstation controllers */ - SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE /**< The north button for Playstation controllers */ + SDL_GAMEPAD_BUTTON_LABEL_A, + SDL_GAMEPAD_BUTTON_LABEL_B, + SDL_GAMEPAD_BUTTON_LABEL_X, + SDL_GAMEPAD_BUTTON_LABEL_Y, + SDL_GAMEPAD_BUTTON_LABEL_CROSS, + SDL_GAMEPAD_BUTTON_LABEL_CIRCLE, + SDL_GAMEPAD_BUTTON_LABEL_SQUARE, + SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE } SDL_GamepadButtonLabel; /** From a5a47d3beeab466f5af0309521ee1f751a0cffb9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 15:38:24 -0800 Subject: [PATCH 320/725] Fixed crash if there is no controller mapping --- test/gamepadutils.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/gamepadutils.c b/test/gamepadutils.c index 80e69630aa4b4..123224336a651 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -766,6 +766,10 @@ static SDL_bool GetButtonBindingString(SDL_GamepadButton button, char *mapping, char label[32]; SDL_bool baxy_mapping = SDL_FALSE; + if (!mapping) { + return SDL_FALSE; + } + SDL_snprintf(label, sizeof(label), ",%s:", SDL_GetGamepadStringForButton(button)); if (GetBindingString(label, mapping, text, size)) { return SDL_TRUE; @@ -2543,7 +2547,7 @@ static SDL_bool MappingHasKey(const char *mapping, const char *key) if (i < 0) { SDL_bool baxy_mapping = SDL_FALSE; - if (SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + if (mapping && SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { baxy_mapping = SDL_TRUE; } i = FindMappingKey(&parts, GetLegacyKey(key, baxy_mapping)); @@ -2567,7 +2571,7 @@ static char *GetMappingValue(const char *mapping, const char *key) if (i < 0) { SDL_bool baxy_mapping = SDL_FALSE; - if (SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { + if (mapping && SDL_strstr(mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) { baxy_mapping = SDL_TRUE; } i = FindMappingKey(&parts, GetLegacyKey(key, baxy_mapping)); From d98e1bdfe1f91ef4453912997b379047bedc3f43 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 16:11:10 -0800 Subject: [PATCH 321/725] Use the standard gamepad type for Switch Pro controllers using the GameCube form factor --- src/joystick/SDL_gamepad.c | 40 +++--- src/joystick/SDL_joystick.c | 21 +++ src/joystick/SDL_joystick_c.h | 3 + src/joystick/controller_list.h | 2 +- src/joystick/hidapi/SDL_hidapi_switch.c | 177 +++++++++++------------- 5 files changed, 121 insertions(+), 122 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 9db1c31c2db23..fabec016f5b12 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -798,31 +798,23 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid /* The original SHIELD controller has a touchpad as well */ SDL_strlcat(mapping_string, "touchpad:b16,", sizeof(mapping_string)); } - } else { - switch (SDL_GetGamepadTypeFromGUID(guid, NULL)) { - case SDL_GAMEPAD_TYPE_PS4: - /* PS4 controllers have an additional touchpad button */ - SDL_strlcat(mapping_string, "touchpad:b15,", sizeof(mapping_string)); - break; - case SDL_GAMEPAD_TYPE_PS5: - /* PS5 controllers have a microphone button and an additional touchpad button */ - SDL_strlcat(mapping_string, "touchpad:b15,misc1:b16,", sizeof(mapping_string)); - /* DualSense Edge controllers have paddles */ - if (SDL_IsJoystickDualSenseEdge(vendor, product)) { - SDL_strlcat(mapping_string, "paddle1:b20,paddle2:b19,paddle3:b18,paddle4:b17,", sizeof(mapping_string)); - } - break; - case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO: - /* Nintendo Switch Pro controllers have a screenshot button */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); - break; - default: - if (vendor == 0 && product == 0) { - /* This is a Bluetooth Nintendo Switch Pro controller */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); - } - break; + } else if (SDL_IsJoystickPS4(vendor, product)) { + /* PS4 controllers have an additional touchpad button */ + SDL_strlcat(mapping_string, "touchpad:b15,", sizeof(mapping_string)); + } else if (SDL_IsJoystickPS5(vendor, product)) { + /* PS5 controllers have a microphone button and an additional touchpad button */ + SDL_strlcat(mapping_string, "touchpad:b15,misc1:b16,", sizeof(mapping_string)); + /* DualSense Edge controllers have paddles */ + if (SDL_IsJoystickDualSenseEdge(vendor, product)) { + SDL_strlcat(mapping_string, "paddle1:b20,paddle2:b19,paddle3:b18,paddle4:b17,", sizeof(mapping_string)); } + } else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) || + SDL_IsJoystickNintendoSwitchProInputOnly(vendor, product)) { + /* Nintendo Switch Pro controllers have a screenshot button */ + SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + } else if (vendor == 0 && product == 0) { + /* This is a Bluetooth Nintendo Switch Pro controller */ + SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); } } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 3d030e179bfa7..14d0a39833fa7 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2368,6 +2368,10 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR) { type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR; + } else if (forUI && SDL_IsJoystickGameCube(vendor, product)) { + /* We don't have a type for the Nintendo GameCube controller */ + type = SDL_GAMEPAD_TYPE_STANDARD; + } else { switch (GuessControllerType(vendor, product)) { case k_eControllerType_XBox360Controller: @@ -2595,6 +2599,23 @@ SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; } +SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id) +{ + static Uint32 gamecube_formfactor[] = { + MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ + MAKE_VIDPID(0x20d6, 0xa711), /* PowerA Wired Controller Nintendo GameCube Style */ + }; + Uint32 id = MAKE_VIDPID(vendor_id, product_id); + int i; + + for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) { + if (id == gamecube_formfactor[i]) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id) { return ((vendor_id == USB_VENDOR_AMAZON && product_id == USB_PRODUCT_AMAZON_LUNA_CONTROLLER) || diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index d81896e28e6be..8b37204d5a8e6 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -108,6 +108,9 @@ extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id); extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id); +/* Function to return whether a joystick is a Nintendo GameCube style controller */ +extern SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id); + /* Function to return whether a joystick is an Amazon Luna controller */ extern SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id); diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index ffb5a46bde5a9..331bf171588ed 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -567,7 +567,7 @@ static const ControllerDescription_t arrControllers[] = { // The first two, at least, shouldn't have their buttons remapped, and since we // can't tell which model we're actually using, we won't do any button remapping // for any of them. - { MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol + { MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol, there is also a version of this that looks like a GameCube controller { MAKE_CONTROLLER_ID( 0x0e6f, 0x0180 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Pro Controller for Nintendo Switch { MAKE_CONTROLLER_ID( 0x0e6f, 0x0181 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Deluxe Wired Pro Controller for Nintendo Switch { MAKE_CONTROLLER_ID( 0x0e6f, 0x0184 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Deluxe+ Audio Controller diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index e9ad734d9adc6..46ffc29da3b0d 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -263,7 +263,6 @@ typedef struct SDL_HIDAPI_Device *device; SDL_Joystick *joystick; SDL_bool m_bInputOnly; - SDL_bool m_bIsGameCube; SDL_bool m_bUseButtonLabels; SDL_bool m_bPlayerLights; int m_nPlayerIndex; @@ -909,8 +908,7 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; } - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, - SDL_MIN_SINT16, SDL_MAX_SINT16); + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue) @@ -927,8 +925,7 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue; } - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, - SDL_MIN_SINT16, SDL_MAX_SINT16); + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button) @@ -1034,7 +1031,10 @@ static SDL_bool HasHomeLED(SDL_DriverSwitch_Context *ctx) static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType) { - /* These controllers don't have a diamond button configuration, so always use labels */ + /* Some controllers don't have a diamond button configuration, so should always use labels */ + if (SDL_IsJoystickGameCube(vendor_id, product_id)) { + return SDL_TRUE; + } switch (eControllerType) { case k_eSwitchDeviceInfoControllerType_HVCLeft: case k_eSwitchDeviceInfoControllerType_HVCRight: @@ -1048,25 +1048,6 @@ static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInf } } -static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id) -{ -#if 0 - static Uint32 gamecube_formfactor[] = { - MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ - MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */ - }; - Uint32 id = MAKE_VIDPID(vendor_id, product_id); - int i; - - for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) { - if (id == gamecube_formfactor[i]) { - return SDL_TRUE; - } - } -#endif - return SDL_FALSE; -} - static void HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata) { SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata); @@ -1183,73 +1164,80 @@ static SDL_bool HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device, static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device) { SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; - char serial[18]; - - switch (ctx->m_eControllerType) { - case k_eSwitchDeviceInfoControllerType_JoyConLeft: - HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT); - device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT; - break; - case k_eSwitchDeviceInfoControllerType_JoyConRight: - HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT); - device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT; - break; - case k_eSwitchDeviceInfoControllerType_ProController: - case k_eSwitchDeviceInfoControllerType_LicProController: - HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_PRO); - device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO; - break; - case k_eSwitchDeviceInfoControllerType_HVCLeft: - HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)"); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_HVCRight: - HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)"); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_NESLeft: - HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)"); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_NESRight: - HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)"); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_SNES: - HIDAPI_SetDeviceName(device, "Nintendo SNES Controller"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_N64: - HIDAPI_SetDeviceName(device, "Nintendo N64 Controller"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: - HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller"); - HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER); - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - case k_eSwitchDeviceInfoControllerType_Unknown: - /* We couldn't read the device info for this controller, might not be fully compliant */ - return; - default: - device->type = SDL_GAMEPAD_TYPE_STANDARD; - break; - } - device->guid.data[15] = ctx->m_eControllerType; - (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - ctx->m_rgucMACAddress[0], - ctx->m_rgucMACAddress[1], - ctx->m_rgucMACAddress[2], - ctx->m_rgucMACAddress[3], - ctx->m_rgucMACAddress[4], - ctx->m_rgucMACAddress[5]); - HIDAPI_SetDeviceSerial(device, serial); + if (ctx->m_bInputOnly) { + if (SDL_IsJoystickGameCube(device->vendor_id, device->product_id)) { + device->type = SDL_GAMEPAD_TYPE_STANDARD; + } + } else { + char serial[18]; + + switch (ctx->m_eControllerType) { + case k_eSwitchDeviceInfoControllerType_JoyConLeft: + HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT); + device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT; + break; + case k_eSwitchDeviceInfoControllerType_JoyConRight: + HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT); + device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT; + break; + case k_eSwitchDeviceInfoControllerType_ProController: + case k_eSwitchDeviceInfoControllerType_LicProController: + HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_PRO); + device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO; + break; + case k_eSwitchDeviceInfoControllerType_HVCLeft: + HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)"); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_HVCRight: + HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)"); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_NESLeft: + HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)"); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_NESRight: + HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)"); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_SNES: + HIDAPI_SetDeviceName(device, "Nintendo SNES Controller"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_N64: + HIDAPI_SetDeviceName(device, "Nintendo N64 Controller"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: + HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller"); + HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER); + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + case k_eSwitchDeviceInfoControllerType_Unknown: + /* We couldn't read the device info for this controller, might not be fully compliant */ + return; + default: + device->type = SDL_GAMEPAD_TYPE_STANDARD; + break; + } + device->guid.data[15] = ctx->m_eControllerType; + + (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", + ctx->m_rgucMACAddress[0], + ctx->m_rgucMACAddress[1], + ctx->m_rgucMACAddress[2], + ctx->m_rgucMACAddress[3], + ctx->m_rgucMACAddress[4], + ctx->m_rgucMACAddress[5]); + HIDAPI_SetDeviceSerial(device, serial); + } } static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) @@ -1267,11 +1255,6 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device); ctx->m_bSyncWrite = SDL_TRUE; - if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) { - /* This is a controller shaped like a GameCube controller, with a large central A button */ - ctx->m_bIsGameCube = SDL_TRUE; - } - /* Find out whether or not we can send output reports */ ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id); if (!ctx->m_bInputOnly) { @@ -1280,8 +1263,8 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]); BReadDeviceInfo(ctx); - UpdateDeviceIdentity(device); } + UpdateDeviceIdentity(device); /* Prefer the USB device over the Bluetooth device */ if (device->is_bluetooth) { From fbb6934905ec3ff75c920db619ef199b4175b636 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 16:34:33 -0800 Subject: [PATCH 322/725] Added support for the Dragonrise GameCube adapter with VID 0x1843 --- src/joystick/SDL_gamepad.c | 4 +++- src/joystick/hidapi/SDL_hidapi_gamecube.c | 4 +++- src/joystick/usb_ids.h | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index fabec016f5b12..a365254b3b957 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -701,7 +701,9 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); if ((vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) || - (vendor == USB_VENDOR_DRAGONRISE && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) { + (vendor == USB_VENDOR_DRAGONRISE && + (product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 || + product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2))) { /* GameCube driver has 12 buttons and 6 axes */ SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", sizeof(mapping_string)); } else if (vendor == USB_VENDOR_NINTENDO && diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 397a77f05749b..e52fbf9dc05bf 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -72,7 +72,9 @@ static SDL_bool HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *devic /* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */ return SDL_TRUE; } - if (vendor_id == USB_VENDOR_DRAGONRISE && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) { + if (vendor_id == USB_VENDOR_DRAGONRISE && + (product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 || + product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2)) { /* EVORETRO GameCube Controller Adapter */ return SDL_TRUE; } diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 875e988955969..08bd21bca52cc 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -63,7 +63,8 @@ #define USB_PRODUCT_BACKBONE_ONE_IOS_PS5 0x0104 #define USB_PRODUCT_GAMESIR_G7 0x1001 #define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400 -#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER 0x1846 +#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 0x1843 +#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2 0x1846 #define USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X 0x0150 #define USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X 0x014f #define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c From 87794d03ad0c0e2bcf1856e6bd3bab268e952b96 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 17:04:37 -0800 Subject: [PATCH 323/725] Added shortened name for "Nintendo Co., Ltd." --- src/joystick/SDL_joystick.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 14d0a39833fa7..8ac7f6d8b7564 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2130,6 +2130,7 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n { "HORI CO.,LTD", "HORI" }, { "HORI CO.,LTD.", "HORI" }, { "Mad Catz Inc.", "Mad Catz" }, + { "Nintendo Co., Ltd.", "Nintendo" }, { "NVIDIA Corporation ", "" }, { "Performance Designed Products", "PDP" }, { "QANBA USA, LLC", "Qanba" }, From 09d1e9defb49e53acefed0d2fd22b3a28584cd8f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 17:09:39 -0800 Subject: [PATCH 324/725] Only update the battery status for Bluetooth Switch Pro controllers Controllers that are plugged in are in the wired state --- src/joystick/hidapi/SDL_hidapi_switch.c | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 46ffc29da3b0d..db52c6f23dce5 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -2035,24 +2035,26 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, ~axis); } - /* High nibble of battery/connection byte is battery level, low nibble is connection status - * LSB of connection nibble is USB/Switch connection status - */ - if (packet->controllerState.ucBatteryAndConnection & 0x1) { - SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED); - } else { - /* LSB of the battery nibble is used to report charging. - * The battery level is reported from 0(empty)-8(full) + if (ctx->device->is_bluetooth) { + /* High nibble of battery/connection byte is battery level, low nibble is connection status + * LSB of connection nibble is USB/Switch connection status */ - int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4; - if (level == 0) { - SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY); - } else if (level <= 2) { - SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW); - } else if (level <= 6) { - SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM); + if (packet->controllerState.ucBatteryAndConnection & 0x1) { + SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED); } else { - SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL); + /* LSB of the battery nibble is used to report charging. + * The battery level is reported from 0(empty)-8(full) + */ + int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4; + if (level == 0) { + SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY); + } else if (level <= 2) { + SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW); + } else if (level <= 6) { + SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM); + } else { + SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL); + } } } From b374105975237fd75134e3008711d47da412a89b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Nov 2023 20:00:53 -0800 Subject: [PATCH 325/725] Replaced SDL_GetTextureDXGIResource() with texture properties Fixes https://github.com/libsdl-org/SDL/issues/8529 --- include/SDL3/SDL_render.h | 60 ++++++++----- include/SDL3/SDL_video.h | 108 +++++++++++++---------- src/dynapi/SDL_dynapi.sym | 1 - src/dynapi/SDL_dynapi_overrides.h | 1 - src/dynapi/SDL_dynapi_procs.h | 1 - src/render/SDL_render.c | 13 --- src/render/SDL_sysrender.h | 2 - src/render/direct3d11/SDL_render_d3d11.c | 25 +----- src/render/direct3d12/SDL_render_d3d12.c | 24 +---- src/render/opengl/SDL_render_gl.c | 6 ++ src/render/opengles2/SDL_render_gles2.c | 8 +- test/testffmpeg.c | 14 +-- 12 files changed, 121 insertions(+), 142 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 73c2c40cf8bfb..120543dd436e9 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -309,12 +309,13 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: "SDL.renderer.d3d9.device" - - * the IDirect3DDevice9 associated with the renderer + * The following properties are provided by SDL: + * ``` + * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with - * the renderer + * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer + * ``` * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call @@ -416,27 +417,42 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); -typedef struct IDXGIResource IDXGIResource; - -/** - * Get the DXGI resource associated with a texture. - * - * This is available when using the direct3d11 and direct3d12 renderers. - * - * Once you are done using the resource, you should release it to avoid a - * resource leak. - * - * \param texture the texture from which to get the associated resource - * \returns the DXGI resource associated with given texture or NULL if it is - * not available; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC IDXGIResource* SDLCALL SDL_GetTextureDXGIResource(SDL_Texture *texture); - /** * Get the properties associated with a texture. * + * The following properties are provided by SDL: + * + * With the direct3d11 renderer: + * ``` + * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture + * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture + * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture + * ``` + * + * With the direct3d12 renderer: + * ``` + * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture + * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture + * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture + * ``` + * + * With the opengl renderer: + * ``` + * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture + * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture + * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture + * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture + * ``` + * + * With the opengles2 renderer: + * ``` + * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture + * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture + * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture + * ``` + * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 8a466a68b4c94..e0363eccdfaf7 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -936,53 +936,71 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following properties are provided by SDL: * - * On Android: "SDL.window.android.window" - the ANativeWindow associated with - * the window "SDL.window.android.surface" - the EGLSurface associated with - * the window - * - * On iOS: "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow - * associated with the window "SDL.window.uikit.metal_view_tag" - the - * NSInteger tag assocated with metal views on the window - * - * On KMS/DRM: "SDL.window.kmsdrm.dev_index" - the device index associated - * with the window (e.g. the X in /dev/dri/cardX) "SDL.window.kmsdrm.drm_fd" - - * the DRM FD associated with the window "SDL.window.kmsdrm.gbm_dev" - the GBM - * device associated with the window - * - * On macOS: "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow - * associated with the window "SDL.window.cocoa.metal_view_tag" - the - * NSInteger tag assocated with metal views on the window - * - * On Vivante: "SDL.window.vivante.display" - the EGLNativeDisplayType - * associated with the window "SDL.window.vivante.window" - the - * EGLNativeWindowType associated with the window "SDL.window.vivante.surface" - * - the EGLSurface associated with the window - * - * On UWP: "SDL.window.winrt.window" - the IInspectable CoreWindow associated - * with the window - * - * On Windows: "SDL.window.win32.hwnd" - the HWND associated with the window + * On Android: + * ``` + * "SDL.window.android.window" - the ANativeWindow associated with the window + * "SDL.window.android.surface" - the EGLSurface associated with the window + * ``` + * + * On iOS: + * ``` + * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window + * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * ``` + * + * On KMS/DRM: + * ``` + * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) + * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window + * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window + * ``` + * + * On macOS: + * ``` + * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window + * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * ``` + * + * On Vivante: + * ``` + * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window + * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window + * "SDL.window.vivante.surface" - the EGLSurface associated with the window + * ``` + * + * On UWP: + * ``` + * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window + * ``` + * + * On Windows: + * ``` + * "SDL.window.win32.hwnd" - the HWND associated with the window * "SDL.window.win32.hdc" - the HDC associated with the window * "SDL.window.win32.instance" - the HINSTANCE associated with the window - * - * On Wayland: "SDL.window.wayland.registry" - the wl_registry associated with - * the window "SDL.window.wayland.display" - the wl_display associated with - * the window "SDL.window.wayland.surface" - the wl_surface associated with - * the window "SDL.window.wayland.egl_window" - the wl_egl_window associated - * with the window "SDL.window.wayland.xdg_surface" - the xdg_surface - * associated with the window "SDL.window.wayland.xdg_toplevel" - the - * xdg_toplevel role associated with the window "SDL.window.wayland.xdg_popup" - * - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with - * the window, in popup mode - * - * Note: The xdg_* window objects do not internally persist across window - * show/hide calls. They will be null if the window is hidden and must be - * queried each time it is shown. - * - * On X11: "SDL.window.x11.display" - the X11 Display associated with the - * window "SDL.window.x11.screen" - the screen number associated with the - * window "SDL.window.x11.window" - the X11 Window associated with the window + * ``` + * + * On Wayland: + * ``` + * "SDL.window.wayland.registry" - the wl_registry associated with the window + * "SDL.window.wayland.display" - the wl_display associated with the window + * "SDL.window.wayland.surface" - the wl_surface associated with the window + * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window + * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window + * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window + * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode + * ``` + * + * Note: The xdg_* window objects do not internally persist across window show/hide calls. + * They will be null if the window is hidden and must be queried each time it is shown. + * + * On X11: + * ``` + * "SDL.window.x11.display" - the X11 Display associated with the window + * "SDL.window.x11.screen" - the screen number associated with the window + * "SDL.window.x11.window" - the X11 Window associated with the window + * ``` * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 51e67d6e54add..8d7f46526128b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -898,7 +898,6 @@ SDL3_0.0.0 { SDL_SetAudioStreamFrequencyRatio; SDL_SetAudioPostmixCallback; SDL_GetAudioStreamQueued; - SDL_GetTextureDXGIResource; SDL_CreateProperties; SDL_LockProperties; SDL_UnlockProperties; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index ac3e1623326fd..e45318e2c9626 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -923,7 +923,6 @@ #define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL #define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL #define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL -#define SDL_GetTextureDXGIResource SDL_GetTextureDXGIResource_REAL #define SDL_CreateProperties SDL_CreateProperties_REAL #define SDL_LockProperties SDL_LockProperties_REAL #define SDL_UnlockProperties SDL_UnlockProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index dd9d7802b6633..fb8f1c457817d 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -957,7 +957,6 @@ SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a), SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 8bf12cc8396a5..0498f0edf8b03 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -4185,19 +4185,6 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) return NULL; } -IDXGIResource *SDL_GetTextureDXGIResource(SDL_Texture *texture) -{ - SDL_Renderer *renderer; - - CHECK_TEXTURE_MAGIC(texture, NULL); - renderer = texture->renderer; - if (renderer && renderer->GetTextureDXGIResource) { - return renderer->GetTextureDXGIResource(texture); - } - SDL_Unsupported(); - return NULL; -} - static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode) { if (blendMode == SDL_BLENDMODE_NONE_FULL) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index c2624084c9ebd..edba7e18e0c88 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -214,8 +214,6 @@ struct SDL_Renderer void *(*GetMetalLayer)(SDL_Renderer *renderer); void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer); - IDXGIResource *(*GetTextureDXGIResource)(SDL_Texture *texture); - /* The current renderer info */ SDL_RendererInfo info; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index b66cd4fd556fc..c51803bf0dc6f 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -184,7 +184,6 @@ static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0 #if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } }; #endif -static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } }; static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } }; static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } }; @@ -1115,6 +1114,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture", textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { @@ -1131,6 +1131,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_u", textureData->mainTextureU); result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, &textureDesc, @@ -1140,6 +1141,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_v", textureData->mainTextureV); } if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { @@ -1629,26 +1631,6 @@ static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; } -static IDXGIResource *D3D11_GetTextureDXGIResource(SDL_Texture *texture) -{ - D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; - IDXGIResource *resource = NULL; - HRESULT result; - - if (!textureData || !textureData->mainTexture) { - SDL_SetError("Texture is not currently available"); - return NULL; - } - - - result = ID3D11Texture2D_QueryInterface(textureData->mainTexture, &SDL_IID_IDXGIResource, (void **)&resource); - if (FAILED(result)) { - WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); - return NULL; - } - return resource; -} - static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; @@ -2426,7 +2408,6 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D11_LockTexture; renderer->UnlockTexture = D3D11_UnlockTexture; renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode; - renderer->GetTextureDXGIResource = D3D11_GetTextureDXGIResource; renderer->SetRenderTarget = D3D11_SetRenderTarget; renderer->QueueSetViewport = D3D11_QueueSetViewport; renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 00b24aec1559b..32196c51b6b64 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -253,7 +253,6 @@ static const GUID SDL_IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { static const GUID SDL_IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } }; static const GUID SDL_IID_ID3D12GraphicsCommandList2 = { 0x38C3E585, 0xFF17, 0x412C, { 0x91, 0x50, 0x4F, 0xC6, 0xF9, 0xD7, 0x2A, 0x28 } }; static const GUID SDL_IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } }; -static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } }; static const GUID SDL_IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } }; static const GUID SDL_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } }; @@ -1487,6 +1486,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture", textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { @@ -1508,6 +1508,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_u", textureData->mainTextureU); result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, &heapProps, @@ -1522,6 +1523,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_v", textureData->mainTextureV); } if (texture->format == SDL_PIXELFORMAT_NV12 || @@ -2065,25 +2067,6 @@ static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR; } -static IDXGIResource *D3D12_GetTextureDXGIResource(SDL_Texture *texture) -{ - D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; - IDXGIResource *resource = NULL; - HRESULT result; - - if (!textureData || !textureData->mainTexture) { - SDL_SetError("Texture is not currently available"); - return NULL; - } - - result = D3D_CALL(textureData->mainTexture, QueryInterface, D3D_GUID(SDL_IID_IDXGIResource), (void **)&resource); - if (FAILED(result)) { - WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); - return NULL; - } - return resource; -} - static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; @@ -2984,7 +2967,6 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D12_LockTexture; renderer->UnlockTexture = D3D12_UnlockTexture; renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode; - renderer->GetTextureDXGIResource = D3D12_GetTextureDXGIResource; renderer->SetRenderTarget = D3D12_SetRenderTarget; renderer->QueueSetViewport = D3D12_QueueSetViewport; renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 41a6cce73ba55..bc86432f5b747 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -518,6 +518,10 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) data->texw = (GLfloat)(texture->w) / texture_w; data->texh = (GLfloat)texture->h / texture_h; } + SDL_PropertiesID props = SDL_GetTextureProperties(texture); + SDL_SetProperty(props, "SDL.texture.opengl.texture", (void *)(uintptr_t)data->texture); + SDL_SetProperty(props, "SDL.texture.opengl.tex_w", (void *)(uintptr_t)(Uint32)(data->texw * 65536)); + SDL_SetProperty(props, "SDL.texture.opengl.tex_h", (void *)(uintptr_t)(Uint32)(data->texh * 65536)); data->format = format; data->formattype = type; @@ -590,6 +594,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); + SDL_SetProperty(props, "SDL.texture.opengl.texture_u", (void *)(uintptr_t)data->utexture); renderdata->glBindTexture(textype, data->vtexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, @@ -602,6 +607,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); + SDL_SetProperty(props, "SDL.texture.opengl.texture_v", (void *)(uintptr_t)data->vtexture); } if (texture->format == SDL_PIXELFORMAT_NV12 || diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 75f9e2c60ed79..21d04c45c37a7 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1499,6 +1499,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", (void *)(uintptr_t)data->texture_v); renderdata->glGenTextures(1, &data->texture_u); if (GL_CheckError("glGenTexures()", renderer) < 0) { @@ -1514,6 +1515,8 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", (void *)(uintptr_t)data->texture_u); + } else if (data->nv12) { renderdata->glGenTextures(1, &data->texture_u); if (GL_CheckError("glGenTexures()", renderer) < 0) { @@ -1529,6 +1532,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", (void *)(uintptr_t)data->texture_u); } #endif @@ -1549,6 +1553,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) return -1; } } + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", (void *)(uintptr_t)data->texture); if (texture->access == SDL_TEXTUREACCESS_TARGET) { data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); @@ -1995,9 +2000,6 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync) /************************************************************************************************* * Bind/unbinding of textures *************************************************************************************************/ -static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh); -static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture); - static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh) { GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; diff --git a/test/testffmpeg.c b/test/testffmpeg.c index aa240f49e6a0b..1fd3816be6660 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -625,20 +625,12 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) } } - IDXGIResource *dxgi_resource = SDL_GetTextureDXGIResource(*texture); - if (!dxgi_resource) { - return SDL_FALSE; - } - - ID3D11Resource *dx11_resource = NULL; - HRESULT result = IDXGIResource_QueryInterface(dxgi_resource, &SDL_IID_ID3D11Resource, (void **)&dx11_resource); - IDXGIResource_Release(dxgi_resource); - if (FAILED(result)) { - SDL_SetError("Couldn't get texture ID3D11Resource interface: 0x%x", result); + ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture"); + if (!dx11_resource) { + SDL_SetError("Couldn't get texture ID3D11Resource interface"); return SDL_FALSE; } ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, dx11_resource, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); - ID3D11Resource_Release(dx11_resource); return SDL_TRUE; #else From 04b6b2979f730d0cc9d0f192998ca78e8c0432b5 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Sat, 11 Nov 2023 10:28:24 +0100 Subject: [PATCH 326/725] Re-add SDL_assert() with non boolean ptr syntax (#8530) --- src/audio/SDL_audio.c | 32 +++++++++++------------ src/audio/SDL_audiocvt.c | 6 ++--- src/audio/SDL_audioqueue.c | 4 +-- src/audio/alsa/SDL_alsa_audio.c | 4 +-- src/audio/directsound/SDL_directsound.c | 2 +- src/audio/haiku/SDL_haikuaudio.cc | 6 ++--- src/audio/pipewire/SDL_pipewire.c | 4 +-- src/audio/pulseaudio/SDL_pulseaudio.c | 12 ++++----- src/audio/wasapi/SDL_wasapi.c | 10 +++---- src/audio/wasapi/SDL_wasapi_win32.c | 4 +-- src/core/linux/SDL_evdev.c | 6 ++--- src/core/windows/SDL_immdevice.c | 4 +-- src/events/SDL_keyboard.c | 2 +- src/filesystem/haiku/SDL_sysfilesystem.cc | 2 +- src/filesystem/unix/SDL_sysfilesystem.c | 2 +- src/haptic/android/SDL_syshaptic.c | 2 +- src/haptic/darwin/SDL_syshaptic.c | 2 +- src/haptic/linux/SDL_syshaptic.c | 2 +- src/haptic/windows/SDL_windowshaptic.c | 2 +- src/joystick/android/SDL_sysjoystick.c | 2 +- src/joystick/bsd/SDL_bsdjoystick.c | 2 +- src/joystick/linux/SDL_sysjoystick.c | 6 ++--- src/locale/windows/SDL_syslocale.c | 2 +- src/render/SDL_render.c | 20 +++++++------- src/render/direct3d/SDL_render_d3d.c | 2 +- src/render/software/SDL_render_sw.c | 2 +- src/video/SDL_shape.c | 2 +- src/video/SDL_video.c | 4 +-- src/video/wayland/SDL_waylandmouse.c | 2 +- src/video/windows/SDL_windowsopengl.c | 4 +-- src/video/x11/SDL_x11events.c | 2 +- src/video/x11/SDL_x11xfixes.c | 2 +- src/video/x11/SDL_x11xinput2.c | 4 +-- test/testaudio.c | 2 +- test/testautomation_surface.c | 10 +++---- 35 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 7d44695d24676..a19807b48bdce 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -139,7 +139,7 @@ static int GetDefaultSampleFramesFromFreq(const int freq) void OnAudioStreamCreated(SDL_AudioStream *stream) { - SDL_assert(stream); + SDL_assert(stream != NULL); // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! @@ -159,7 +159,7 @@ void OnAudioStreamCreated(SDL_AudioStream *stream) void OnAudioStreamDestroy(SDL_AudioStream *stream) { - SDL_assert(stream); + SDL_assert(stream != NULL); // NOTE that you can create an audio stream without initializing the audio subsystem, // but it will not be automatically destroyed during a later call to SDL_Quit! @@ -500,7 +500,7 @@ void RefPhysicalAudioDevice(SDL_AudioDevice *device) static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) { - SDL_assert(name); + SDL_assert(name != NULL); SDL_LockRWLockForReading(current_audio.device_hash_lock); const int shutting_down = SDL_AtomicGet(¤t_audio.shutting_down); @@ -593,8 +593,8 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, p->devid = device->instance_id; p->next = NULL; SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail); - SDL_assert(!current_audio.pending_events_tail->next); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); current_audio.pending_events_tail->next = p; current_audio.pending_events_tail = p; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -670,8 +670,8 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) if (first_disconnect) { if (pending.next) { // NULL if event is disabled or disaster struck. SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail); - SDL_assert(!current_audio.pending_events_tail->next); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -1127,7 +1127,7 @@ void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device) static int SDLCALL OutputAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; - SDL_assert(device); + SDL_assert(device != NULL); SDL_assert(!device->iscapture); SDL_OutputAudioThreadSetup(device); @@ -1233,7 +1233,7 @@ void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device) static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; - SDL_assert(device); + SDL_assert(device != NULL); SDL_assert(device->iscapture); SDL_CaptureAudioThreadSetup(device); @@ -1726,7 +1726,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int // !!! FIXME: Actually, why do we allow there to be an invalid format, again? // make sure start of list is sane. - SDL_assert(!logdev->bound_streams || (!logdev->bound_streams->prev_binding)); + SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL)); // lock all the streams upfront, so we can verify they aren't bound elsewhere and add them all in one block, as this is intended to add everything or nothing. for (int i = 0; i < num_streams; i++) { @@ -1735,7 +1735,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int retval = SDL_SetError("Stream #%d is NULL", i); } else { SDL_LockMutex(stream->lock); - SDL_assert((!stream->bound_device) == ((!stream->prev_binding) || (!stream->next_binding))); + SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); if (stream->bound_device) { retval = SDL_SetError("Stream #%d is already bound to a device", i); } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. @@ -1892,7 +1892,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au } else { SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. - SDL_assert(device); + SDL_assert(device != NULL); const SDL_bool iscapture = device->iscapture; if (iscapture) { @@ -2105,8 +2105,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (pending.next) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail); - SDL_assert(!current_audio.pending_events_tail->next); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -2186,8 +2186,8 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL if (pending.next) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_assert(current_audio.pending_events_tail); - SDL_assert(!current_audio.pending_events_tail->next); + SDL_assert(current_audio.pending_events_tail != NULL); + SDL_assert(current_audio.pending_events_tail->next == NULL); current_audio.pending_events_tail->next = pending.next; current_audio.pending_events_tail = pending_tail; SDL_UnlockRWLock(current_audio.device_hash_lock); diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index ed93684f2ef8b..a101410095704 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -221,8 +221,8 @@ static SDL_bool SDL_IsSupportedChannelCount(const int channels) void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, int src_channels, void *dst, SDL_AudioFormat dst_format, int dst_channels, void* scratch) { - SDL_assert(src); - SDL_assert(dst); + SDL_assert(src != NULL); + SDL_assert(dst != NULL); SDL_assert(SDL_IsSupportedAudioFormat(src_format)); SDL_assert(SDL_IsSupportedAudioFormat(dst_format)); SDL_assert(SDL_IsSupportedChannelCount(src_channels)); @@ -313,7 +313,7 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i SDL_assert(dst_channels <= SDL_arraysize(channel_converters[0])); channel_converter = channel_converters[src_channels - 1][dst_channels - 1]; - SDL_assert(channel_converter); + SDL_assert(channel_converter != NULL); // swap in some SIMD versions for a few of these. if (channel_converter == SDL_ConvertStereoToMono) { diff --git a/src/audio/SDL_audioqueue.c b/src/audio/SDL_audioqueue.c index 37a2f8457d237..763809fdca896 100644 --- a/src/audio/SDL_audioqueue.c +++ b/src/audio/SDL_audioqueue.c @@ -153,7 +153,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) return SDL_OutOfMemory(); } - SDL_assert((!track->head) && (!track->tail) && (track->queued_bytes == 0)); + SDL_assert((track->head == NULL) && (track->tail == NULL) && (track->queued_bytes == 0)); track->head = chunk; track->tail = chunk; } @@ -423,7 +423,7 @@ void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue) size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, SDL_bool *out_flushed) { SDL_AudioTrack *iter = *inout_iter; - SDL_assert(iter); + SDL_assert(iter != NULL); SDL_copyp(out_spec, &iter->spec); diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 71977c23f5132..e7505b88d9533 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -224,7 +224,7 @@ static const ALSA_Device default_capture_handle = { static const char *get_audio_device(void *handle, const int channels) { - SDL_assert(handle); // SDL2 used NULL to mean "default" but that's not true in SDL3. + SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3. ALSA_Device *dev = (ALSA_Device *)handle; if (SDL_strcmp(dev->name, "default") == 0) { @@ -723,7 +723,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A desc = (char *)name; } - SDL_assert(name); + SDL_assert(name != NULL); // some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output". // just chop the extra lines off, this seems to get a reasonable device diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index dc869bc46b377..f9ae9787166d3 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -358,7 +358,7 @@ static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b } SDL_assert(ptr1len == (DWORD)buflen); - SDL_assert(!ptr2); + SDL_assert(ptr2 == NULL); SDL_assert(ptr2len == 0); SDL_memcpy(buffer, ptr1, ptr1len); diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 1c223721376ae..5772fbe056507 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -39,7 +39,7 @@ extern "C" static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { - SDL_assert(device->hidden->current_buffer); + SDL_assert(device->hidden->current_buffer != NULL); SDL_assert(device->hidden->current_buffer_len > 0); *buffer_size = device->hidden->current_buffer_len; return device->hidden->current_buffer; @@ -48,7 +48,7 @@ static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static int HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { // We already wrote our output right into the BSoundPlayer's callback's stream. Just clean up our stuff. - SDL_assert(device->hidden->current_buffer); + SDL_assert(device->hidden->current_buffer != NULL); SDL_assert(device->hidden->current_buffer_len > 0); device->hidden->current_buffer = NULL; device->hidden->current_buffer_len = 0; @@ -59,7 +59,7 @@ static int HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i static void FillSound(void *data, void *stream, size_t len, const media_raw_audio_format & format) { SDL_AudioDevice *device = (SDL_AudioDevice *)data; - SDL_assert(!device->hidden->current_buffer); + SDL_assert(device->hidden->current_buffer == NULL); SDL_assert(device->hidden->current_buffer_len == 0); device->hidden->current_buffer = (Uint8 *) stream; device->hidden->current_buffer_len = (int) len; diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 2e5586eb8f116..bd4ee2ed00cb4 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -361,7 +361,7 @@ static struct io_node *io_list_get_by_id(Uint32 id) static void node_object_destroy(struct node_object *node) { - SDL_assert(node); + SDL_assert(node != NULL); spa_list_remove(&node->link); spa_hook_remove(&node->node_listener); @@ -373,7 +373,7 @@ static void node_object_destroy(struct node_object *node) // The pending node list static void pending_list_add(struct node_object *node) { - SDL_assert(node); + SDL_assert(node != NULL); spa_list_append(&hotplug_pending_list, &node->link); } diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 4cf9a6cf0fd2c..b4fd97e5c59f2 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -297,7 +297,7 @@ static void OperationStateChangeCallback(pa_operation *o, void *userdata) static void WaitForPulseOperation(pa_operation *o) { // This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. - SDL_assert(pulseaudio_threaded_mainloop); + SDL_assert(pulseaudio_threaded_mainloop != NULL); if (o) { // note that if PULSEAUDIO_pa_operation_set_state_callback == NULL, then `o` must have a callback that will signal pulseaudio_threaded_mainloop. // If not, on really old (earlier PulseAudio 4.0, from the year 2013!) installs, this call will block forever. @@ -339,8 +339,8 @@ static int ConnectToPulseServer(void) pa_mainloop_api *mainloop_api = NULL; int state = 0; - SDL_assert(!pulseaudio_threaded_mainloop); - SDL_assert(!pulseaudio_context); + SDL_assert(pulseaudio_threaded_mainloop == NULL); + SDL_assert(pulseaudio_context == NULL); // Set up a new main loop if (!(pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new())) { @@ -360,7 +360,7 @@ static int ConnectToPulseServer(void) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); mainloop_api = PULSEAUDIO_pa_threaded_mainloop_get_api(pulseaudio_threaded_mainloop); - SDL_assert(mainloop_api); // this never fails, right? + SDL_assert(mainloop_api != NULL); // this never fails, right? pulseaudio_context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName()); if (!pulseaudio_context) { @@ -609,8 +609,8 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) int format = PA_SAMPLE_INVALID; int retval = 0; - SDL_assert(pulseaudio_threaded_mainloop); - SDL_assert(pulseaudio_context); + SDL_assert(pulseaudio_threaded_mainloop != NULL); + SDL_assert(pulseaudio_context != NULL); // Initialize all variables that we clean on shutdown h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 934ac4e6e6c2c..938811a4a4720 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -433,7 +433,7 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) if (device->hidden->render) { if (WasapiFailed(device, IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer))) { - SDL_assert(!buffer); + SDL_assert(buffer == NULL); if (device->hidden->device_lost) { // just use an available buffer, we won't be playing it anyhow. *buffer_size = 0; // we'll recover during WaitDevice and try again. } @@ -562,7 +562,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) const AUDCLNT_SHAREMODE sharemode = AUDCLNT_SHAREMODE_SHARED; IAudioClient *client = device->hidden->client; - SDL_assert(client); + SDL_assert(client != NULL); #if defined(__WINRT__) || defined(__GDK__) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP. device->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); @@ -581,7 +581,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) if (FAILED(ret)) { return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret); } - SDL_assert(waveformat); + SDL_assert(waveformat != NULL); device->hidden->waveformat = waveformat; SDL_AudioSpec newspec; @@ -662,7 +662,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't get capture client service", ret); } - SDL_assert(capture); + SDL_assert(capture != NULL); device->hidden->capture = capture; ret = IAudioClient_Start(client); if (FAILED(ret)) { @@ -677,7 +677,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't get render client service", ret); } - SDL_assert(render); + SDL_assert(render != NULL); device->hidden->render = render; ret = IAudioClient_Start(client); if (FAILED(ret)) { diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 25af3225cd530..db8397c416675 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -164,11 +164,11 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device) IMMDevice_Release(immdevice); if (FAILED(ret)) { - SDL_assert(!device->hidden->client); + SDL_assert(device->hidden->client == NULL); return WIN_SetErrorFromHRESULT("WASAPI can't activate audio endpoint", ret); } - SDL_assert(device->hidden->client); + SDL_assert(device->hidden->client != NULL); if (WASAPI_PrepDevice(device) == -1) { // not async, fire it right away. return -1; } diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index 38f28602e9aa0..829c7d864a001 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -250,8 +250,8 @@ void SDL_EVDEV_Quit(void) SDL_EVDEV_kbd_quit(_this->kbd); - SDL_assert(!_this->first); - SDL_assert(!_this->last); + SDL_assert(_this->first == NULL); + SDL_assert(_this->last == NULL); SDL_assert(_this->num_devices == 0); SDL_free(_this); @@ -292,7 +292,7 @@ void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *relea void (*acquire_callback)(void*), void *acquire_callback_data) { SDL_EVDEV_kbd_set_vt_switch_callbacks(_this->kbd, - release_callback, release_callback_data, + release_callback, release_callback_data, acquire_callback, acquire_callback_data); } diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index e2d1266efe89f..629f4a181c02e 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -342,8 +342,8 @@ int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool i { const Uint64 timeout = SDL_GetTicks() + 8000; /* intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. */ - SDL_assert(device); - SDL_assert(immdevice); + SDL_assert(device != NULL); + SDL_assert(immdevice != NULL); LPCWSTR devid = SDL_IMMDevice_GetDevID(device); SDL_assert(devid != NULL); diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 6bb763e463367..c8ddf125034a2 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -787,7 +787,7 @@ int SDL_SetKeyboardFocus(SDL_Window *window) if (keyboard->focus && keyboard->focus != window) { /* new window shouldn't think it has mouse captured. */ - SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)); + SDL_assert(window == NULL || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)); /* old window must lose an existing mouse capture. */ if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) { diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index a70e297bd94cc..9a5f2575cf4d0 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -47,7 +47,7 @@ char *SDL_GetBasePath(void) rc = path.GetParent(&path); /* chop filename, keep directory. */ SDL_assert(rc == B_OK); const char *str = path.Path(); - SDL_assert(str); + SDL_assert(str != NULL); const size_t len = SDL_strlen(str); char *retval = (char *) SDL_malloc(len + 2); diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index d75dd5066b1fc..491f0f0d8d36f 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -89,7 +89,7 @@ static char *search_path_for_binary(const char *bin) return NULL; } - SDL_assert(bin); + SDL_assert(bin != NULL); alloc_size = SDL_strlen(bin) + SDL_strlen(envr) + 2; exe = (char *)SDL_malloc(alloc_size); diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index 65e7b39201c4a..b3d9b21eb42e8 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -59,7 +59,7 @@ static SDL_hapticlist_item *HapticByOrder(int index) return NULL; } while (index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); --index; item = item->next; } diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index 9d50ac643ab78..c0583640ab3d2 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -193,7 +193,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); --device_index; item = item->next; } diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index d1375c18069fe..00e60411b742b 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -188,7 +188,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); --device_index; item = item->next; } diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c index a203f3e28d341..771ba012bcd29 100644 --- a/src/haptic/windows/SDL_windowshaptic.c +++ b/src/haptic/windows/SDL_windowshaptic.c @@ -120,7 +120,7 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); --device_index; item = item->next; } diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 1e1003aea4822..bcc2a715cb74a 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -499,7 +499,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); device_index--; item = item->next; } diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index f764d16f63c56..4b52509c67e65 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -526,7 +526,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) } while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); device_index--; item = item->next; } diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 0430a7380cfc2..8a3dc2e164335 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -1001,7 +1001,7 @@ static SDL_joylist_item *GetJoystickByDevIndex(int device_index) item = SDL_joylist; while (device_index > 0) { - SDL_assert(item); + SDL_assert(item != NULL); device_index--; item = item->next; } @@ -1481,8 +1481,8 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) return -1; /* SDL_SetError will already have been called */ } - SDL_assert(!item->hwdata); - SDL_assert(!item_sensor || !item_sensor->hwdata); + SDL_assert(item->hwdata == NULL); + SDL_assert(!item_sensor || item_sensor->hwdata == NULL); item->hwdata = joystick->hwdata; if (item_sensor) { item_sensor->hwdata = joystick->hwdata; diff --git a/src/locale/windows/SDL_syslocale.c b/src/locale/windows/SDL_syslocale.c index 634e8370a98bc..977ed0461e4ff 100644 --- a/src/locale/windows/SDL_syslocale.c +++ b/src/locale/windows/SDL_syslocale.c @@ -61,7 +61,7 @@ static int SDL_SYS_GetPreferredLocales_vista(char *buf, size_t buflen) ULONG wbuflen = 0; SDL_bool isstack; - SDL_assert(pGetUserPreferredUILanguages); + SDL_assert(pGetUserPreferredUILanguages != NULL); pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numlangs, NULL, &wbuflen); wbuf = SDL_small_alloc(WCHAR, wbuflen, &isstack); diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 0498f0edf8b03..55904a38c6810 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -229,7 +229,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer) { int retval; - SDL_assert((!renderer->render_commands) == (!renderer->render_commands_tail)); + SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL)); if (!renderer->render_commands) { /* nothing to do! */ SDL_assert(renderer->vertex_data_used == 0); @@ -327,7 +327,7 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) } } - SDL_assert((!renderer->render_commands) == (!renderer->render_commands_tail)); + SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL)); if (renderer->render_commands_tail) { renderer->render_commands_tail->next = retval; } else { @@ -751,13 +751,13 @@ static SDL_INLINE void VerifyDrawQueueFunctions(const SDL_Renderer *renderer) { /* all of these functions are required to be implemented, even as no-ops, so we don't have to check that they aren't NULL over and over. */ - SDL_assert(renderer->QueueSetViewport); - SDL_assert(renderer->QueueSetDrawColor); - SDL_assert(renderer->QueueDrawPoints); - SDL_assert(renderer->QueueDrawLines || renderer->QueueGeometry); - SDL_assert(renderer->QueueFillRects || renderer->QueueGeometry); - SDL_assert(renderer->QueueCopy || renderer->QueueGeometry); - SDL_assert(renderer->RunCommandQueue); + SDL_assert(renderer->QueueSetViewport != NULL); + SDL_assert(renderer->QueueSetDrawColor != NULL); + SDL_assert(renderer->QueueDrawPoints != NULL); + SDL_assert(renderer->QueueDrawLines != NULL || renderer->QueueGeometry != NULL); + SDL_assert(renderer->QueueFillRects != NULL || renderer->QueueGeometry != NULL); + SDL_assert(renderer->QueueCopy != NULL || renderer->QueueGeometry != NULL); + SDL_assert(renderer->RunCommandQueue != NULL); } static SDL_RenderLineMethod SDL_GetRenderLineMethod(void) @@ -2304,7 +2304,7 @@ static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) static void SDL_RenderLogicalPresentation(SDL_Renderer *renderer) { - SDL_assert(!renderer->target); + SDL_assert(renderer->target == NULL); SDL_SetRenderViewport(renderer, NULL); SDL_SetRenderClipRect(renderer, NULL); SDL_SetRenderScale(renderer, 1.0f, 1.0f); diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 7870d10eb4ff1..4fd16b4e9ff18 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -928,7 +928,7 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, LPDIREC { D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - SDL_assert(!*shader); + SDL_assert(*shader == NULL); if (!texturedata) { return SDL_SetError("Texture is not currently available"); diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index e6516a43b445d..ed428d3fc4266 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -641,7 +641,7 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate) if (drawstate->surface_cliprect_dirty) { const SDL_Rect *viewport = drawstate->viewport; const SDL_Rect *cliprect = drawstate->cliprect; - SDL_assert_release(viewport); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */ + SDL_assert_release(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */ if (cliprect) { SDL_Rect clip_rect; diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index 2afcf6319ecff..2362ed7f7f380 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -200,7 +200,7 @@ SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *sha void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure) { - SDL_assert(tree); + SDL_assert(tree != NULL); if (tree->kind == QuadShape) { SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft, function, closure); SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright, function, closure); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 591e0277c7f71..a293b7dc4ffcc 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -271,7 +271,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U } } - SDL_assert(renderer); /* should have explicitly checked this above. */ + SDL_assert(renderer != NULL); /* should have explicitly checked this above. */ /* Create the data after we successfully create the renderer (bug #1116) */ data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data)); @@ -570,7 +570,7 @@ int SDL_VideoInit(const char *driver_name) return 0; pre_driver_error: - SDL_assert(!_this); + SDL_assert(_this == NULL); if (init_video_capture) { SDL_QuitVideoCapture(); } diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 02d30b25db57f..8c1bae80fce53 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -442,7 +442,7 @@ static int create_buffer_from_shm(Wayland_CursorData *d, return SDL_SetError("mmap() failed."); } - SDL_assert(d->shm_data); + SDL_assert(d->shm_data != NULL); shm_pool = wl_shm_create_pool(data->shm, shm_fd, size); d->buffer = wl_shm_pool_create_buffer(shm_pool, diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 88e274f8d17d9..41103805e4f41 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -689,7 +689,7 @@ int WIN_GL_SetupWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_bool WIN_GL_UseEGL(SDL_VideoDevice *_this) { - SDL_assert(_this->gl_data); + SDL_assert(_this->gl_data != NULL); SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES); return SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE) || _this->gl_config.major_version == 1 || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor); /* No WGL extension for OpenGL ES 1.x profiles. */ @@ -829,7 +829,7 @@ int WIN_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext } /* sanity check that higher level handled this. */ - SDL_assert(window || (!window && !context)); + SDL_assert(window || (window == NULL && !context)); /* Some Windows drivers freak out if hdc is NULL, even when context is NULL, against spec. Since hdc is _supposed_ to be ignored if context diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 59a0b969d8a1e..75acc17af7d3e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -821,7 +821,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) XClientMessageEvent m; int i; - SDL_assert(videodata); + SDL_assert(videodata != NULL); display = videodata->display; /* Save the original keycode for dead keys, which are filtered out by diff --git a/src/video/x11/SDL_x11xfixes.c b/src/video/x11/SDL_x11xfixes.c index 89952a1008d98..28ea7a6adb80a 100644 --- a/src/video/x11/SDL_x11xfixes.c +++ b/src/video/x11/SDL_x11xfixes.c @@ -120,7 +120,7 @@ int X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const X11_DestroyPointerBarrier(_this, data->active_cursor_confined_window); } - SDL_assert(window); + SDL_assert(window != NULL); wdata = window->driverdata; /* If user did not specify an area to confine, destroy the barrier that was/is assigned to diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index fa7a651be53c1..eb7f89a747dc9 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -190,7 +190,7 @@ static void xinput2_remove_device_info(SDL_VideoData *videodata, const int devic for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (!prev)); + SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); if (!prev) { videodata->mouse_device_info = devinfo->next; } else { @@ -214,7 +214,7 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (!prev)); + SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); if (prev) { /* move this to the front of the list, assuming we'll get more from this one. */ prev->next = devinfo->next; devinfo->next = videodata->mouse_device_info; diff --git a/test/testaudio.c b/test/testaudio.c index 924924187e5ae..0738b1884ee96 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -188,7 +188,7 @@ static Thing *CreateThing(ThingType what, float x, float y, float z, float w, fl } if ((w < 0) || (h < 0)) { - SDL_assert(texture); + SDL_assert(texture != NULL); if (w < 0) { w = texture->w; } diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index c75c85d93ecec..5567ece46bebd 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -353,21 +353,21 @@ static int surface_testCompleteSurfaceConversion(void *arg) for (i = 0; i < SDL_arraysize(pixel_formats); ++i) { for (j = 0; j < SDL_arraysize(pixel_formats); ++j) { fmt1 = SDL_CreatePixelFormat(pixel_formats[i]); - SDL_assert(fmt1); + SDL_assert(fmt1 != NULL); cvt1 = SDL_ConvertSurface(face, fmt1); - SDL_assert(cvt1); + SDL_assert(cvt1 != NULL); fmt2 = SDL_CreatePixelFormat(pixel_formats[j]); - SDL_assert(fmt1); + SDL_assert(fmt1 != NULL); cvt2 = SDL_ConvertSurface(cvt1, fmt2); - SDL_assert(cvt2); + SDL_assert(cvt2 != NULL); if (fmt1->BytesPerPixel == face->format->BytesPerPixel && fmt2->BytesPerPixel == face->format->BytesPerPixel && (fmt1->Amask != 0) == (face->format->Amask != 0) && (fmt2->Amask != 0) == (face->format->Amask != 0)) { final = SDL_ConvertSurface(cvt2, face->format); - SDL_assert(final); + SDL_assert(final != NULL); /* Compare surface. */ ret = SDLTest_CompareSurfaces(face, final, 0); From f66f61de01e1269cd25999a584885ec563f174e8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 11 Nov 2023 08:30:13 -0800 Subject: [PATCH 327/725] Fixed missing "0" in the button list --- test/gamepadutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/gamepadutils.c b/test/gamepadutils.c index 123224336a651..a404591a16e94 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -1710,7 +1710,7 @@ void RenderJoystickDisplay(JoystickDisplay *ctx, SDL_Joystick *joystick) highlight.h = (float)ctx->button_height; RenderJoystickButtonHighlight(ctx, i, &highlight); - SDL_snprintf(text, sizeof(text), "%2.d:", i); + SDL_snprintf(text, sizeof(text), "%2d:", i); SDLTest_DrawString(ctx->renderer, x, y, text); if (SDL_GetJoystickButton(joystick, (Uint8)i)) { From 843873626c88c8cc4a9d23e01beb6512f5978dee Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 11 Nov 2023 12:49:53 -0800 Subject: [PATCH 328/725] Handle window resizing on the render thread in D3D11 and D3D12 This prevents crashing when a separate thread is being used for rendering Discussion and sample code in https://github.com/libsdl-org/SDL/issues/8528 --- src/render/direct3d11/SDL_render_d3d11.c | 10 +++++++++- src/render/direct3d12/SDL_render_d3d12.c | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index c51803bf0dc6f..5b3b10e8fb015 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -138,6 +138,7 @@ typedef struct ID3D11SamplerState *nearestPixelSampler; ID3D11SamplerState *linearSampler; D3D_FEATURE_LEVEL featureLevel; + SDL_bool pixelSizeChanged; /* Rasterizers */ ID3D11RasterizerState *mainRasterizer; @@ -1036,8 +1037,10 @@ void D3D11_Trim(SDL_Renderer *renderer) static void D3D11_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) { + D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; + if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { - D3D11_UpdateForWindowSizeChange(renderer); + data->pixelSizeChanged = SDL_TRUE; } } @@ -2094,6 +2097,11 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer); + if (rendererData->pixelSizeChanged) { + D3D11_UpdateForWindowSizeChange(renderer); + rendererData->pixelSizeChanged = SDL_FALSE; + } + if (rendererData->currentViewportRotation != viewportRotation) { rendererData->currentViewportRotation = viewportRotation; rendererData->viewportDirty = SDL_TRUE; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 32196c51b6b64..bda1fbe0feeeb 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -174,6 +174,7 @@ typedef struct ID3D12GraphicsCommandList2 *commandList; DXGI_SWAP_EFFECT swapEffect; UINT swapFlags; + SDL_bool pixelSizeChanged; /* Descriptor heaps */ ID3D12DescriptorHeap *rtvDescriptorHeap; @@ -1386,8 +1387,10 @@ static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer) static void D3D12_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) { + D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata; + if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { - D3D12_UpdateForWindowSizeChange(renderer); + data->pixelSizeChanged = SDL_TRUE; } } @@ -2562,6 +2565,11 @@ static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; const int viewportRotation = D3D12_GetRotationForCurrentRenderTarget(renderer); + if (rendererData->pixelSizeChanged) { + D3D12_UpdateForWindowSizeChange(renderer); + rendererData->pixelSizeChanged = SDL_FALSE; + } + if (rendererData->currentViewportRotation != viewportRotation) { rendererData->currentViewportRotation = viewportRotation; rendererData->viewportDirty = SDL_TRUE; From 43571769f16b45ddcb9d7dd1d4c6e21cd39e691e Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Sun, 12 Nov 2023 15:55:10 +0000 Subject: [PATCH 329/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 42 ++------------- include/SDL3/SDL_video.h | 108 ++++++++++++++++---------------------- 2 files changed, 49 insertions(+), 101 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 120543dd436e9..d98170d615c15 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -309,13 +309,12 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: - * ``` - * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer + * The following properties are provided by SDL: "SDL.renderer.d3d9.device" - + * the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer - * ``` + * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with + * the renderer * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call @@ -420,39 +419,6 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * /** * Get the properties associated with a texture. * - * The following properties are provided by SDL: - * - * With the direct3d11 renderer: - * ``` - * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture - * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture - * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture - * ``` - * - * With the direct3d12 renderer: - * ``` - * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture - * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture - * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture - * ``` - * - * With the opengl renderer: - * ``` - * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture - * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture - * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture - * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture - * ``` - * - * With the opengles2 renderer: - * ``` - * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture - * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture - * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture - * ``` - * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index e0363eccdfaf7..8a466a68b4c94 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -936,71 +936,53 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following properties are provided by SDL: * - * On Android: - * ``` - * "SDL.window.android.window" - the ANativeWindow associated with the window - * "SDL.window.android.surface" - the EGLSurface associated with the window - * ``` - * - * On iOS: - * ``` - * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window - * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window - * ``` - * - * On KMS/DRM: - * ``` - * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) - * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window - * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window - * ``` - * - * On macOS: - * ``` - * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window - * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window - * ``` - * - * On Vivante: - * ``` - * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window - * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window - * "SDL.window.vivante.surface" - the EGLSurface associated with the window - * ``` - * - * On UWP: - * ``` - * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window - * ``` - * - * On Windows: - * ``` - * "SDL.window.win32.hwnd" - the HWND associated with the window + * On Android: "SDL.window.android.window" - the ANativeWindow associated with + * the window "SDL.window.android.surface" - the EGLSurface associated with + * the window + * + * On iOS: "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow + * associated with the window "SDL.window.uikit.metal_view_tag" - the + * NSInteger tag assocated with metal views on the window + * + * On KMS/DRM: "SDL.window.kmsdrm.dev_index" - the device index associated + * with the window (e.g. the X in /dev/dri/cardX) "SDL.window.kmsdrm.drm_fd" - + * the DRM FD associated with the window "SDL.window.kmsdrm.gbm_dev" - the GBM + * device associated with the window + * + * On macOS: "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow + * associated with the window "SDL.window.cocoa.metal_view_tag" - the + * NSInteger tag assocated with metal views on the window + * + * On Vivante: "SDL.window.vivante.display" - the EGLNativeDisplayType + * associated with the window "SDL.window.vivante.window" - the + * EGLNativeWindowType associated with the window "SDL.window.vivante.surface" + * - the EGLSurface associated with the window + * + * On UWP: "SDL.window.winrt.window" - the IInspectable CoreWindow associated + * with the window + * + * On Windows: "SDL.window.win32.hwnd" - the HWND associated with the window * "SDL.window.win32.hdc" - the HDC associated with the window * "SDL.window.win32.instance" - the HINSTANCE associated with the window - * ``` - * - * On Wayland: - * ``` - * "SDL.window.wayland.registry" - the wl_registry associated with the window - * "SDL.window.wayland.display" - the wl_display associated with the window - * "SDL.window.wayland.surface" - the wl_surface associated with the window - * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window - * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window - * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window - * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode - * ``` - * - * Note: The xdg_* window objects do not internally persist across window show/hide calls. - * They will be null if the window is hidden and must be queried each time it is shown. - * - * On X11: - * ``` - * "SDL.window.x11.display" - the X11 Display associated with the window - * "SDL.window.x11.screen" - the screen number associated with the window - * "SDL.window.x11.window" - the X11 Window associated with the window - * ``` + * + * On Wayland: "SDL.window.wayland.registry" - the wl_registry associated with + * the window "SDL.window.wayland.display" - the wl_display associated with + * the window "SDL.window.wayland.surface" - the wl_surface associated with + * the window "SDL.window.wayland.egl_window" - the wl_egl_window associated + * with the window "SDL.window.wayland.xdg_surface" - the xdg_surface + * associated with the window "SDL.window.wayland.xdg_toplevel" - the + * xdg_toplevel role associated with the window "SDL.window.wayland.xdg_popup" + * - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with + * the window, in popup mode + * + * Note: The xdg_* window objects do not internally persist across window + * show/hide calls. They will be null if the window is hidden and must be + * queried each time it is shown. + * + * On X11: "SDL.window.x11.display" - the X11 Display associated with the + * window "SDL.window.x11.screen" - the screen number associated with the + * window "SDL.window.x11.window" - the X11 Window associated with the window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call From d3e43668d0aca54abbb9cdc0eeccf5e51f669e91 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 09:02:22 -0800 Subject: [PATCH 330/725] Revert "Sync SDL3 wiki -> header" This reverts commit 43571769f16b45ddcb9d7dd1d4c6e21cd39e691e. --- include/SDL3/SDL_render.h | 42 +++++++++++++-- include/SDL3/SDL_video.h | 108 ++++++++++++++++++++++---------------- 2 files changed, 101 insertions(+), 49 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index d98170d615c15..120543dd436e9 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -309,12 +309,13 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: "SDL.renderer.d3d9.device" - - * the IDirect3DDevice9 associated with the renderer + * The following properties are provided by SDL: + * ``` + * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with - * the renderer + * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer + * ``` * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call @@ -419,6 +420,39 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * /** * Get the properties associated with a texture. * + * The following properties are provided by SDL: + * + * With the direct3d11 renderer: + * ``` + * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture + * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture + * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture + * ``` + * + * With the direct3d12 renderer: + * ``` + * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture + * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture + * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture + * ``` + * + * With the opengl renderer: + * ``` + * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture + * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture + * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture + * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture + * ``` + * + * With the opengles2 renderer: + * ``` + * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture + * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture + * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture + * ``` + * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 8a466a68b4c94..e0363eccdfaf7 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -936,53 +936,71 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following properties are provided by SDL: * - * On Android: "SDL.window.android.window" - the ANativeWindow associated with - * the window "SDL.window.android.surface" - the EGLSurface associated with - * the window - * - * On iOS: "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow - * associated with the window "SDL.window.uikit.metal_view_tag" - the - * NSInteger tag assocated with metal views on the window - * - * On KMS/DRM: "SDL.window.kmsdrm.dev_index" - the device index associated - * with the window (e.g. the X in /dev/dri/cardX) "SDL.window.kmsdrm.drm_fd" - - * the DRM FD associated with the window "SDL.window.kmsdrm.gbm_dev" - the GBM - * device associated with the window - * - * On macOS: "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow - * associated with the window "SDL.window.cocoa.metal_view_tag" - the - * NSInteger tag assocated with metal views on the window - * - * On Vivante: "SDL.window.vivante.display" - the EGLNativeDisplayType - * associated with the window "SDL.window.vivante.window" - the - * EGLNativeWindowType associated with the window "SDL.window.vivante.surface" - * - the EGLSurface associated with the window - * - * On UWP: "SDL.window.winrt.window" - the IInspectable CoreWindow associated - * with the window - * - * On Windows: "SDL.window.win32.hwnd" - the HWND associated with the window + * On Android: + * ``` + * "SDL.window.android.window" - the ANativeWindow associated with the window + * "SDL.window.android.surface" - the EGLSurface associated with the window + * ``` + * + * On iOS: + * ``` + * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window + * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * ``` + * + * On KMS/DRM: + * ``` + * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) + * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window + * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window + * ``` + * + * On macOS: + * ``` + * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window + * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * ``` + * + * On Vivante: + * ``` + * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window + * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window + * "SDL.window.vivante.surface" - the EGLSurface associated with the window + * ``` + * + * On UWP: + * ``` + * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window + * ``` + * + * On Windows: + * ``` + * "SDL.window.win32.hwnd" - the HWND associated with the window * "SDL.window.win32.hdc" - the HDC associated with the window * "SDL.window.win32.instance" - the HINSTANCE associated with the window - * - * On Wayland: "SDL.window.wayland.registry" - the wl_registry associated with - * the window "SDL.window.wayland.display" - the wl_display associated with - * the window "SDL.window.wayland.surface" - the wl_surface associated with - * the window "SDL.window.wayland.egl_window" - the wl_egl_window associated - * with the window "SDL.window.wayland.xdg_surface" - the xdg_surface - * associated with the window "SDL.window.wayland.xdg_toplevel" - the - * xdg_toplevel role associated with the window "SDL.window.wayland.xdg_popup" - * - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with - * the window, in popup mode - * - * Note: The xdg_* window objects do not internally persist across window - * show/hide calls. They will be null if the window is hidden and must be - * queried each time it is shown. - * - * On X11: "SDL.window.x11.display" - the X11 Display associated with the - * window "SDL.window.x11.screen" - the screen number associated with the - * window "SDL.window.x11.window" - the X11 Window associated with the window + * ``` + * + * On Wayland: + * ``` + * "SDL.window.wayland.registry" - the wl_registry associated with the window + * "SDL.window.wayland.display" - the wl_display associated with the window + * "SDL.window.wayland.surface" - the wl_surface associated with the window + * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window + * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window + * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window + * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode + * ``` + * + * Note: The xdg_* window objects do not internally persist across window show/hide calls. + * They will be null if the window is hidden and must be queried each time it is shown. + * + * On X11: + * ``` + * "SDL.window.x11.display" - the X11 Display associated with the window + * "SDL.window.x11.screen" - the screen number associated with the window + * "SDL.window.x11.window" - the X11 Window associated with the window + * ``` * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call From 7c80ac6df7001ba8ad37c6cf3ab0dc70b57011dd Mon Sep 17 00:00:00 2001 From: Christoph Reichenbach Date: Sun, 27 Aug 2023 06:20:29 +0000 Subject: [PATCH 331/725] API for pressure-sensitive pens + XInput2/Wayland This patch adds an API for querying pressure- sensitive pens, cf. SDL_pen.h: - Enumerate all pens - Get pen capabilities, names, GUIDs - Distinguishes pens and erasers - Distinguish attached and detached pens - Pressure and tilt support - Rotation, distance, throttle wheel support (throttle wheel untested) - Pen type and meta-information reporting (partially tested) Pen event reporting: - Three new event structures: PenTip, PenMotion, and PenButton - Report location with sub-pixel precision - Include axis and button status, is-eraser flag Internal pen tracker, intended to be independent of platform APIs, cf. SDL_pen_c.h: - Track known pens - Handle pen hotplugging Automatic test: - testautomation_pen.c Other features: - XInput2 implementation, incl. hotplugging - Wayland implementation, incl. hotplugging - Backward compatibility: pen events default to emulating pens with mouse ID SDL_PEN_MOUSEID - Can be toggled via SDL_HINT_PEN_NOT_MOUSE - Test/demo program (testpen) - Wacom pen feature identification by pen ID Acknowledgements: - Ping Cheng (Wacom) provided extensive feedback on Wacom pen features and detection so that hopefully untested Wacom devices have a realistic chance of working out of the box. --- VisualC-GDK/SDL/SDL.vcxproj | 2 + VisualC-GDK/SDL/SDL.vcxproj.filters | 6 + VisualC-WinRT/SDL-UWP.vcxproj | 2 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 6 + VisualC/SDL/SDL.vcxproj | 2 + VisualC/SDL/SDL.vcxproj.filters | 6 + .../testautomation/testautomation.vcxproj | 6 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 33 + include/SDL3/SDL_events.h | 76 +- include/SDL3/SDL_hints.h | 34 + include/SDL3/SDL_pen.h | 285 +++ src/dynapi/SDL_dynapi.sym | 16 + src/dynapi/SDL_dynapi_overrides.h | 16 + src/dynapi/SDL_dynapi_procs.h | 8 + src/dynapi/gendynapi.py | 2 +- src/events/SDL_events.c | 54 +- src/events/SDL_mouse.c | 24 +- src/events/SDL_mouse_c.h | 3 + src/events/SDL_pen.c | 1083 ++++++++++ src/events/SDL_pen_c.h | 336 +++ src/video/wayland/SDL_waylandevents.c | 463 +++- src/video/wayland/SDL_waylandevents_c.h | 38 +- src/video/x11/SDL_x11events.c | 185 +- src/video/x11/SDL_x11events.h | 4 + src/video/x11/SDL_x11pen.c | 694 ++++++ src/video/x11/SDL_x11pen.h | 54 + src/video/x11/SDL_x11sym.h | 1 + src/video/x11/SDL_x11video.c | 13 +- src/video/x11/SDL_x11window.c | 38 +- src/video/x11/SDL_x11xinput2.c | 180 +- src/video/x11/SDL_x11xinput2.h | 3 +- test/CMakeLists.txt | 1 + test/testautomation.c | 1 + test/testautomation_pen.c | 1908 +++++++++++++++++ test/testautomation_suites.h | 1 + test/testpen.c | 496 +++++ 36 files changed, 5841 insertions(+), 239 deletions(-) create mode 100644 include/SDL3/SDL_pen.h create mode 100644 src/events/SDL_pen.c create mode 100644 src/events/SDL_pen_c.h create mode 100644 src/video/x11/SDL_x11pen.c create mode 100644 src/video/x11/SDL_x11pen.h create mode 100644 test/testautomation_pen.c create mode 100644 test/testpen.c diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index a2c5aa6db2803..3d6451e2fbe6e 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -330,6 +330,7 @@ + @@ -586,6 +587,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index a5772a7453409..2396f04b6ee46 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -300,6 +300,9 @@ API Headers + + API Headers + API Headers @@ -940,6 +943,9 @@ events + + events + events diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index f7eca1ef796b6..2fad76fd31f82 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -67,6 +67,7 @@ + @@ -306,6 +307,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index fc905ac9e8528..747841ba1b484 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -105,6 +105,9 @@ Header Files + + Header Files + Header Files @@ -552,6 +555,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index fc53003e73fb7..0dee2d50069f1 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -280,6 +280,7 @@ + @@ -507,6 +508,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index c9d6f36e5d477..fbaadb802a5c5 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -294,6 +294,9 @@ API Headers + + API Headers + API Headers @@ -921,6 +924,9 @@ events + + events + events diff --git a/VisualC/tests/testautomation/testautomation.vcxproj b/VisualC/tests/testautomation/testautomation.vcxproj index 260617b4a8723..dbe1f3d8c2e1b 100644 --- a/VisualC/tests/testautomation/testautomation.vcxproj +++ b/VisualC/tests/testautomation/testautomation.vcxproj @@ -209,6 +209,12 @@ + + $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) + diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 32f2baf0f119a..66ead99a18f71 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -43,6 +43,27 @@ 00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; platformFilters = (macos, ); }; 557D0CFA254586CA003913E3 /* CoreHaptics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F37DC5F225350EBC0002E6F7 /* CoreHaptics.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); }; 557D0CFB254586D7003913E3 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A75FDABD23E28B6200529352 /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 63125C002A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; + 63125C012A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; + 63125C022A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; + 63125C0A2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C0B2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C0C2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C0D2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C0E2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C0F2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C102A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C112A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C122A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; + 63125C142A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C152A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C162A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C172A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C182A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C192A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C1A2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C1B2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; + 63125C1C2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; 5616CA4C252BB2A6005D5928 /* SDL_url.c in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA49252BB2A5005D5928 /* SDL_url.c */; }; 5616CA4D252BB2A6005D5928 /* SDL_sysurl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */; }; 5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA4B252BB2A6005D5928 /* SDL_sysurl.m */; }; @@ -52,6 +73,9 @@ 566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; }; 566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; }; 56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */; }; + 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A212A7902CF0021E9A6 /* SDL_pen.h */; }; + 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */; }; + 63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63134A242A7902FD0021E9A6 /* SDL_pen.c */; }; 75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = 75E09158241EA924004729E1 /* SDL_virtualjoystick.c */; }; 75E09163241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 75E09159241EA924004729E1 /* SDL_virtualjoystick_c.h */; }; 9846B07C287A9020000C35C8 /* SDL_hidapi_shield.c in Sources */ = {isa = PBXBuildFile; fileRef = 9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */; }; @@ -534,6 +558,9 @@ 566E26CD246274CB00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = ""; }; 566E26CE246274CC00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = ""; }; 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysrwlock.c; sourceTree = ""; }; + 63134A212A7902CF0021E9A6 /* SDL_pen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_pen.h; path = SDL3/SDL_pen.h; sourceTree = ""; }; + 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pen_c.h; sourceTree = ""; }; + 63134A242A7902FD0021E9A6 /* SDL_pen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_pen.c; sourceTree = ""; }; 75E09158241EA924004729E1 /* SDL_virtualjoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_virtualjoystick.c; sourceTree = ""; }; 75E09159241EA924004729E1 /* SDL_virtualjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_virtualjoystick_c.h; sourceTree = ""; }; 9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_shield.c; sourceTree = ""; }; @@ -1093,6 +1120,7 @@ F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */, F3F7D8B12933074900816151 /* SDL_opengles2_khrplatform.h */, F3F7D8C72933074B00816151 /* SDL_opengles2.h */, + 63134A212A7902CF0021E9A6 /* SDL_pen.h */, F3F7D8B52933074A00816151 /* SDL_pixels.h */, F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */, F3F7D8AB2933074900816151 /* SDL_platform.h */, @@ -2059,6 +2087,8 @@ A7D8A93823E2514000DCD162 /* SDL_keyboard.c */, A7D8A92B23E2514000DCD162 /* SDL_mouse_c.h */, A7D8A92A23E2514000DCD162 /* SDL_mouse.c */, + 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */, + 63134A242A7902FD0021E9A6 /* SDL_pen.c */, A7D8A93C23E2514000DCD162 /* SDL_quit.c */, A7D8A93723E2514000DCD162 /* SDL_touch_c.h */, A7D8A93E23E2514000DCD162 /* SDL_touch.c */, @@ -2365,6 +2395,8 @@ A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */, A7D8B3C823E2514200DCD162 /* yuv_rgb_sse_func.h in Headers */, A7D8B3CE23E2514300DCD162 /* yuv_rgb_std_func.h in Headers */, + 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */, + 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2685,6 +2717,7 @@ A7D8AEA023E2514100DCD162 /* SDL_cocoavulkan.m in Sources */, A7D8AB6123E2514100DCD162 /* SDL_offscreenwindow.c in Sources */, 566E26D8246274CC00718109 /* SDL_locale.c in Sources */, + 63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */, 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */, 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */, 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */, diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index dcc9ece04a722..186f9f40787a4 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,8 @@ typedef enum SDL_EVENT_WINDOW_RESTORED, /**< Window has been restored to normal size and position */ SDL_EVENT_WINDOW_MOUSE_ENTER, /**< Window has gained mouse focus */ SDL_EVENT_WINDOW_MOUSE_LEAVE, /**< Window has lost mouse focus */ + SDL_EVENT_WINDOW_PEN_ENTER, /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */ + SDL_EVENT_WINDOW_PEN_LEAVE, /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */ SDL_EVENT_WINDOW_FOCUS_GAINED, /**< Window has gained keyboard focus */ SDL_EVENT_WINDOW_FOCUS_LOST, /**< Window has lost keyboard focus */ SDL_EVENT_WINDOW_CLOSE_REQUESTED, /**< The window manager requests that the window be closed */ @@ -191,6 +194,13 @@ typedef enum /* Sensor events */ SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */ + /* Pressure-sensitive pen events */ + SDL_EVENT_PEN_DOWN = 0x1300, /**< Pressure-sensitive pen touched drawing surface */ + SDL_EVENT_PEN_UP, /**< Pressure-sensitive pen stopped touching drawing surface */ + SDL_EVENT_PEN_MOTION, /**< Pressure-sensitive pen moved, or angle/pressure changed */ + SDL_EVENT_PEN_BUTTON_DOWN, /**< Pressure-sensitive pen button pressed */ + SDL_EVENT_PEN_BUTTON_UP, /**< Pressure-sensitive pen button released */ + /* Render events */ SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */ SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */ @@ -296,7 +306,7 @@ typedef struct SDL_MouseMotionEvent Uint32 type; /**< ::SDL_EVENT_MOUSE_MOTION */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ - SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ Uint32 state; /**< The current button state */ float x; /**< X coordinate, relative to window */ float y; /**< Y coordinate, relative to window */ @@ -312,7 +322,7 @@ typedef struct SDL_MouseButtonEvent Uint32 type; /**< ::SDL_EVENT_MOUSE_BUTTON_DOWN or ::SDL_EVENT_MOUSE_BUTTON_UP */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ - SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ Uint8 button; /**< The mouse button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */ @@ -329,7 +339,7 @@ typedef struct SDL_MouseWheelEvent Uint32 type; /**< ::SDL_EVENT_MOUSE_WHEEL */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ - SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */ Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ @@ -512,6 +522,63 @@ typedef struct SDL_TouchFingerEvent #define SDL_DROPEVENT_DATA_SIZE 64 +/** + * Pressure-sensitive pen touched or stopped touching surface (event.ptip.*) + */ +typedef struct SDL_PenTipEvent +{ + Uint32 type; /**< ::SDL_EVENT_PEN_DOWN or ::SDL_EVENT_PEN_UP */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + Uint32 windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ + Uint8 tip; /**< ::SDL_PEN_TIP_INK when using a regular pen tip, or ::SDL_PEN_TIP_ERASER if the pen is being used as an eraser (e.g., flipped to use the eraser tip) */ + Uint8 state; /**< ::SDL_PRESSED on ::SDL_EVENT_PEN_DOWN and ::SDL_RELEASED on ::SDL_EVENT_PEN_UP */ + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), + ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and + ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ + float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ +} SDL_PenTipEvent; + +/** + * Pressure-sensitive pen motion / pressure / angle event structure (event.pmotion.*) + */ +typedef struct SDL_PenMotionEvent +{ + Uint32 type; /**< ::SDL_EVENT_PEN_MOTION */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + Uint32 windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ + Uint8 padding1; + Uint8 padding2; + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), + ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and + ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ + float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ +} SDL_PenMotionEvent; + +/** + * Pressure-sensitive pen button event structure (event.pbutton.*) + */ +typedef struct SDL_PenButtonEvent +{ + Uint32 type; /**< ::SDL_EVENT_PEN_BUTTON_DOWN or ::SDL_EVENT_PEN_BUTTON_UP */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + Uint32 windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ + Uint8 button; /**< The pen button index (1 represents the pen tip for compatibility with mouse events) */ + Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), + ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and + ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ + float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ +} SDL_PenButtonEvent; + /** * An event used to drop text or request a file open by the system (event.drop.*) * @@ -603,6 +670,9 @@ typedef union SDL_Event SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_PenTipEvent ptip; /**< Pen tip touching or leaving drawing surface */ + SDL_PenMotionEvent pmotion; /**< Pen change in position, pressure, or angle */ + SDL_PenButtonEvent pbutton; /**< Pen button press */ SDL_DropEvent drop; /**< Drag and drop event data */ SDL_ClipboardEvent clipboard; /**< Clipboard event data */ diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 0e4bf7565231d..91d7f0670ca5d 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1220,6 +1220,40 @@ extern "C" { */ #define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE" +/** + * Treat pen movement as separate from mouse movement + * + * By default, pens report both ::SDL_MouseMotionEvent and ::SDL_PenMotionEvent updates + * (analogously for button presses). This hint allows decoupling mouse and pen updates. + * + * This variable toggles between the following behaviour: + * "0" - (Default) Pen acts as a mouse with mouse ID ::SDL_PEN_MOUSEID. + * Use case: client application is not pen aware, user wants to + * use pen instead of mouse to interact. + * "1" - Pen reports mouse clicks and movement events but does not update + * SDL-internal mouse state (buttons pressed, current mouse location). + * Use case: client application is not pen aware, user frequently + * alternates between pen and "real" mouse. + * "2" - Pen reports no mouse events. + * Use case: pen-aware client application uses this hint to allow user to + * toggle between pen+mouse mode ("2") and pen-only mode ("1" or "0"). + */ +#define SDL_HINT_PEN_NOT_MOUSE "SDL_HINT_PEN_NOT_MOUSE" + +/** + * Pen mouse button emulation triggers only when the pen touches the tablet surface + * + * "0" - The pen reports mouse button press/release immediately when the pen + * button is pressed/released, and the pen tip touching the surface counts + * as left mouse button press. + * "1" - (Default) Mouse button presses are sent when the pen first touches + * the tablet (analogously for releases). Not pressing a pen button + * simulates mouse button 1, pressing the first pen button simulates + * mouse button 2 etc.; it is not possible to report multiple buttons + * as pressed at the same time. + */ +#define SDL_HINT_PEN_DELAY_MOUSE_BUTTON "SDL_HINT_PEN_DELAY_MOUSE_BUTTON" + /** * Tell SDL not to catch the SIGINT or SIGTERM signals. * diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h new file mode 100644 index 0000000000000..0f48da90abac4 --- /dev/null +++ b/include/SDL3/SDL_pen.h @@ -0,0 +1,285 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_pen.h + * + * Include file for SDL pen event handling. + * + * This file describes operations for pressure-sensitive pen (stylus and/or eraser) handling, e.g., for input + * and drawing tablets or suitably equipped mobile / tablet devices. + * + * To get started with pens: + * - Listen to ::SDL_PenMotionEvent and ::SDL_PenButtonEvent + * - To avoid treating pen events as mouse events, ignore ::SDL_MouseMotionEvent and ::SDL_MouseButtonEvent + * whenever "which" == ::SDL_PEN_MOUSEID. + * + * This header file describes advanced functionality that can be useful for managing user configuration + * and understanding the capabilities of the attached pens. + * + * We primarily identify pens by ::SDL_PenID. The implementation makes a best effort to relate each :SDL_PenID + * to the same physical device during a session. Formerly valid ::SDL_PenID values remain valid + * even if a device disappears. + * + * For identifying pens across sessions, the API provides the type ::SDL_GUID . + */ + +#ifndef SDL_pen_h_ +#define SDL_pen_h_ + +#include "SDL_error.h" +#include "SDL_guid.h" +#include "SDL_stdinc.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a session */ + +#define SDL_PEN_INVALID ((Uint32)0) /**< Reserved invalid ::SDL_PenID is valid */ + +#define SDL_PEN_MOUSEID ((Uint32)-2) /**< Device ID for mouse events triggered by pen events */ + +#define SDL_PEN_INFO_UNKNOWN (-1) /**< Marks unknown information when querying the pen */ + +/** + * Pen axis indices + * + * Below are the valid indices to the "axis" array from ::SDL_PenMotionEvent and ::SDL_PenButtonEvent. + * The axis indices form a contiguous range of ints from 0 to ::SDL_PEN_AXIS_LAST, inclusive. + * All "axis[]" entries are either normalised to 0..1 or report a (positive or negative) + * angle in degrees, with 0.0 representing the centre. + * Not all pens/backends support all axes: unsupported entries are always "0.0f". + * + * To convert angles for tilt and rotation into vector representation, use + * \link SDL_sinf \endlink on the XTILT, YTILT, or ROTATION component, e.g., "SDL_sinf(xtilt * SDL_PI_F / 180.0)". + */ +typedef enum +{ + SDL_PEN_AXIS_PRESSURE = 0, /**< Pen pressure. Unidirectional: 0..1.0 */ + SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0..90.0 (left-to-right). + The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */ + SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0..90.0 (top-to-down). + The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */ + SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0..1.0 */ + SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180..179.9 (clockwise, 0 is facing up, -180.0 is facing down). */ + SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0..1.0 */ + SDL_PEN_NUM_AXES, /**< Last valid axis index */ + SDL_PEN_AXIS_LAST = SDL_PEN_NUM_AXES - 1 /**< Last axis index plus 1 */ +} SDL_PenAxis; + +/* Pen flags. These share a bitmask space with ::SDL_BUTTON_LEFT and friends. */ +#define SDL_PEN_FLAG_DOWN_BIT_INDEX 13 /* Bit for storing that pen is touching the surface */ +#define SDL_PEN_FLAG_INK_BIT_INDEX 14 /* Bit for storing has-non-eraser-capability status */ +#define SDL_PEN_FLAG_ERASER_BIT_INDEX 15 /* Bit for storing is-eraser or has-eraser-capability property */ +#define SDL_PEN_FLAG_AXIS_BIT_OFFSET 16 /* Bit for storing has-axis-0 property */ + +#define SDL_PEN_CAPABILITY(capbit) (1ul << (capbit)) +#define SDL_PEN_AXIS_CAPABILITY(axis) SDL_PEN_CAPABILITY((axis) + SDL_PEN_FLAG_AXIS_BIT_OFFSET) + +/** + * Pen tips + * @{ + */ +#define SDL_PEN_TIP_INK SDL_PEN_FLAG_INK_BIT_INDEX /**< Regular pen tip (for drawing) touched the surface */ +#define SDL_PEN_TIP_ERASER SDL_PEN_FLAG_ERASER_BIT_INDEX /**< Eraser pen tip touched the surface */ +/** @} */ + + +/** + * \defgroup SDL_PEN_CAPABILITIES Pen capabilities + * Pen capabilities reported by ::SDL_GetPenCapabilities + * @{ + */ +#define SDL_PEN_DOWN_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_DOWN_BIT_INDEX) /**< Pen tip is currently touching the drawing surface. */ +#define SDL_PEN_INK_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_INK_BIT_INDEX) /**< Pen has a regular drawing tip (::SDL_GetPenCapabilities). For events (::SDL_PenButtonEvent, ::SDL_PenMotionEvent, ::SDL_GetPenStatus) this flag is mutually exclusive with ::SDL_PEN_ERASER_MASK . */ +#define SDL_PEN_ERASER_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_ERASER_BIT_INDEX) /**< Pen has an eraser tip (::SDL_GetPenCapabilities) or is being used as eraser (::SDL_PenButtonEvent , ::SDL_PenMotionEvent , ::SDL_GetPenStatus) */ +#define SDL_PEN_AXIS_PRESSURE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_PRESSURE) /**< Pen provides pressure information in axis ::SDL_PEN_AXIS_PRESSURE */ +#define SDL_PEN_AXIS_XTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_XTILT) /**< Pen provides horizontal tilt information in axis ::SDL_PEN_AXIS_XTILT */ +#define SDL_PEN_AXIS_YTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_YTILT) /**< Pen provides vertical tilt information in axis ::SDL_PEN_AXIS_YTILT */ +#define SDL_PEN_AXIS_DISTANCE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_DISTANCE) /**< Pen provides distance to drawing tablet in ::SDL_PEN_AXIS_DISTANCE */ +#define SDL_PEN_AXIS_ROTATION_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_ROTATION) /**< Pen provides barrel rotation information in axis ::SDL_PEN_AXIS_ROTATION */ +#define SDL_PEN_AXIS_SLIDER_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_SLIDER) /**< Pen provides slider / finger wheel or similar in axis ::SDL_PEN_AXIS_SLIDER */ + +#define SDL_PEN_AXIS_BIDIRECTIONAL_MASKS (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) +/**< Masks for all axes that may be bidirectional */ +/** @} */ + +/** + * Pen types + * + * Some pens identify as a particular type of drawing device (e.g., an airbrush or a pencil). + * + */ +typedef enum +{ + SDL_PEN_TYPE_ERASER = 1, /**< Eraser */ + SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */ + SDL_PEN_TYPE_PENCIL, /**< Pencil */ + SDL_PEN_TYPE_BRUSH, /**< Brush-like device */ + SDL_PEN_TYPE_AIRBRUSH, /**< Airbrush device that "sprays" ink */ + SDL_PEN_TYPE_LAST = SDL_PEN_TYPE_AIRBRUSH /**< Last valid pen type */ +} SDL_PenSubtype; + + +/* Function prototypes */ + +/** + * Retrieves all pens that are connected to the system. + * + * Yields an array of ::SDL_PenID values. These identify and track pens throughout a session. + * To track pens across sessions (program restart), use ::SDL_GUID . + * + * \param[out] count The number of pens in the array (number of array elements minus 1, i.e., not + * counting the terminator 0). + * + * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. + * The array must be freed with ::SDL_free(). + * On a NULL return, ::SDL_GetError() is set. + * + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); + +/** + * Retrieves the pen's current status. + * + * If the pen is detached (cf. ::SDL_PenConnected), this operation may return + * default values. + * + * \param instance_id The pen to query. + * \param[out] x Out-mode parameter for pen x coordinate. May be NULL. + * \param[out] y Out-mode parameter for pen y coordinate. May be NULL. + * \param[out] axes Out-mode parameter for axis information. May be null. The axes are in the same order as for + * ::SDL_PenAxis . + * \param num_axes Maximum number of axes to write to "axes". + * + * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK etc.), + * possibly ::SDL_PEN_DOWN_MASK, and exactly one of + * ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see ::SDL_GetError()). + * + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes); + +/** + * Retrieves an ::SDL_PenID for the given ::SDL_GUID. + * + * \param guid A pen GUID. + * + * \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching SDL_PenID. + * + * \since This function is available since SDL 3.TBD + * + * \sa SDL_GUID() + */ +extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); + +/** + * Retrieves the ::SDL_GUID for a given ::SDL_PenID. + * + * \param instance_id The pen to query. + * + * \returns The corresponding pen GUID; persistent across multiple sessions. + * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. + * + * \since This function is available since SDL 3.TBD + * + * \sa SDL_PenForID() + */ +extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id); + +/** + * Checks whether a pen is still attached. + * + * If a pen is detached, it will not show up for ::SDL_GetPens(). + * Other operations will still be available but may return default values. + * + * \param instance_id A pen ID. + * \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is attached, or + * SDL_FALSE otherwise. + * + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); + +/** + * Retrieves a human-readable description for a ::SDL_PenID. + * + * \param instance_id The pen to query. + * + * \returns A string that contains the name of the pen, intended for human consumption. + * The string might or might not be localised, depending on platform settings. + * It is not guaranteed to be unique; use ::SDL_GetPenGUID() for (best-effort) + * unique identifiers. + * The pointer is managed by the SDL pen subsystem and must not be deallocated. + * The pointer remains valid until SDL is shut down. + * Returns NULL on error (cf. ::SDL_GetError()) + * + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC const char *SDLCALL SDL_GetPenName(SDL_PenID instance_id); + +/** + * Pen capabilities, as reported by ::SDL_GetPenCapabilities() + */ +typedef struct SDL_PenCapabilityInfo +{ + float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or SDL_PEN_INFO_UNKNOWN . Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */ + Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */ + Sint8 num_buttons; /**< Number of pen buttons (not counting the pen tip), or SDL_PEN_INFO_UNKNOWN */ +} SDL_PenCapabilityInfo; + +/** + * Retrieves capability flags for a given ::SDL_PenID. + * + * \param instance_id The pen to query. + * \param[out] capabilities Detail information about pen capabilities, such as the number of buttons + * + * \returns a set of capability flags, cf. \link SDL_PEN_CAPABILITIES \endlink. Returns 0 on error + * (cf. ::SDL_GetError()) + * + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *capabilities); + +/** + * Retrieves the pen type for a given ::SDL_PenID. + * + * \param instance_id The pen to query. + * \returns The corresponding pen type (cf. ::SDL_PenSubtype) or 0 on error. Note that the pen type does not + * dictate whether the pen tip is ::SDL_PEN_TIP_INK or ::SDL_PEN_TIP_ERASER; to determine whether a pen + * is being used for drawing or in eraser mode, check either the pen tip on ::SDL_EVENT_PEN_DOWN, or the + * flag ::SDL_PEN_ERASER_MASK in the pen state. + * \since This function is available since SDL 3.TBD + */ +extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif + +#endif /* SDL_pen_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8d7f46526128b..972a6ee45dc5f 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -940,6 +940,22 @@ SDL3_0.0.0 { SDL_GetVideoCaptureDevices; SDL_GetGamepadButtonLabelForType; SDL_GetGamepadButtonLabel; + SDL_GetPens; + SDL_GetPenStatus; + SDL_GetPenFromGUID; + SDL_GetPenGUID; + SDL_PenConnected; + SDL_GetPenName; + SDL_GetPenCapabilities; + SDL_GetPenType; + SDL_GetPens; + SDL_GetPenStatus; + SDL_GetPenFromGUID; + SDL_GetPenGUID; + SDL_PenConnected; + SDL_GetPenName; + SDL_GetPenCapabilities; + SDL_GetPenType; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index e45318e2c9626..41a95138b035a 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -965,3 +965,19 @@ #define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL #define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL #define SDL_GetGamepadButtonLabel SDL_GetGamepadButtonLabel_REAL +#define SDL_GetPens SDL_GetPens_REAL +#define SDL_GetPenStatus SDL_GetPenStatus_REAL +#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL +#define SDL_GetPenGUID SDL_GetPenGUID_REAL +#define SDL_PenConnected SDL_PenConnected_REAL +#define SDL_GetPenName SDL_GetPenName_REAL +#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL +#define SDL_GetPenType SDL_GetPenType_REAL +#define SDL_GetPens SDL_GetPens_REAL +#define SDL_GetPenStatus SDL_GetPenStatus_REAL +#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL +#define SDL_GetPenGUID SDL_GetPenGUID_REAL +#define SDL_PenConnected SDL_PenConnected_REAL +#define SDL_GetPenName SDL_GetPenName_REAL +#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL +#define SDL_GetPenType SDL_GetPenType_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index fb8f1c457817d..07f1bd1e2d887 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -998,3 +998,11 @@ SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),) SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabelForType,(SDL_GamepadType a, SDL_GamepadButton b),(a,b),return) SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) +SDL_DYNAPI_PROC(SDL_PenID*,SDL_GetPens,(int *a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_GetPenStatus,(SDL_PenID a, float *b, float *c, float *d, size_t e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_PenID,SDL_GetPenFromGUID,(SDL_GUID a),(a),return) +SDL_DYNAPI_PROC(SDL_GUID,SDL_GetPenGUID,(SDL_PenID a),(a),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return) diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index b91f2ee7f2cac..e08ce2cc60308 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -379,7 +379,7 @@ def check_comment(): if header != 'SDL_stdinc.h': parameter_name = i['parameter_name'] for n in parameter_name: - if n != "" and "\\param " + n not in comment: + if n != "" and "\\param " + n not in comment and "\\param[out] " + n not in comment: check_comment_header() print(" In file %s: function %s() missing '\\param %s'" % (header, name, n)); diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index f79f46970e3e2..5879629ba0189 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -192,7 +192,7 @@ static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, co * Verbosity of logged events as defined in SDL_HINT_EVENT_LOGGING: * - 0: (default) no logging * - 1: logging of most events - * - 2: as above, plus mouse and finger motion + * - 2: as above, plus mouse, pen, and finger motion */ static int SDL_EventLoggingVerbosity = 0; @@ -206,10 +206,11 @@ static void SDL_LogEvent(const SDL_Event *event) char name[64]; char details[128]; - /* sensor/mouse/finger motion are spammy, ignore these if they aren't demanded. */ + /* sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. */ if ((SDL_EventLoggingVerbosity < 2) && ((event->type == SDL_EVENT_MOUSE_MOTION) || (event->type == SDL_EVENT_FINGER_MOTION) || + (event->type == SDL_EVENT_PEN_MOTION) || (event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) || (event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) || (event->type == SDL_EVENT_SENSOR_UPDATE))) { @@ -302,6 +303,8 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_ENTER); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_LEAVE); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED); @@ -470,6 +473,53 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_FINGER_EVENT +#define PRINT_PTIP_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g)", \ + (uint)event->ptip.timestamp, (uint)event->ptip.windowID, \ + (uint)event->ptip.which, (uint)event->ptip.tip, \ + event->ptip.state == SDL_PRESSED ? "down" : "up", \ + event->ptip.x, event->ptip.y) + SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN) + PRINT_PTIP_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_PEN_UP) + PRINT_PTIP_EVENT(event); + break; +#undef PRINT_PTIP_EVENT + + SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%08x x=%g y=%g [%g, %g, %g, %g, %g, %g])", + (uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, + (uint)event->pmotion.which, (uint)event->pmotion.pen_state, + event->pmotion.x, event->pmotion.y, + event->pmotion.axes[SDL_PEN_AXIS_PRESSURE], + event->pmotion.axes[SDL_PEN_AXIS_XTILT], + event->pmotion.axes[SDL_PEN_AXIS_YTILT], + event->pmotion.axes[SDL_PEN_AXIS_DISTANCE], + event->pmotion.axes[SDL_PEN_AXIS_ROTATION], + event->pmotion.axes[SDL_PEN_AXIS_SLIDER]); + break; + +#define PRINT_PBUTTON_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g axes=[%g, %g, %g, %g, %g, %g])", \ + (uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, \ + (uint)event->pbutton.which, (uint)event->pbutton.button, \ + event->pbutton.state == SDL_PRESSED ? "pressed" : "released", \ + event->pbutton.x, event->pbutton.y, \ + event->pbutton.axes[SDL_PEN_AXIS_PRESSURE], \ + event->pbutton.axes[SDL_PEN_AXIS_XTILT], \ + event->pbutton.axes[SDL_PEN_AXIS_YTILT], \ + event->pbutton.axes[SDL_PEN_AXIS_DISTANCE], \ + event->pbutton.axes[SDL_PEN_AXIS_ROTATION], \ + event->pbutton.axes[SDL_PEN_AXIS_SLIDER]) + SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN) + PRINT_PBUTTON_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_UP) + PRINT_PBUTTON_EVENT(event); + break; +#undef PRINT_PBUTTON_EVENT + #define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y) SDL_EVENT_CASE(SDL_EVENT_DROP_FILE) PRINT_DROP_EVENT(event); diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index cd4e6a71952e1..6487ca181847c 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -22,9 +22,11 @@ /* General mouse handling code for SDL */ -#include "SDL_events_c.h" #include "../SDL_hints_c.h" #include "../video/SDL_sysvideo.h" +#include "SDL_events_c.h" +#include "SDL_mouse_c.h" +#include "SDL_pen_c.h" #if defined(__WIN32__) || defined(__GDK__) #include "../core/windows/SDL_windows.h" // For GetDoubleClickTime() #endif @@ -221,6 +223,8 @@ void SDL_PostInitMouse(void) SDL_DestroySurface(surface); } } + + SDL_PenInit(); } void SDL_SetDefaultCursor(SDL_Cursor *cursor) @@ -351,17 +355,25 @@ void SDL_SetMouseFocus(SDL_Window *window) SDL_SetCursor(NULL); } -/* Check to see if we need to synthesize focus events */ -static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion) +SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y) { - SDL_Mouse *mouse = SDL_GetMouse(); - SDL_bool inWindow = SDL_TRUE; + if (!window) { + return SDL_FALSE; + } if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) { if (x < 0.0f || y < 0.0f || x >= (float)window->w || y >= (float)window->h) { - inWindow = SDL_FALSE; + return SDL_FALSE; } } + return SDL_TRUE; +} + +/* Check to see if we need to synthesize focus events */ +static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_bool inWindow = SDL_MousePositionInWindow(window, mouse->mouseID, x, y); if (!inWindow) { if (window == mouse->focus) { diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 0887b5626b133..cd08f1640b0ed 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -163,6 +163,9 @@ extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, S extern void SDL_ResetMouse(void); #endif /* 0 */ +/* Check if mouse position is within window or captured by window */ +extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y); + /* Shutdown the mouse subsystem */ extern void SDL_QuitMouse(void); diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c new file mode 100644 index 0000000000000..78e6b617c0c72 --- /dev/null +++ b/src/events/SDL_pen.c @@ -0,0 +1,1083 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +/* Pressure-sensitive pen handling code for SDL */ + +#include "../SDL_hints_c.h" +#include "SDL_events_c.h" +#include "SDL_pen_c.h" + +#define PEN_MOUSE_EMULATE 0 /* pen behaves like mouse */ +#define PEN_MOUSE_STATELESS 1 /* pen does not update mouse state */ +#define PEN_MOUSE_DISABLED 2 /* pen does not send mouse events */ + +/* flags that are not SDL_PEN_FLAG_ */ +#define PEN_FLAGS_CAPABILITIES (~(SDL_PEN_FLAG_NEW | SDL_PEN_FLAG_DETACHED | SDL_PEN_FLAG_STALE)) + +#define PEN_GET_PUBLIC_STATUS_MASK(pen) (((pen)->header.flags & (SDL_PEN_ERASER_MASK | SDL_PEN_DOWN_MASK))) + +static int pen_mouse_emulation_mode = PEN_MOUSE_EMULATE; /* SDL_HINT_PEN_NOT_MOUSE */ + +static int pen_delay_mouse_button_mode = 1; /* SDL_HINT_PEN_DELAY_MOUSE_BUTTON */ + +#ifndef SDL_THREADS_DISABLED +static SDL_Mutex *SDL_pen_access_lock; +# define SDL_LOCK_PENS() SDL_LockMutex(SDL_pen_access_lock) +# define SDL_UNLOCK_PENS() SDL_UnlockMutex(SDL_pen_access_lock) +#else +# define SDL_LOCK_PENS() +# define SDL_UNLOCK_PENS() +#endif + +static struct +{ + SDL_Pen *pens; /* if "sorted" is SDL_TRUE: + sorted by: (is-attached, id): + - first all attached pens, in ascending ID order + - then all detached pens, in ascending ID order */ + size_t pens_allocated; /* # entries allocated to "pens" */ + size_t pens_known; /* <= pens_allocated; this includes detached pens */ + size_t pens_attached; /* <= pens_known; all attached pens are at the beginning of "pens" */ + SDL_bool sorted; /* This is SDL_FALSE in the period between SDL_PenGCMark() and SDL_PenGCSWeep() */ +} pen_handler; + +static SDL_PenID pen_invalid = { SDL_PEN_INVALID }; + +static SDL_GUID pen_guid_zero = { { 0 } }; + +#define SDL_LOAD_LOCK_PEN(penvar, instance_id, err_return) \ + SDL_Pen *penvar; \ + if (instance_id == SDL_PEN_INVALID) { \ + SDL_SetError("Invalid SDL_PenID"); \ + return (err_return); \ + } \ + SDL_LOCK_PENS();\ + penvar = SDL_GetPenPtr(instance_id); \ + if (!(penvar)) { \ + SDL_SetError("Stale SDL_PenID"); \ + return (err_return); \ + } + +static int SDL_GUIDCompare(SDL_GUID lhs, SDL_GUID rhs) +{ + return SDL_memcmp(lhs.data, rhs.data, sizeof(lhs.data)); +} + +static int SDLCALL pen_compare(const void *lhs, const void *rhs) +{ + int left_inactive = (((const SDL_Pen *)lhs)->header.flags & SDL_PEN_FLAG_DETACHED); + int right_inactive = (((const SDL_Pen *)rhs)->header.flags & SDL_PEN_FLAG_DETACHED); + if (left_inactive && !right_inactive) { + return 1; + } + if (!left_inactive && right_inactive) { + return -1; + } + return ((const SDL_Pen *)lhs)->header.id - ((const SDL_Pen *)rhs)->header.id; +} + +static int SDLCALL pen_header_compare(const void *lhs, const void *rhs) +{ + const struct SDL_Pen_header *l = lhs; + const struct SDL_Pen_header *r = rhs; + int l_detached = l->flags & SDL_PEN_FLAG_DETACHED; + int r_detached = r->flags & SDL_PEN_FLAG_DETACHED; + + if (l_detached != r_detached) { + if (l_detached) { + return -1; + } + return 1; + } + + return l->id - r->id; +} + +SDL_Pen *SDL_GetPenPtr(const Uint32 instance_id) +{ + unsigned int i; + + if (!pen_handler.pens) { + return NULL; + } + + if (pen_handler.sorted) { + struct SDL_Pen_header key = { 0, 0 }; + SDL_Pen *pen; + + key.id = instance_id; + + pen = SDL_bsearch(&key, pen_handler.pens, + pen_handler.pens_known, sizeof(SDL_Pen), + pen_header_compare); + if (pen) { + return pen; + } + /* If the pen is not active, fall through */ + } + + /* fall back to linear search */ + for (i = 0; i < pen_handler.pens_known; ++i) { + if (pen_handler.pens[i].header.id == instance_id) { + return &pen_handler.pens[i]; + } + } + return NULL; +} + +SDL_PenID *SDL_GetPens(int *count) +{ + int i; + int pens_nr = (int)pen_handler.pens_attached; + SDL_PenID *pens = SDL_calloc(pens_nr + 1, sizeof(SDL_PenID)); + if (!pens) { /* OOM */ + return pens; + } + + for (i = 0; i < pens_nr; ++i) { + pens[i] = pen_handler.pens[i].header.id; + } + + if (count) { + *count = pens_nr; + } + return pens; +} + +SDL_PenID SDL_GetPenFromGUID(SDL_GUID guid) +{ + unsigned int i; + /* Must do linear search */ + SDL_LOCK_PENS(); + for (i = 0; i < pen_handler.pens_known; ++i) { + SDL_Pen *pen = &pen_handler.pens[i]; + + if (0 == SDL_GUIDCompare(guid, pen->guid)) { + SDL_UNLOCK_PENS(); + return pen->header.id; + } + } + SDL_UNLOCK_PENS(); + return pen_invalid; +} + +SDL_bool SDL_PenConnected(SDL_PenID instance_id) +{ + SDL_Pen *pen; + SDL_bool result; + + if (instance_id == SDL_PEN_INVALID) { + return SDL_FALSE; + } + + SDL_LOCK_PENS(); + pen = SDL_GetPenPtr(instance_id); + if (!pen) { + SDL_UNLOCK_PENS(); + return SDL_FALSE; + } + result = (pen->header.flags & SDL_PEN_FLAG_DETACHED) ? SDL_FALSE : SDL_TRUE; + SDL_UNLOCK_PENS(); + return result; +} + +SDL_GUID SDL_GetPenGUID(SDL_PenID instance_id) +{ + SDL_GUID result; + SDL_LOAD_LOCK_PEN(pen, instance_id, pen_guid_zero); + result = pen->guid; + SDL_UNLOCK_PENS(); + return result; +} + +const char *SDL_GetPenName(SDL_PenID instance_id) +{ + const char *result; + SDL_LOAD_LOCK_PEN(pen, instance_id, NULL); + result = pen->name; /* Allocated separately from the pen table, so it is safe to hand to client code */ + SDL_UNLOCK_PENS(); + return result; +} + +SDL_PenSubtype SDL_GetPenType(SDL_PenID instance_id) +{ + SDL_PenSubtype result; + SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); + result = pen->type; + SDL_UNLOCK_PENS(); + return result; +} + +Uint32 SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *info) +{ + Uint32 result; + SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); + if (info) { + *info = pen->info; + } + result = pen->header.flags & PEN_FLAGS_CAPABILITIES; + SDL_UNLOCK_PENS(); + return result; +} + +Uint32 SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes) +{ + Uint32 result; + SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); + + if (x) { + *x = pen->last.x; + } + if (y) { + *y = pen->last.y; + } + if (axes && num_axes) { + size_t axes_to_copy = SDL_min(num_axes, SDL_PEN_NUM_AXES); + SDL_memcpy(axes, pen->last.axes, sizeof(float) * axes_to_copy); + } + result = pen->last.buttons | (pen->header.flags & (SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_DOWN_MASK)); + SDL_UNLOCK_PENS(); + return result; +} + +/* Backend functionality */ + +/* Sort all pens. Only safe during SDL_LOCK_PENS. */ +static void pen_sort(void) +{ + SDL_qsort(pen_handler.pens, + pen_handler.pens_known, + sizeof(SDL_Pen), + pen_compare); + pen_handler.sorted = SDL_TRUE; +} + +SDL_Pen *SDL_PenModifyBegin(const Uint32 instance_id) +{ + SDL_PenID id = { 0 }; + const size_t alloc_growth_constant = 1; /* Expect few pens */ + SDL_Pen *pen; + + id = instance_id; + + if (id == SDL_PEN_INVALID) { + SDL_SetError("Invalid SDL_PenID"); + return NULL; + } + + SDL_LOCK_PENS(); + pen = SDL_GetPenPtr(id); + + if (!pen) { + if (!pen_handler.pens || pen_handler.pens_known == pen_handler.pens_allocated) { + size_t pens_to_allocate = pen_handler.pens_allocated + alloc_growth_constant; + SDL_Pen *pens; + if (pen_handler.pens) { + pens = SDL_realloc(pen_handler.pens, sizeof(SDL_Pen) * pens_to_allocate); + SDL_memset(pens + pen_handler.pens_known, 0, + sizeof(SDL_Pen) * (pens_to_allocate - pen_handler.pens_allocated)); + } else { + pens = SDL_calloc(sizeof(SDL_Pen), pens_to_allocate); + } + pen_handler.pens = pens; + pen_handler.pens_allocated = pens_to_allocate; + } + pen = &pen_handler.pens[pen_handler.pens_known]; + pen_handler.pens_known += 1; + + /* Default pen initialisation */ + pen->header.id = id; + pen->header.flags = SDL_PEN_FLAG_NEW; + pen->info.num_buttons = SDL_PEN_INFO_UNKNOWN; + pen->info.max_tilt = SDL_PEN_INFO_UNKNOWN; + pen->type = SDL_PEN_TYPE_PEN; + pen->name = SDL_calloc(1, SDL_PEN_MAX_NAME); /* Never deallocated */ + } + return pen; +} + +void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities) +{ + if (capabilities & SDL_PEN_ERASER_MASK) { + pen->header.flags &= ~SDL_PEN_INK_MASK; + } else if (capabilities & SDL_PEN_INK_MASK) { + pen->header.flags &= ~SDL_PEN_ERASER_MASK; + } + pen->header.flags |= (capabilities & PEN_FLAGS_CAPABILITIES); +} + +static void pen_hotplug_attach(SDL_Pen *pen) +{ + if (!pen->header.window) { + /* Attach to default window */ + const SDL_Mouse *mouse = SDL_GetMouse(); + SDL_SendPenWindowEvent(0, pen->header.id, mouse->focus); + } +} + +static void pen_hotplug_detach(SDL_Pen *pen) +{ + SDL_SendPenWindowEvent(0, pen->header.id, NULL); +} + +void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach) +{ + SDL_bool is_new = pen->header.flags & SDL_PEN_FLAG_NEW; + SDL_bool was_attached = !(pen->header.flags & (SDL_PEN_FLAG_DETACHED | SDL_PEN_FLAG_NEW)); + SDL_bool broke_sort_order = SDL_FALSE; + + if (pen->type == SDL_PEN_TYPE_NONE) { + /* remove pen */ + if (!is_new) { + if (!(pen->header.flags & SDL_PEN_FLAG_ERROR)) { + SDL_Log("Error: attempt to remove known pen %lu", (unsigned long) pen->header.id); + pen->header.flags |= SDL_PEN_FLAG_ERROR; + } + + /* Treat as detached pen of unknown type instead */ + pen->type = SDL_PEN_TYPE_PEN; + attach = SDL_FALSE; + } else { + pen_handler.pens_known -= 1; + SDL_memset(pen, 0, sizeof(SDL_Pen)); + SDL_UNLOCK_PENS(); + return; + } + } + + pen->header.flags &= ~(SDL_PEN_FLAG_NEW | SDL_PEN_FLAG_STALE | SDL_PEN_FLAG_DETACHED); + if (attach == SDL_FALSE) { + pen->header.flags |= SDL_PEN_FLAG_DETACHED; + if (was_attached) { + broke_sort_order = SDL_TRUE; + if (!is_new) { + pen_handler.pens_attached -= 1; + } + pen_hotplug_detach(pen); + } + } else if (!was_attached || is_new) { + broke_sort_order = SDL_TRUE; + pen_handler.pens_attached += 1; + pen_hotplug_attach(pen); + } + + if (is_new) { + /* default: name */ + if (!pen->name[0]) { + SDL_snprintf(pen->name, SDL_PEN_MAX_NAME, + "%s %lu", + pen->type == SDL_PEN_TYPE_ERASER ? "Eraser" : "Pen", + (unsigned long) pen->header.id); + } + + /* default: enabled axes */ + if (!(pen->header.flags & (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK))) { + pen->info.max_tilt = 0; /* no tilt => no max_tilt */ + } + + /* sanity-check GUID */ + if (0 == SDL_GUIDCompare(pen->guid, pen_guid_zero)) { + SDL_Log("Error: pen %lu: has GUID 0", (unsigned long) pen->header.id); + } + + /* pen or eraser? */ + if (pen->type == SDL_PEN_TYPE_ERASER || pen->header.flags & SDL_PEN_ERASER_MASK) { + pen->header.flags = (pen->header.flags & ~SDL_PEN_INK_MASK) | SDL_PEN_ERASER_MASK; + pen->type = SDL_PEN_TYPE_ERASER; + } else { + pen->header.flags = (pen->header.flags & ~SDL_PEN_ERASER_MASK) | SDL_PEN_INK_MASK; + } + + broke_sort_order = SDL_TRUE; + } + if (broke_sort_order && pen_handler.sorted) { + /* Maintain sortedness invariant */ + pen_sort(); + } + SDL_UNLOCK_PENS(); +} + +void SDL_PenGCMark(void) +{ + unsigned int i; + SDL_LOCK_PENS(); + for (i = 0; i < pen_handler.pens_known; ++i) { + SDL_Pen *pen = &pen_handler.pens[i]; + pen->header.flags |= SDL_PEN_FLAG_STALE; + } + pen_handler.sorted = SDL_FALSE; + SDL_UNLOCK_PENS(); +} + +void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32, void *, void *)) +{ + unsigned int i; + pen_handler.pens_attached = 0; + + SDL_LOCK_PENS(); + /* We don't actually free the SDL_Pen entries, so that we can still answer queries about + formerly active SDL_PenIDs later. */ + for (i = 0; i < pen_handler.pens_known; ++i) { + SDL_Pen *pen = &pen_handler.pens[i]; + + if (pen->header.flags & SDL_PEN_FLAG_STALE) { + pen->header.flags |= SDL_PEN_FLAG_DETACHED; + pen_hotplug_detach(pen); + if (pen->deviceinfo) { + free_deviceinfo(pen->header.id, pen->deviceinfo, context); + pen->deviceinfo = NULL; + } + } else { + pen_handler.pens_attached += 1; + } + + pen->header.flags &= ~SDL_PEN_FLAG_STALE; + } + pen_sort(); + /* We could test for changes in the above and send a hotplugging event here */ + SDL_UNLOCK_PENS(); +} + +static void pen_relative_coordinates(SDL_Window *window, SDL_bool window_relative, float *x, float *y) +{ + int win_x, win_y; + + if (window_relative) { + return; + } + SDL_GetWindowPosition(window, &win_x, &win_y); + *x -= win_x; + *y -= win_y; +} + +/* Initialises timestamp, windowID, which, pen_state, x, y, and axes */ +static void event_setup(const SDL_Pen *pen, const SDL_Window *window, Uint64 timestamp, const SDL_PenStatusInfo *status, SDL_Event *event) +{ + Uint16 last_buttons = pen->last.buttons; + + if (timestamp == 0) { + /* Generate timestamp ourselves, if needed, so that we report the same timestamp + for the pen event and for any emulated mouse event */ + timestamp = SDL_GetTicksNS(); + } + + /* This code assumes that all of the SDL_Pen*Event structures have the same layout for these fields. + * This is checked by testautomation_pen.c, pen_memoryLayout(). */ + event->pmotion.timestamp = timestamp; + event->pmotion.windowID = window ? window->id : 0; + event->pmotion.which = pen->header.id; + event->pmotion.pen_state = (Uint16)last_buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); + event->pmotion.x = status->x; + event->pmotion.y = status->y; + SDL_memcpy(event->pmotion.axes, status->axes, SDL_PEN_NUM_AXES * sizeof(float)); +} + + +int SDL_SendPenMotion(Uint64 timestamp, + SDL_PenID instance_id, + SDL_bool window_relative, + const SDL_PenStatusInfo *status) +{ + const SDL_Mouse *mouse = SDL_GetMouse(); + int i; + SDL_Pen *pen = SDL_GetPenPtr(instance_id); + SDL_Event event; + SDL_bool posted = SDL_FALSE; + float x = status->x; + float y = status->y; + float last_x = pen->last.x; + float last_y = pen->last.y; + /* Suppress mouse updates for axis changes or sub-pixel movement: */ + SDL_bool send_mouse_update; + SDL_bool axes_changed = SDL_FALSE; + SDL_Window *window; + + if (!pen) { + return SDL_FALSE; + } + window = pen->header.window; + if (!window) { + return SDL_FALSE; + } + + pen_relative_coordinates(window, window_relative, &x, &y); + + /* Check if the event actually modifies any cached axis or location, update as neeed */ + if (x != last_x || y != last_y) { + axes_changed = SDL_TRUE; + pen->last.x = status->x; + pen->last.y = status->y; + } + for (i = 0; i < SDL_PEN_NUM_AXES; ++i) { + if ((pen->header.flags & SDL_PEN_AXIS_CAPABILITY(i)) && (status->axes[i] != pen->last.axes[i])) { + axes_changed = SDL_TRUE; + pen->last.axes[i] = status->axes[i]; + } + } + if (!axes_changed) { + /* No-op event */ + return SDL_FALSE; + } + + send_mouse_update = (x != last_x) || (y != last_y); + + if (!(SDL_MousePositionInWindow(window, mouse->mouseID, x, y))) { + return SDL_FALSE; + } + + if (SDL_EventEnabled(SDL_EVENT_PEN_MOTION)) { + event_setup(pen, window, timestamp, status, &event); + event.pmotion.type = SDL_EVENT_PEN_MOTION; + + posted = SDL_PushEvent(&event) > 0; + + if (!posted) { + return SDL_FALSE; + } + } + + if (send_mouse_update) { + switch (pen_mouse_emulation_mode) { + case PEN_MOUSE_EMULATE: + return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, 0, x, y)) || posted; + + case PEN_MOUSE_STATELESS: + /* Report mouse event but don't update mouse state */ + if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) { + event.motion.windowID = event.pmotion.windowID; + event.motion.timestamp = timestamp; + event.motion.which = SDL_PEN_MOUSEID; + event.motion.type = SDL_EVENT_MOUSE_MOTION; + event.motion.state = pen->last.buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); + event.motion.x = x; + event.motion.y = y; + event.motion.xrel = last_x - x; + event.motion.yrel = last_y - y; + return (SDL_PushEvent(&event) > 0) || posted; + } + + default: + break; + } + } + return posted; +} + +int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Pen *pen = SDL_GetPenPtr(instance_id); + SDL_Event event; + SDL_bool posted = SDL_FALSE; + SDL_PenStatusInfo *last = &pen->last; + int mouse_button = SDL_BUTTON_LEFT; + SDL_Window *window; + + if (!pen) { + return SDL_FALSE; + } + window = pen->header.window; + + if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) { + return SDL_FALSE; + } + + if (state == SDL_PRESSED) { + event.pbutton.type = SDL_EVENT_PEN_DOWN; + pen->header.flags |= SDL_PEN_DOWN_MASK; + } else { + event.pbutton.type = SDL_EVENT_PEN_UP; + pen->header.flags &= ~SDL_PEN_DOWN_MASK; + } + + if (SDL_EventEnabled(event.ptip.type)) { + event_setup(pen, window, timestamp, &pen->last, &event); + + /* Used as eraser? Report eraser event, otherwise ink event */ + event.ptip.tip = (pen->header.flags & SDL_PEN_ERASER_MASK) ? SDL_PEN_TIP_ERASER : SDL_PEN_TIP_INK; + event.ptip.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; + + posted = SDL_PushEvent(&event) > 0; + + if (!posted) { + return SDL_FALSE; + } + } + + /* Mouse emulation */ + if (pen_delay_mouse_button_mode) { + /* Send button events when pen touches / leaves surface */ + mouse_button = pen->last_mouse_button; + if (0 == mouse_button) { + mouse_button = SDL_BUTTON_LEFT; /* No current button? Instead report left mouse button */ + } + } + + switch (pen_mouse_emulation_mode) { + case PEN_MOUSE_EMULATE: + return (SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, state, mouse_button)) || posted; + + case PEN_MOUSE_STATELESS: + /* Report mouse event without updating mouse state */ + event.button.type = state == SDL_PRESSED ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; + if (SDL_EventEnabled(event.button.type)) { + event.button.windowID = window ? window->id : 0; + event.button.timestamp = timestamp; + event.button.which = SDL_PEN_MOUSEID; + + event.button.state = state; + event.button.button = mouse_button; + event.button.clicks = 1; + event.button.x = last->x; + event.button.y = last->y; + return (SDL_PushEvent(&event) > 0) || posted; + } + break; + + default: + break; + } + return posted; +} + +int SDL_SendPenButton(Uint64 timestamp, + SDL_PenID instance_id, + Uint8 state, Uint8 button) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Pen *pen = SDL_GetPenPtr(instance_id); + SDL_Event event; + SDL_bool posted = SDL_FALSE; + SDL_PenStatusInfo *last = &pen->last; + int mouse_button = button + 1; /* For mouse emulation, PEN_DOWN counts as button 1, so the first actual button is mouse button 2 */ + SDL_Window *window; + + if (!pen) { + return SDL_FALSE; + } + window = pen->header.window; + + if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) { + return SDL_FALSE; + } + + if (state == SDL_PRESSED) { + event.pbutton.type = SDL_EVENT_PEN_BUTTON_DOWN; + pen->last.buttons |= (1 << (button - 1)); + } else { + event.pbutton.type = SDL_EVENT_PEN_BUTTON_UP; + pen->last.buttons &= ~(1 << (button - 1)); + } + + if (SDL_EventEnabled(event.pbutton.type)) { + event_setup(pen, window, timestamp, &pen->last, &event); + + event.pbutton.button = button; + event.pbutton.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; + + posted = SDL_PushEvent(&event) > 0; + + if (!posted) { + return SDL_FALSE; + } + } + + /* Mouse emulation */ + if (pen_delay_mouse_button_mode) { + /* Can only change active mouse button while not touching the surface */ + if (!(pen->header.flags & SDL_PEN_DOWN_MASK)) { + if (state == SDL_RELEASED) { + pen->last_mouse_button = 0; + } else { + pen->last_mouse_button = mouse_button; + } + } + /* Defer emulation event */ + return SDL_TRUE; + } + + switch (pen_mouse_emulation_mode) { + case PEN_MOUSE_EMULATE: + return (SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, state, mouse_button)) || posted; + + case PEN_MOUSE_STATELESS: + /* Report mouse event without updating mouse state */ + event.button.type = state == SDL_PRESSED ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; + if (SDL_EventEnabled(event.button.type)) { + event.button.windowID = window ? window->id : 0; + event.button.timestamp = timestamp; + event.button.which = SDL_PEN_MOUSEID; + + event.button.state = state; + event.button.button = mouse_button; + event.button.clicks = 1; + event.button.x = last->x; + event.button.y = last->y; + return (SDL_PushEvent(&event) > 0) || posted; + } + break; + + default: + break; + } + return posted; +} + +int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window) +{ + SDL_EventType event_id = window ? SDL_EVENT_WINDOW_PEN_ENTER : SDL_EVENT_WINDOW_PEN_LEAVE; + SDL_Event event = { 0 }; + SDL_Pen *pen = SDL_GetPenPtr(instance_id); + SDL_bool posted; + + if (!pen) { + return SDL_FALSE; + } + + if (pen->header.window == window) { /* (TRIVIAL-EVENT) Nothing new to report */ + return SDL_FALSE; + } + + if (timestamp == 0) { + /* Generate timestamp ourselves, if needed, so that we report the same timestamp + for the pen event and for any emulated mouse event */ + timestamp = SDL_GetTicksNS(); + } + + event.window.type = event_id; + /* If window == NULL and not (TRIVIAL-EVENT), then pen->header.window != NULL */ + event.window.timestamp = timestamp; + event.window.windowID = window ? window->id : pen->header.window->id; + event.window.data1 = instance_id; + posted = (SDL_PushEvent(&event) > 0); + + /* Update after assembling event */ + pen->header.window = window; + + switch (pen_mouse_emulation_mode) { + case PEN_MOUSE_EMULATE: + SDL_SetMouseFocus(event_id == SDL_EVENT_WINDOW_PEN_ENTER ? window : NULL); + break; + + case PEN_MOUSE_STATELESS: + /* Send event without going through mouse API */ + if (event_id == SDL_EVENT_WINDOW_PEN_ENTER) { + event.window.type = SDL_EVENT_WINDOW_MOUSE_ENTER; + } else { + event.window.type = SDL_EVENT_WINDOW_MOUSE_LEAVE; + } + posted = posted || (SDL_PushEvent(&event) > 0); + break; + + default: + break; + } + + return posted; +} + +static void SDLCALL SDL_PenUpdateHint(void *userdata, const char *name, const char *oldvalue, const char *newvalue) +{ + int *var = userdata; + if (newvalue == NULL) { + return; + } + + if (0 == SDL_strcmp("2", newvalue)) { + *var = 2; + } else if (0 == SDL_strcmp("1", newvalue)) { + *var = 1; + } else if (0 == SDL_strcmp("0", newvalue)) { + *var = 0; + } else { + SDL_Log("Unexpected value for pen hint: '%s'", newvalue); + } +} + +void SDL_PenInit(void) +{ +#if (SDL_PEN_DEBUG_NOID | SDL_PEN_DEBUG_NONWACOM | SDL_PEN_DEBUG_UNKNOWN_WACOM) + printf("[pen] Debugging enabled: noid=%d nonwacom=%d unknown-wacom=%d\n", + SDL_PEN_DEBUG_NOID, SDL_PEN_DEBUG_NONWACOM, SDL_PEN_DEBUG_UNKNOWN_WACOM); +#endif + SDL_AddHintCallback(SDL_HINT_PEN_NOT_MOUSE, + SDL_PenUpdateHint, &pen_mouse_emulation_mode); + + SDL_AddHintCallback(SDL_HINT_PEN_DELAY_MOUSE_BUTTON, + SDL_PenUpdateHint, &pen_delay_mouse_button_mode); +#ifndef SDL_THREADS_DISABLED + SDL_pen_access_lock = SDL_CreateMutex(); +#endif +} + +SDL_bool SDL_PenPerformHitTest(void) +{ + return pen_mouse_emulation_mode == PEN_MOUSE_EMULATE; +} + +/* Vendor-specific bits */ + +/* Default pen names */ +#define PEN_NAME_AES 0 +#define PEN_NAME_ART 1 +#define PEN_NAME_AIRBRUSH 2 +#define PEN_NAME_GENERAL 3 +#define PEN_NAME_GRIP 4 +#define PEN_NAME_INKING 5 +#define PEN_NAME_PRO 6 +#define PEN_NAME_PRO2 7 +#define PEN_NAME_PRO3 8 +#define PEN_NAME_PRO3D 9 +#define PEN_NAME_PRO_SLIM 10 +#define PEN_NAME_STROKE 11 + +#define PEN_NAME_LAST PEN_NAME_STROKE +#define PEN_NUM_NAMES (PEN_NAME_LAST + 1) + +const static char *default_pen_names[PEN_NUM_NAMES] = { + /* PEN_NAME_AES */ + "AES Pen", + /* PEN_NAME_ART */ + "Art Pen", + /* PEN_NAME_AIRBRUSH */ + "Airbrush Pen", + /* PEN_NAME_GENERAL */ + "Pen", + /* PEN_NAME_GRIP */ + "Grip Pen", + /* PEN_NAME_INKING */ + "Inking Pen", + /* PEN_NAME_PRO */ + "Pro Pen", + /* PEN_NAME_PRO2 */ + "Pro Pen 2", + /* PEN_NAME_PRO3 */ + "Pro Pen 3", + /* PEN_NAME_PRO3D */ + "Pro Pen 3D", + /* PEN_NAME_PRO_SLIM */ + "Pro Pen Slim", + /* PEN_NAME_STROKE */ + "Stroke Pen" +}; + +#define PEN_SPEC_TYPE_SHIFT 0 +#define PEN_SPEC_TYPE_MASK 0x0000000fu +#define PEN_SPEC_BUTTONS_SHIFT 4 +#define PEN_SPEC_BUTTONS_MASK 0x000000f0u +#define PEN_SPEC_NAME_SHIFT 8 +#define PEN_SPEC_NAME_MASK 0x00000f00u +#define PEN_SPEC_AXES_SHIFT 0 +#define PEN_SPEC_AXES_MASK 0xffff0000u + +#define PEN_WACOM_ID_INVALID 0xffffffffu /* Generic "invalid ID" marker */ + +#define PEN_SPEC(name, buttons, type, axes) (0 | (PEN_SPEC_NAME_MASK & ((name) << PEN_SPEC_NAME_SHIFT)) | (PEN_SPEC_BUTTONS_MASK & ((buttons) << PEN_SPEC_BUTTONS_SHIFT)) | (PEN_SPEC_TYPE_MASK & ((type) << PEN_SPEC_TYPE_SHIFT)) | (PEN_SPEC_AXES_MASK & ((axes) << PEN_SPEC_AXES_SHIFT))) + +/* Returns a suitable pen name string from default_pen_names on success, otherwise NULL. */ +static const char *pen_wacom_identify_tool(Uint32 requested_wacom_id, int *num_buttons, int *tool_type, int *axes) +{ + int i; + + /* List of known Wacom pens, extracted from libwacom.stylus and wacom_wac.c in the Linux kernel. + Could be complemented by dlopen()ing libwacom, in the future (if new pens get added). */ + struct + { + /* Compress properties to 8 bytes per device in order to keep memory cost well below 1k. + Could be compressed further with more complex code. */ + Uint32 wacom_id; /* Must be != PEN_WACOM_ID_INVALID */ + Uint32 properties; + } tools[] = { + { 0x0001, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0011, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0019, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0021, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0031, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0039, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0049, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0071, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0200, PEN_SPEC(PEN_NAME_PRO3, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0221, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0231, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0271, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0421, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0431, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0621, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0631, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, + { 0x0801, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0802, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0804, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, + { 0x080a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x080c, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0812, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0813, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x081b, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0822, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0823, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x082a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x082b, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0832, PEN_SPEC(PEN_NAME_STROKE, 0, SDL_PEN_TYPE_BRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0842, PEN_SPEC(PEN_NAME_PRO2, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x084a, PEN_SPEC(PEN_NAME_PRO2, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0852, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x085a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0862, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0885, PEN_SPEC(PEN_NAME_ART, 0, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, + { 0x08e2, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0902, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, + { 0x090a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0912, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, + { 0x0913, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x091a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x091b, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x0d12, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, + { 0x0d1a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x8051, PEN_SPEC(PEN_NAME_AES, 0, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x805b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x806b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x807b, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x826b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x846b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, + { 0x2802, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x4200, PEN_SPEC(PEN_NAME_PRO3, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x4802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x480a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x8842, PEN_SPEC(PEN_NAME_PRO3D, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x10802, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x10804, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, + { 0x1080a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x1080c, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x10842, PEN_SPEC(PEN_NAME_PRO_SLIM, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x1084a, PEN_SPEC(PEN_NAME_PRO_SLIM, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x10902, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, + { 0x1090a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x12802, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x14802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x1480a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x16802, PEN_SPEC(PEN_NAME_PRO, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x1680a, PEN_SPEC(PEN_NAME_PRO, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x18802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0x1880a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, + { 0, 0 } + }; + + /* The list of pens is sorted, so we could do binary search, but this call should be pretty rare. */ + for (i = 0; tools[i].wacom_id; ++i) { + if (tools[i].wacom_id == requested_wacom_id) { + Uint32 properties = tools[i].properties; + int name_index = (properties & PEN_SPEC_NAME_MASK) >> PEN_SPEC_NAME_SHIFT; + + *num_buttons = (properties & PEN_SPEC_BUTTONS_MASK) >> PEN_SPEC_BUTTONS_SHIFT; + *tool_type = (properties & PEN_SPEC_TYPE_MASK) >> PEN_SPEC_TYPE_SHIFT; + *axes = (properties & PEN_SPEC_AXES_MASK) >> PEN_SPEC_AXES_SHIFT; + + return default_pen_names[name_index]; + } + } + return NULL; +} + +void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower) +{ + int i; + + for (i = 0; i < 4; ++i) { + guid->data[8 + i] = (lower >> (i * 8)) & 0xff; + } + + for (i = 0; i < 4; ++i) { + guid->data[12 + i] = (upper >> (i * 8)) & 0xff; + } +} + +void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype) +{ + guid->data[7] = pentype; +} + +void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id) +{ + int i; + + for (i = 0; i < 4; ++i) { + guid->data[0 + i] = (wacom_serial_id >> (i * 8)) & 0xff; + } + + for (i = 0; i < 3; ++i) { /* 24 bit values */ + guid->data[4 + i] = (wacom_devicetype_id >> (i * 8)) & 0xff; + } +} + +int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags) +{ + const char *name = NULL; + int num_buttons; + int tool_type; + int axes; + +#if SDL_PEN_DEBUG_UNKNOWN_WACOM + wacom_devicetype_id = PEN_WACOM_ID_INVALID; /* force detection to fail */ +#endif + +#if defined(__LINUX__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + /* According to Ping Cheng, the curent Wacom for Linux maintainer, device IDs on Linux + squeeze a "0" nibble after the 3rd (least significant) nibble. + This may also affect the *BSDs, so they are heuristically included here. + On those platforms, we first try the "patched" ID: */ + if (0 == (wacom_devicetype_id & 0x0000f000u)) { + const Uint32 lower_mask = 0xfffu; + int wacom_devicetype_alt_id = ((wacom_devicetype_id & ~lower_mask) >> 4) | (wacom_devicetype_id & lower_mask); + + name = pen_wacom_identify_tool(wacom_devicetype_alt_id, &num_buttons, &tool_type, &axes); + if (name) { + wacom_devicetype_id = wacom_devicetype_alt_id; + } + } +#endif + if (name == NULL) { + name = pen_wacom_identify_tool(wacom_devicetype_id, &num_buttons, &tool_type, &axes); + } + + if (!name) { + return SDL_FALSE; + } + + *axis_flags = axes; + + /* Override defaults */ + if (pen->info.num_buttons == SDL_PEN_INFO_UNKNOWN) { + pen->info.num_buttons = num_buttons; + } + if (pen->type == SDL_PEN_TYPE_PEN) { + pen->type = (SDL_PenSubtype)tool_type; + } + if (pen->info.max_tilt == SDL_PEN_INFO_UNKNOWN) { + /* supposedly: 64 degrees left, 63 right, as reported by the Wacom X11 driver */ + pen->info.max_tilt = 64.0f; + } + pen->info.wacom_id = wacom_devicetype_id; + if (0 == pen->name[0]) { + SDL_snprintf(pen->name, SDL_PEN_MAX_NAME, + "Wacom %s%s", name, (tool_type == SDL_PEN_TYPE_ERASER) ? " Eraser" : ""); + } + return SDL_TRUE; +} diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h new file mode 100644 index 0000000000000..0488d5d92f798 --- /dev/null +++ b/src/events/SDL_pen_c.h @@ -0,0 +1,336 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../SDL_internal.h" + +#ifndef SDL_pen_c_h_ +#define SDL_pen_c_h_ + +#include "../../include/SDL3/SDL_pen.h" +#include "SDL_mouse_c.h" + +/* For testing alternate code paths: */ +#define SDL_PEN_DEBUG_NOID 0 /* Pretend that pen device does not supply ID / ID is some default value \ + affects: SDL_x11pen.c \ + SDL_waylandevents.c */ +#define SDL_PEN_DEBUG_NONWACOM 0 /* Pretend that no attached device is a Wacom device \ + affects: SDL_x11pen.c \ + SDL_waylandevents.c */ +#define SDL_PEN_DEBUG_UNKNOWN_WACOM 0 /* Pretend that any attached Wacom device is of an unknown make \ + affects: SDL_PenModifyFromWacomID() */ +#define SDL_PEN_DEBUG_NOSERIAL_WACOM 0 /* Pretend that any attached Wacom device has serial number 0 \ + affects: SDL_x11pen.c \ + SDL_waylandevents.c */ + +#define SDL_PEN_TYPE_NONE 0 /**< Pen type for non-pens (use to cancel pen registration) */ + +#define SDL_PEN_MAX_NAME 64 + +#define SDL_PEN_FLAG_ERROR (1ul << 28) /* Printed an internal API usage error about this pen (used to prevent spamming) */ +#define SDL_PEN_FLAG_NEW (1ul << 29) /* Pen was registered in most recent call to SDL_PenRegisterBegin() */ +#define SDL_PEN_FLAG_DETACHED (1ul << 30) /* Detached (not re-registered before last SDL_PenGCSweep()) */ +#define SDL_PEN_FLAG_STALE (1ul << 31) /* Not re-registered since last SDL_PenGCMark() */ + +typedef struct SDL_PenStatusInfo +{ + float x, y; + float axes[SDL_PEN_NUM_AXES]; + Uint32 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */ +} SDL_PenStatusInfo; + +/** + * Internal (backend driver-independent) pen representation + * + * Implementation-specific backend drivers may read and write most of this structure, and + * are expected to initialise parts of it when registering a new pen. They must not write + * to the "header" section. + */ +typedef struct SDL_Pen +{ + /* Backend driver MUST NOT not write to: */ + struct SDL_Pen_header + { + SDL_PenID id; /* id determines sort order unless SDL_PEN_FLAG_DETACHED is set */ + Uint32 flags; /* SDL_PEN_FLAG_* | SDK_PEN_DOWN_MASK | SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_* */ + SDL_Window *window; /* Current SDL window for this pen, or NULL */ + } header; + + SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */ + + /* Backend: MUST initialise this block when pen is first registered: */ + SDL_GUID guid; /* GUID, MUST be set by backend. + MUST be unique (no other pen ID with same GUID). + SHOULD be persistent across sessions. */ + + /* Backend: SHOULD initialise this block when pen is first registered if it can + Otherwise: Set to sane default values during SDL_PenModifyEnd() */ + SDL_PenCapabilityInfo info; /* Detail information about the pen (buttons, tilt) */ + SDL_PenSubtype type; + Uint8 last_mouse_button; /* For mouse button emulation: last emulated button */ + char *name; /* Preallocated; set via SDL_strlcpy(pen->name, src, SDL_PEN_MAX_NAME) */ + /* We hand this exact pointer to client code, so it must not be modified after + creation. */ + + void *deviceinfo; /* implementation-specific information */ +} SDL_Pen; + +/* ---- API for backend driver only ---- */ + +/** + * (Only for backend driver) Look up a pen by pen ID + * + * \param instance_id A Uint32 pen identifier (driver-dependent meaning). Must not be 0 = SDL_PEN_INVALID. + * The same ID is exposed to clients as SDL_PenID. + * + * The pen pointer is only valid until the next call to SDL_PenModifyEnd() or SDL_PenGCSweep() + * + * \return pen, if it exists, or NULL + */ +extern SDL_Pen *SDL_GetPenPtr(Uint32 instance_id); + +/** + * (Only for backend driver) Start registering a new pen or updating an existing pen. + * + * Acquires the pen mutex, which is held until the next call to SDL_PenModifyEnd() . + * + * If the PenID already exists, returns the existing entry. Otherwise initialise fresh SDL_Pen. + * For new pens, sets SDL_PEN_FLAG_NEW. + * + * Usage: + * - SDL_PenModifyStart() + * - update pen object, in any order: + * - SDL_PenModifyAddCapabilities() + * - pen->guid (MUST be set for new pens, e.g. via ::SDL_PenUpdateGUIDForGeneric and related operations) + * - pen->info.num_buttons + * - pen->info.max_tilt + * - pen->type + * - pen->name + * - pen->deviceinfo (backend-specific) + * - SDL_PenModifyEnd() + * + * For new pens, sets defaults for: + * - num_buttons (SDL_PEN_INFO_UNKNOWN) + * - max_tilt (SDL_PEN_INFO_UNKNOWN) + * - pen_type (SDL_PEN_TYPE_PEN) + * - Zeroes all other (non-header) fields + * + * \param instance_id Pen ID to allocate (must not be 0 = SDL_PEN_ID_INVALID) + * \returns SDL_Pen pointer; only valid until the call to SDL_PenModifyEnd() + */ +extern SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id); + +/** + * (Only for backend driver) Add capabilities to a pen (cf. SDL_PenModifyBegin()). + * + * Adds capabilities to a pen obtained via SDL_PenModifyBegin(). Can be called more than once. + * + * \param pen The pen to update + * \param capabilities Capabilities flags, out of: SDL_PEN_AXIS_*, SDL_PEN_ERASER_MASK, SDL_PEN_INK_MASK + * Setting SDL_PEN_ERASER_MASK will clear SDL_PEN_INK_MASK, and vice versa. + */ +extern void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities); + +/** + * Set up a pen structure for a Wacom device. + * + * Some backends (e.g., XInput2, Wayland) can only partially identify the capabilities of a given + * pen but can identify Wacom pens and obtain their Wacom-specific device type identifiers. + * This function partly automates device setup in those cases. + * + * This function does NOT set up the pen's GUID. Use ::SD_PenModifyGUIDForWacom instead. + * + * This function does NOT call SDL_PenModifyAddCapabilities() ifself, since some backends may + * not have access to all pen axes (e.g., Xinput2). + * + * \param pen The pen to initialise + * \param wacom_devicetype_id The Wacom-specific device type identifier + * \param[out] axis_flags The set of physically supported axes for this pen, suitable for passing to + * SDL_PenModifyAddCapabilities() + * + * \returns SDL_TRUE if the device ID could be identified, otherwise SDL_FALSE + */ +extern int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags); + +/** + * Updates a GUID for a generic pen device. + * + * Assumes that the GUID has been pre-initialised (typically to 0). + * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForType + * + * \param[out] guid The GUID to update + * \param upper Upper half of the device ID (assume lower entropy than "lower"; pass 0 if not available) + * \param lower Lower half of the device ID (assume higher entropy than "upper") + */ +extern void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower); + +/** + * Updates a GUID based on a pen type + * + * Assumes that the GUID has been pre-initialised (typically to 0). + * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForGeneric + * + * \param[out] guid The GUID to update + * \param pentype The pen type to insert + */ +extern void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype); + +/** + * Updates a GUID for a Wacom pen device. + * + * Assumes that the GUID has been pre-initialised (typically to 0). + * Idempotent, and commutative with ::SDL_PenUpdateGUIDForType and ::SDL_PenUpdateGUIDForGeneric + * + * This update is identical to the one written by ::SDL_PenModifyFromWacomID . + * + * \param[out] guid The GUID to update + * \param wacom_devicetype_id The Wacom-specific device type identifier + * \param wacom_serial_id The Wacom-specific serial number + */ +extern void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id); + +/** + * (Only for backend driver) Finish updating a pen. + * + * Releases the pen mutex acquired by SDL_PenModifyBegin() . + * + * If pen->type == SDL_PEN_TYPE_NONE, removes the pen entirely (only + * for new pens). This allows backends to start registering a + * potential pen device and to abort if the device turns out to not be + * a pen. + * + * For new pens, this call will also set the following: + * - name (default name, if not yet set) + * + * \param pen The pen to register. That pointer is no longer valid after this call. + * \param attach Whether the pen should be attached (SDL_TRUE) or detached (SDL_FALSE). + * + * If the pen is detached or removed, it is the caller's responsibility to free + * and null "deviceinfo". + */ +extern void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach); + +/** + * (Only for backend driver) Mark all current pens for garbage collection. + * + * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ). + * + * SDL_PenGCMark() / SDL_PenGCSweep() provide a simple mechanism for + * detaching all known pens that are not discoverable. This allows + * backends to use the same code for pen discovery and for + * hotplugging: + * + * - SDL_PenGCMark() and start backend-specific discovery + * - for each discovered pen: SDL_PenModifyBegin() + SDL_PenModifyEnd() (this will retain existing state) + * - SDL_PenGCSweep() (will now detach all pens that were not re-registered). + */ +extern void SDL_PenGCMark(void); + +/** + * (Only for backend driver) Detach pens that haven't been reported attached since the last call to SDL_PenGCMark(). + * + * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ). + * + * See SDL_PenGCMark() for details. + * + * \param context Extra parameter to pass through to "free_deviceinfo" + * \param free_deviceinfo Operation to call on any non-NULL "backend.deviceinfo". + * + * \sa SDL_PenGCMark() + */ +extern void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32 instance_id, void *deviceinfo, void *context)); + +/** + * (Only for backend driver) Send a pen motion event. + * + * Suppresses pen motion events that do not change the current pen state. + * May also send a mouse motion event, if mouse emulation is enabled and the pen position has + * changed sufficiently for the motion to be visible to mouse event listeners. + * + * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . + * While 0 is safe to report, your backends may be able to report more precise + * timing information. + * Keep in mind that you should never report timestamps that are greater than + * SDL_GetTicksNS() . In particular, SDL_GetTicksNS() reports nanoseconds since the start + * of the SDL session, and your backend may use a different starting point as "timestamp zero". + * \param instance_id Pen + * \param window_relative Coordinates are already window-relative + * \param status Coordinates and axes (buttons are ignored) + * + * \returns SDL_TRUE if at least one event was sent + */ +extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_bool window_relative, const SDL_PenStatusInfo *status); + +/** + * (Only for backend driver) Send a pen button event + * + * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . + * See SDL_SendPenMotion() for a discussion about how to handle timestamps. + * \param instance_id Pen + * \param state SDL_PRESSED or SDL_RELEASED + * \param button Button number: 1 (first physical button) etc. + * + * \returns SDL_TRUE if at least one event was sent + */ +extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button); + +/** + * (Only for backend driver) Send a pen tip event (touching or no longer touching the surface) + * + * Note: the backend should perform hit testing on window decoration elements to allow the pen + * to e.g. resize/move the window, just as for mouse events, unless ::SDL_SendPenTipEvent is false. + * + * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . + * See SDL_SendPenMotion() for a discussion about how to handle timestamps. + * \param instance_id Pen + * \param state SDL_PRESSED (for PEN_DOWN) or SDL_RELEASED (for PEN_UP) + * + * \returns SDL_TRUE if at least one event was sent + */ +extern int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state); + +/** + * (Only for backend driver) Check if a PEN_DOWN event should perform hit box testing. + * + * \returns SDL_TRUE if and only if the backend should perform hit testing + */ +extern SDL_bool SDL_PenPerformHitTest(void); + +/** + * (Only for backend driver) Send a pen window event. + * + * Tracks when a pen has entered/left a window. + * Don't call this when reporting new pens or removing known pens; those cases are handled automatically. + * + * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . + * See SDL_SendPenMotion() for a discussion about how to handle timestamps. + * \param instance_id Pen + * \param window Window to enter, or NULL to exit + */ +extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window); + +/** + * Initialises the pen subsystem. + */ +extern void SDL_PenInit(void); + +#endif /* SDL_pen_c_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 7d3fab4efee08..1a954c59ccd4f 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -572,13 +572,15 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer, } } -static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial) +static SDL_bool ProcessHitTest(SDL_WindowData *window_data, + struct wl_seat *seat, + wl_fixed_t sx_w, wl_fixed_t sy_w, + uint32_t serial) { - SDL_WindowData *window_data = input->pointer_focus; SDL_Window *window = window_data->sdlwindow; if (window->hit_test) { - const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) }; + const SDL_Point point = { wl_fixed_to_int(sx_w), wl_fixed_to_int(sy_w) }; const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); static const uint32_t directions[] = { @@ -602,14 +604,14 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial) #ifdef HAVE_LIBDECOR_H if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (window_data->shell_surface.libdecor.frame) { - libdecor_frame_move(window_data->shell_surface.libdecor.frame, input->seat, serial); + libdecor_frame_move(window_data->shell_surface.libdecor.frame, seat, serial); } } else #endif if (window_data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (window_data->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel, - input->seat, + seat, serial); } } @@ -626,14 +628,14 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial) #ifdef HAVE_LIBDECOR_H if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (window_data->shell_surface.libdecor.frame) { - libdecor_frame_resize(window_data->shell_surface.libdecor.frame, input->seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]); + libdecor_frame_resize(window_data->shell_surface.libdecor.frame, seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]); } } else #endif if (window_data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (window_data->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel, - input->seat, + seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]); } @@ -660,7 +662,7 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_ switch (button) { case BTN_LEFT: sdl_button = SDL_BUTTON_LEFT; - if (ProcessHitTest(input, serial)) { + if (ProcessHitTest(input->pointer_focus, input->seat, input->sx_w, input->sy_w, serial)) { return; /* don't pass this event on to app. */ } break; @@ -832,19 +834,19 @@ static void pointer_handle_axis(void *data, struct wl_pointer *pointer, } static void pointer_handle_axis_relative_direction(void *data, struct wl_pointer *pointer, - uint32_t axis, uint32_t axis_relative_direction) + uint32_t axis, uint32_t axis_relative_direction) { struct SDL_WaylandInput *input = data; if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { return; } switch (axis_relative_direction) { - case WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL: - input->pointer_curr_axis_info.direction = SDL_MOUSEWHEEL_NORMAL; - break; - case WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED: - input->pointer_curr_axis_info.direction = SDL_MOUSEWHEEL_FLIPPED; - break; + case WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL: + input->pointer_curr_axis_info.direction = SDL_MOUSEWHEEL_NORMAL; + break; + case WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED: + input->pointer_curr_axis_info.direction = SDL_MOUSEWHEEL_FLIPPED; + break; } } @@ -928,11 +930,11 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_motion, pointer_handle_button, pointer_handle_axis, - pointer_handle_frame, /* Version 5 */ - pointer_handle_axis_source, /* Version 5 */ - pointer_handle_axis_stop, /* Version 5 */ - pointer_handle_axis_discrete, /* Version 5 */ - pointer_handle_axis_value120, /* Version 8 */ + pointer_handle_frame, /* Version 5 */ + pointer_handle_axis_source, /* Version 5 */ + pointer_handle_axis_stop, /* Version 5 */ + pointer_handle_axis_discrete, /* Version 5 */ + pointer_handle_axis_value120, /* Version 8 */ pointer_handle_axis_relative_direction /* Version 9 */ }; @@ -2361,40 +2363,202 @@ void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t vers } } +static SDL_PenID Wayland_get_penid(void *data, struct zwp_tablet_tool_v2 *tool) +{ + struct SDL_WaylandTool *sdltool = data; + return sdltool->penid; +} + +/* For registering pens */ +static SDL_Pen *Wayland_get_current_pen(void *data, struct zwp_tablet_tool_v2 *tool) +{ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + + if (!input->current_pen.builder) { + /* Starting new pen or updating one? */ + SDL_PenID penid = sdltool->penid; + + if (penid == 0) { + /* Found completely new pen? */ + penid = ++input->num_pens; + sdltool->penid = penid; + } + input->current_pen.builder = SDL_GetPenPtr(penid); + if (!input->current_pen.builder) { + /* Must register as new pen */ + input->current_pen.builder = SDL_PenModifyBegin(penid); + } + } + return input->current_pen.builder; +} + static void tablet_tool_handle_type(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t type) { - /* unimplemented */ + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + + switch (type) { + case ZWP_TABLET_TOOL_V2_TYPE_ERASER: + pen->type = SDL_PEN_TYPE_ERASER; + break; + + case ZWP_TABLET_TOOL_V2_TYPE_PEN: + pen->type = SDL_PEN_TYPE_PEN; + break; + + case ZWP_TABLET_TOOL_V2_TYPE_PENCIL: + pen->type = SDL_PEN_TYPE_PENCIL; + break; + + case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH: + pen->type = SDL_PEN_TYPE_AIRBRUSH; + break; + + case ZWP_TABLET_TOOL_V2_TYPE_BRUSH: + pen->type = SDL_PEN_TYPE_BRUSH; + break; + + case ZWP_TABLET_TOOL_V2_TYPE_FINGER: + case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: + case ZWP_TABLET_TOOL_V2_TYPE_LENS: + default: + pen->type = SDL_PEN_TYPE_NONE; /* Mark for deregistration */ + } + + SDL_PenUpdateGUIDForType(&pen->guid, pen->type); } static void tablet_tool_handle_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial_hi, uint32_t serial_lo) { - /* unimplemented */ +#if !(SDL_PEN_DEBUG_NOID) + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + + if (!input->current_pen.builder_guid_complete) { + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + SDL_PenUpdateGUIDForGeneric(&pen->guid, serial_hi, serial_lo); + if (serial_hi || serial_lo) { + input->current_pen.builder_guid_complete = SDL_TRUE; + } + } +#endif } static void tablet_tool_handle_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t id_hi, uint32_t id_lo) { - /* unimplemented */ +#if !(SDL_PEN_DEBUG_NOID | SDL_PEN_DEBUG_NONWACOM) + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + Uint32 axis_flags; + +#if SDL_PEN_DEBUG_NOSERIAL_WACOM /* Check: have we disabled pen serial ID decoding for testing? */ + id_hi = 0; +#endif + + SDL_PenUpdateGUIDForWacom(&pen->guid, id_lo, id_hi); + if (id_hi) { /* Have a serial number? */ + input->current_pen.builder_guid_complete = SDL_TRUE; + } + + if (SDL_PenModifyForWacomID(pen, id_lo, &axis_flags)) { + SDL_PenModifyAddCapabilities(pen, axis_flags); + } +#endif } static void tablet_tool_handle_capability(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t capability) { - /* unimplemented */ + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + + switch (capability) { + case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK); + break; + + case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_PRESSURE_MASK); + break; + + case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_DISTANCE_MASK); + break; + + case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_ROTATION_MASK); + break; + + case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_SLIDER_MASK); + break; + + case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: + /* Presumably for tools other than pens? */ + break; + + default: + break; + } +} + +static void Wayland_tool_builder_reset(struct SDL_WaylandTabletInput *input) +{ + input->current_pen.builder = NULL; + input->current_pen.builder_guid_complete = SDL_FALSE; } static void tablet_tool_handle_done(void *data, struct zwp_tablet_tool_v2 *tool) { - /* unimplemented */ + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + + if (!input->current_pen.builder_guid_complete) { + /* No complete GUID? Use tablet and tool device index */ + SDL_PenUpdateGUIDForGeneric(&pen->guid, input->id, sdltool->penid); + } + + SDL_PenModifyEnd(pen, SDL_TRUE); + + Wayland_tool_builder_reset(input); } +static void Wayland_tool_destroy(struct zwp_tablet_tool_v2 *tool) +{ + if (tool) { + struct SDL_WaylandTool *waypen = zwp_tablet_tool_v2_get_user_data(tool); + if (waypen) { + SDL_free(waypen); + } + zwp_tablet_tool_v2_destroy(tool); + } +} + +static void tablet_object_list_remove(struct SDL_WaylandTabletObjectListNode *head, void *object); + static void tablet_tool_handle_removed(void *data, struct zwp_tablet_tool_v2 *tool) { - /* unimplemented */ + struct SDL_WaylandTool *waypen = zwp_tablet_tool_v2_get_user_data(tool); + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + SDL_Pen *pen = Wayland_get_current_pen(data, tool); + if (pen) { + SDL_PenModifyEnd(pen, SDL_FALSE); + Wayland_tool_builder_reset(waypen->tablet); + Wayland_tool_destroy(tool); + } else { + zwp_tablet_tool_v2_destroy(tool); + } + + tablet_object_list_remove(input->tools, tool); } static void tablet_tool_handle_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) { - struct SDL_WaylandTabletInput *input = data; + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; SDL_WindowData *window; + SDL_PenID penid = Wayland_get_penid(data, tool); if (!surface) { return; @@ -2410,155 +2574,214 @@ static void tablet_tool_handle_proximity_in(void *data, struct zwp_tablet_tool_v input->tool_focus = window; input->tool_prox_serial = serial; - input->is_down = SDL_FALSE; - - input->btn_stylus = SDL_FALSE; - input->btn_stylus2 = SDL_FALSE; - input->btn_stylus3 = SDL_FALSE; - - SDL_SetMouseFocus(window->sdlwindow); + if (penid) { + SDL_SendPenWindowEvent(0, penid, window->sdlwindow); + } else { + SDL_SetMouseFocus(window->sdlwindow); + } SDL_SetCursor(NULL); } } static void tablet_tool_handle_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool) { - struct SDL_WaylandTabletInput *input = data; - + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + SDL_PenID penid = Wayland_get_penid(data, tool); if (input->tool_focus) { - SDL_SetMouseFocus(NULL); + if (penid) { + SDL_SendPenWindowEvent(0, penid, NULL); + } else { + SDL_SetMouseFocus(NULL); + } input->tool_focus = NULL; } } -static uint32_t tablet_tool_btn_to_sdl_button(struct SDL_WaylandTabletInput *input) -{ - unsigned int tool_btn = input->btn_stylus3 << 2 | input->btn_stylus2 << 1 | input->btn_stylus << 0; - switch (tool_btn) { - case 0b000: - return SDL_BUTTON_LEFT; - case 0b001: - return SDL_BUTTON_RIGHT; - case 0b010: - return SDL_BUTTON_MIDDLE; - case 0b100: - return SDL_BUTTON_X1; - default: - return SDL_BUTTON_LEFT; - } -} - static void tablet_tool_handle_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial) { - struct SDL_WaylandTabletInput *input = data; - SDL_WindowData *window = input->tool_focus; - input->is_down = SDL_TRUE; - Wayland_UpdateImplicitGrabSerial(input->sdlWaylandInput, serial); - if (!window) { - /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd. - * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still - * received. To prevent SIGSEGV this returns when this is the case. - */ - return; - } + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + + input->current_pen.buttons_pressed |= SDL_PEN_DOWN_MASK; - SDL_SendMouseButton(0, window->sdlwindow, 0, SDL_PRESSED, tablet_tool_btn_to_sdl_button(input)); + input->current_pen.serial = serial; } static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 *tool) { - struct SDL_WaylandTabletInput *input = data; - SDL_WindowData *window = input->tool_focus; - - input->is_down = SDL_FALSE; - - if (!window) { - /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd. - * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still - * received. To prevent SIGSEGV this returns when this is the case. - */ - return; - } - - SDL_SendMouseButton(0, window->sdlwindow, 0, SDL_RELEASED, tablet_tool_btn_to_sdl_button(input)); + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + input->current_pen.buttons_released |= SDL_PEN_DOWN_MASK; } static void tablet_tool_handle_motion(void *data, struct zwp_tablet_tool_v2 *tool, wl_fixed_t sx_w, wl_fixed_t sy_w) { - struct SDL_WaylandTabletInput *input = data; + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; SDL_WindowData *window = input->tool_focus; + SDL_PenID penid = Wayland_get_penid(data, tool); input->sx_w = sx_w; input->sy_w = sy_w; + if (input->tool_focus) { - float sx = (float)(wl_fixed_to_double(sx_w) * window->pointer_scale_x); - float sy = (float)(wl_fixed_to_double(sy_w) * window->pointer_scale_y); - SDL_SendMouseMotion(0, window->sdlwindow, 0, 0, sx, sy); + const float sx_f = (float)wl_fixed_to_double(sx_w); + const float sy_f = (float)wl_fixed_to_double(sy_w); + const float sx = sx_f * window->pointer_scale_x; + const float sy = sy_f * window->pointer_scale_y; + + if (penid != SDL_PEN_INVALID) { + input->current_pen.update_status.x = sx; + input->current_pen.update_status.y = sy; + input->current_pen.update_window = window; + } else { + /* Plain mouse event */ + SDL_SendMouseMotion(0, window->sdlwindow, 0, 0, sx, sy); + } } } static void tablet_tool_handle_pressure(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t pressure) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + input->current_pen.update_status.axes[SDL_PEN_AXIS_PRESSURE] = pressure / 65535.0f; + if (pressure) { + input->current_pen.update_status.axes[SDL_PEN_AXIS_DISTANCE] = 0.0f; + } } static void tablet_tool_handle_distance(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t distance) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + input->current_pen.update_status.axes[SDL_PEN_AXIS_DISTANCE] = distance / 65535.0f; + if (distance) { + input->current_pen.update_status.axes[SDL_PEN_AXIS_PRESSURE] = 0.0f; + } } static void tablet_tool_handle_tilt(void *data, struct zwp_tablet_tool_v2 *tool, wl_fixed_t xtilt, wl_fixed_t ytilt) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + + input->current_pen.update_status.axes[SDL_PEN_AXIS_XTILT] = (float)(wl_fixed_to_double(xtilt)); + input->current_pen.update_status.axes[SDL_PEN_AXIS_YTILT] = (float)(wl_fixed_to_double(ytilt)); } static void tablet_tool_handle_button(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial, uint32_t button, uint32_t state) { - struct SDL_WaylandTabletInput *input = (struct SDL_WaylandTabletInput*)data; - - if (input->is_down) { - tablet_tool_handle_up(data, tool); - input->is_down = SDL_TRUE; - } + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + Uint16 mask = 0; + SDL_bool pressed = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE; - Wayland_UpdateImplicitGrabSerial(input->sdlWaylandInput, serial); + /* record event serial number to report it later in tablet_tool_handle_frame() */ + input->current_pen.serial = serial; switch (button) { /* see %{_includedir}/linux/input-event-codes.h */ case 0x14b: /* BTN_STYLUS */ - input->btn_stylus = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); + mask = SDL_BUTTON_LMASK; break; case 0x14c: /* BTN_STYLUS2 */ - input->btn_stylus2 = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); + mask = SDL_BUTTON_MMASK; break; case 0x149: /* BTN_STYLUS3 */ - input->btn_stylus3 = (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED); + mask = SDL_BUTTON_RMASK; break; } - if (input->is_down) { - tablet_tool_handle_down(data, tool, serial); + if (pressed) { + input->current_pen.buttons_pressed |= mask; + } else { + input->current_pen.buttons_released |= mask; } } static void tablet_tool_handle_rotation(void *data, struct zwp_tablet_tool_v2 *tool, wl_fixed_t degrees) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + float rotation = (float)(wl_fixed_to_double(degrees)); + + /* map to -180.0f ... 179.0f range: */ + input->current_pen.update_status.axes[SDL_PEN_AXIS_ROTATION] = rotation > 180.0f ? rotation - 360.0f : rotation; } static void tablet_tool_handle_slider(void *data, struct zwp_tablet_tool_v2 *tool, int32_t position) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + input->current_pen.update_status.axes[SDL_PEN_AXIS_SLIDER] = position / 65535.0; } static void tablet_tool_handle_wheel(void *data, struct zwp_tablet_tool_v2 *tool, int32_t degrees, int32_t clicks) { - /* unimplemented */ + /* not supported at the moment */ } static void tablet_tool_handle_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) { - /* unimplemented */ + struct SDL_WaylandTool *sdltool = data; + struct SDL_WaylandTabletInput *input = sdltool->tablet; + SDL_PenID penid = Wayland_get_penid(data, tool); + SDL_WindowData *window = input->current_pen.update_window; + SDL_PenStatusInfo *status = &input->current_pen.update_status; + int button; + int button_mask; + Uint64 timestamp = Wayland_GetEventTimestamp(SDL_MS_TO_NS(time)); + + if (penid == 0 || !window) { /* Not a pen, or event reported out of focus */ + return; + } + /* window == input->tool_focus */ + + /* All newly released buttons + PEN_UP event */ + button_mask = input->current_pen.buttons_released; + if (button_mask & SDL_PEN_DOWN_MASK) { + /* Perform hit test, if appropriate */ + if (!SDL_PenPerformHitTest() + || !ProcessHitTest(window, input->sdlWaylandInput->seat, input->sx_w, input->sy_w, input->current_pen.serial)) { + SDL_SendPenTipEvent(timestamp, penid, SDL_RELEASED); + } + } + button_mask &= ~SDL_PEN_DOWN_MASK; + + for (button = 1; button_mask; ++button, button_mask >>= 1) { + if (button_mask & 1) { + SDL_SendPenButton(timestamp, penid, SDL_RELEASED, button); + } + } + + /* All newly pressed buttons + PEN_DOWN event */ + button_mask = input->current_pen.buttons_pressed; + if (button_mask & SDL_PEN_DOWN_MASK) { + /* Perform hit test, if appropriate */ + if (!SDL_PenPerformHitTest() + || !ProcessHitTest(window, input->sdlWaylandInput->seat, input->sx_w, input->sy_w, input->current_pen.serial)) { + SDL_SendPenTipEvent(timestamp, penid, SDL_PRESSED); + } + } + button_mask &= ~SDL_PEN_DOWN_MASK; + + for (button = 1; button_mask; ++button, button_mask >>= 1) { + if (button_mask & 1) { + SDL_SendPenButton(timestamp, penid, SDL_PRESSED, button); + } + } + + SDL_SendPenMotion(timestamp, penid, SDL_TRUE, status); + + /* Wayland_UpdateImplicitGrabSerial will ignore serial 0, so it is safe to call with the default value */ + Wayland_UpdateImplicitGrabSerial(input->sdlWaylandInput, input->current_pen.serial); + + /* Reset masks for next tool frame */ + input->current_pen.buttons_pressed = 0; + input->current_pen.buttons_released = 0; + input->current_pen.serial = 0; } static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { @@ -2624,6 +2847,26 @@ static void tablet_object_list_destroy(struct SDL_WaylandTabletObjectListNode *h } } +void tablet_object_list_remove(struct SDL_WaylandTabletObjectListNode *head, void *object) +{ + struct SDL_WaylandTabletObjectListNode **head_p = &head; + while (*head_p && (*head_p)->object != object) { + head_p = &((*head_p)->next); + } + + if (*head_p) { + struct SDL_WaylandTabletObjectListNode *object_head = *head_p; + + if (object_head == head) { + /* Must not remove head node */ + head->object = NULL; + } else { + *head_p = object_head->next; + SDL_free(object_head); + } + } +} + static void tablet_seat_handle_tablet_added(void *data, struct zwp_tablet_seat_v2 *seat, struct zwp_tablet_v2 *tablet) { struct SDL_WaylandTabletInput *input = data; @@ -2634,9 +2877,12 @@ static void tablet_seat_handle_tablet_added(void *data, struct zwp_tablet_seat_v static void tablet_seat_handle_tool_added(void *data, struct zwp_tablet_seat_v2 *seat, struct zwp_tablet_tool_v2 *tool) { struct SDL_WaylandTabletInput *input = data; + struct SDL_WaylandTool *sdltool = SDL_calloc(1, sizeof(struct SDL_WaylandTool)); + + zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, sdltool); + zwp_tablet_tool_v2_set_user_data(tool, sdltool); - zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, data); - zwp_tablet_tool_v2_set_user_data(tool, data); + sdltool->tablet = input; tablet_object_list_append(input->tools, tool); } @@ -2657,6 +2903,7 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager *tablet_manager) { struct SDL_WaylandTabletInput *tablet_input; + static Uint32 num_tablets = 0; if (!tablet_manager || !input || !input->seat) { return; @@ -2675,6 +2922,7 @@ void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_Wayland tablet_input->tablets = tablet_object_list_new_node(NULL); tablet_input->tools = tablet_object_list_new_node(NULL); tablet_input->pads = tablet_object_list_new_node(NULL); + tablet_input->id = num_tablets++; zwp_tablet_seat_v2_add_listener((struct zwp_tablet_seat_v2 *)tablet_input->seat, &tablet_seat_listener, tablet_input); } @@ -2683,7 +2931,7 @@ void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_Wayland void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input) { tablet_object_list_destroy(input->tablet->pads, TABLET_OBJECT_LIST_DELETER(zwp_tablet_pad_v2_destroy)); - tablet_object_list_destroy(input->tablet->tools, TABLET_OBJECT_LIST_DELETER(zwp_tablet_tool_v2_destroy)); + tablet_object_list_destroy(input->tablet->tools, TABLET_OBJECT_LIST_DELETER(Wayland_tool_destroy)); tablet_object_list_destroy(input->tablet->tablets, TABLET_OBJECT_LIST_DELETER(zwp_tablet_v2_destroy)); zwp_tablet_seat_v2_destroy(input->tablet->seat); @@ -2808,7 +3056,8 @@ void Wayland_display_destroy_input(SDL_VideoData *d) wl_touch_destroy(input->touch); } - wl_list_for_each_safe (tp, tmp, &touch_points, link) { + wl_list_for_each_safe(tp, tmp, &touch_points, link) + { WAYLAND_wl_list_remove(&tp->link); SDL_free(tp); } diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 5dd5840841908..0d4e66ec5e816 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -25,6 +25,7 @@ #define SDL_waylandevents_h_ #include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_pen_c.h" #include "SDL_waylandvideo.h" #include "SDL_waylandwindow.h" @@ -55,31 +56,38 @@ struct SDL_WaylandTabletInput struct SDL_WaylandTabletObjectListNode *tools; struct SDL_WaylandTabletObjectListNode *pads; + Uint32 id; + Uint32 num_pens; /* next pen ID is num_pens+1 */ + struct SDL_WaylandCurrentPen + { + SDL_Pen *builder; /* pen that is being defined or receiving updates, if any */ + SDL_bool builder_guid_complete; /* have complete/precise GUID information */ + SDL_PenStatusInfo update_status; /* collects pen update information before sending event */ + Uint16 buttons_pressed; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_DOWN */ + Uint16 buttons_released; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_UP */ + Uint32 serial; /* Most recent serial event number observed, or 0 */ + SDL_WindowData *update_window; /* NULL while no event is in progress, otherwise the affected window */ + } current_pen; + SDL_WindowData *tool_focus; uint32_t tool_prox_serial; - /* Last motion location */ + /* Last motion end location (kept separate from sx_w, sy_w for the mouse pointer) */ wl_fixed_t sx_w; wl_fixed_t sy_w; - - SDL_bool is_down; - - SDL_bool btn_stylus; - SDL_bool btn_stylus2; - SDL_bool btn_stylus3; }; typedef struct { - int32_t repeat_rate; /* Repeat rate in range of [1, 1000] character(s) per second */ - int32_t repeat_delay_ms; /* Time to first repeat event in milliseconds */ + int32_t repeat_rate; /* Repeat rate in range of [1, 1000] character(s) per second */ + int32_t repeat_delay_ms; /* Time to first repeat event in milliseconds */ SDL_bool is_initialized; SDL_bool is_key_down; uint32_t key; - Uint64 wl_press_time_ns; /* Key press time as reported by the Wayland API */ - Uint64 sdl_press_time_ns; /* Key press time expressed in SDL ticks */ - Uint64 next_repeat_ns; /* Next repeat event in nanoseconds */ + Uint64 wl_press_time_ns; /* Key press time as reported by the Wayland API */ + Uint64 sdl_press_time_ns; /* Key press time expressed in SDL ticks */ + Uint64 next_repeat_ns; /* Next repeat event in nanoseconds */ uint32_t scancode; char text[8]; } SDL_WaylandKeyboardRepeat; @@ -169,6 +177,12 @@ struct SDL_WaylandInput SDL_Keymod locked_modifiers; }; +struct SDL_WaylandTool +{ + SDL_PenID penid; + struct SDL_WaylandTabletInput *tablet; +}; + extern Uint64 Wayland_GetTouchTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms); extern void Wayland_PumpEvents(SDL_VideoDevice *_this); diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 75acc17af7d3e..52ef9575ae8ef 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -179,14 +179,14 @@ static SDL_bool X11_KeyRepeat(Display *display, XEvent *event) return d.found; } -static SDL_bool X11_IsWheelEvent(Display *display, XEvent *event, int *xticks, int *yticks) +static SDL_bool X11_IsWheelEvent(Display *display, int button, int *xticks, int *yticks) { /* according to the xlib docs, no specific mouse wheel events exist. However, the defacto standard is that the vertical wheel is X buttons 4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */ /* Xlib defines "Button1" through 5, so we just use literals here. */ - switch (event->xbutton.button) { + switch (button) { case 4: *yticks = 1; return SDL_TRUE; @@ -333,13 +333,15 @@ void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) } #ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS -static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev) +static void X11_HandleGenericEvent(SDL_VideoDevice *_this, XEvent *xev) { + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + /* event is a union, so cookie == &event, but this is type safe. */ XGenericEventCookie *cookie = &xev->xcookie; if (X11_XGetEventData(videodata->display, cookie)) { if (!g_X11EventHook || g_X11EventHook(g_X11EventHookData, xev)) { - X11_HandleXinput2Event(videodata, cookie); + X11_HandleXinput2Event(_this, cookie); } X11_XFreeEventData(videodata->display, cookie); } @@ -557,12 +559,12 @@ static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *d X11_XSync(display, 0); } -static SDL_bool ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const XEvent *xev) +SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y) { SDL_Window *window = data->window; if (window->hit_test) { - const SDL_Point point = { xev->xbutton.x, xev->xbutton.y }; + const SDL_Point point = { x, y }; const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); static const int directions[] = { _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP, @@ -761,14 +763,14 @@ static Bool isReparentNotify(Display *display, XEvent *ev, XPointer arg) static SDL_bool IsHighLatin1(const char *string, int length) { - while (length-- > 0) { - Uint8 ch = (Uint8)*string; - if (ch >= 0x80) { - return SDL_TRUE; - } - ++string; - } - return SDL_FALSE; + while (length-- > 0) { + Uint8 ch = (Uint8)*string; + if (ch >= 0x80) { + return SDL_TRUE; + } + ++string; + } + return SDL_FALSE; } static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, XComposeStatus *status_in_out) @@ -787,6 +789,78 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int return result; } +SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window) +{ + const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + int i; + + if (videodata && videodata->windowlist) { + for (i = 0; i < videodata->numwindows; ++i) { + if ((videodata->windowlist[i] != NULL) && + (videodata->windowlist[i]->xwindow == window)) { + return videodata->windowlist[i]; + } + } + } + return NULL; +} + +void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button, const float x, const float y, const unsigned long time) +{ + SDL_Window *window = windowdata->window; + const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + Display *display = videodata->display; + int xticks = 0, yticks = 0; +#ifdef DEBUG_XEVENTS + printf("window %p: ButtonPress (X11 button = %d)\n", window, button); +#endif + if (X11_IsWheelEvent(display, button, &xticks, &yticks)) { + SDL_SendMouseWheel(0, window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL); + } else { + SDL_bool ignore_click = SDL_FALSE; + if (button == Button1) { + if (X11_ProcessHitTest(_this, windowdata, x, y)) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); + return; /* don't pass this event on to app. */ + } + } else if (button > 7) { + /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ... + => subtract (8-SDL_BUTTON_X1) to get value SDL expects */ + button -= (8 - SDL_BUTTON_X1); + } + if (windowdata->last_focus_event_time) { + const int X11_FOCUS_CLICK_TIMEOUT = 10; + if (SDL_GetTicks() < (windowdata->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) { + ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE); + } + windowdata->last_focus_event_time = 0; + } + if (!ignore_click) { + SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button); + } + } + X11_UpdateUserTime(windowdata, time); +} + +void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button) +{ + SDL_Window *window = windowdata->window; + const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + Display *display = videodata->display; + /* The X server sends a Release event for each Press for wheels. Ignore them. */ + int xticks = 0, yticks = 0; +#ifdef DEBUG_XEVENTS + printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button); +#endif + if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) { + if (button > 7) { + /* see explanation at case ButtonPress */ + button -= (8 - SDL_BUTTON_X1); + } + SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button); + } +} + void X11_GetBorderValues(SDL_WindowData *data) { SDL_VideoData *videodata = data->videodata; @@ -861,7 +935,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) #ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS if (xevent->type == GenericEvent) { - X11_HandleGenericEvent(videodata, xevent); + X11_HandleGenericEvent(_this, xevent); return; } #endif @@ -886,19 +960,19 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) #ifdef SDL_VIDEO_DRIVER_X11_XFIXES if (SDL_X11_HAVE_XFIXES && - xevent->type == X11_GetXFixesSelectionNotifyEvent()) { - XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *) xevent; + xevent->type == X11_GetXFixesSelectionNotifyEvent()) { + XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *)xevent; /* !!! FIXME: cache atoms */ Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0); #ifdef DEBUG_XEVENTS printf("window CLIPBOARD: XFixesSelectionNotify (selection = %s)\n", - X11_XGetAtomName(display, ev->selection)); + X11_XGetAtomName(display, ev->selection)); #endif if (ev->selection == XA_PRIMARY || - (XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) { + (XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) { SDL_SendClipboardUpdate(); return; } @@ -911,16 +985,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) return; } - data = NULL; - if (videodata && videodata->windowlist) { - for (i = 0; i < videodata->numwindows; ++i) { - if ((videodata->windowlist[i] != NULL) && - (videodata->windowlist[i]->xwindow == xevent->xany.window)) { - data = videodata->windowlist[i]; - break; - } - } - } + data = X11_FindWindow(_this, xevent->xany.window); + if (!data) { /* The window for KeymapNotify, etc events is 0 */ if (xevent->type == KeymapNotify) { @@ -1227,8 +1293,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) xevent->xconfigure.x, xevent->xconfigure.y, xevent->xconfigure.width, xevent->xconfigure.height); #endif - /* Real configure notify events are relative to the parent, synthetic events are absolute. */ - if (!xevent->xconfigure.send_event) { + /* Real configure notify events are relative to the parent, synthetic events are absolute. */ + if (!xevent->xconfigure.send_event) + { unsigned int NumChildren; Window ChildReturn, Root, Parent; Window *Children; @@ -1318,7 +1385,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) root_y = xevent->xclient.data.l[2] & 0xffff; /* Translate from root to current window position */ X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow, - root_x, root_y, &window_x, &window_y, &ChildReturn); + root_x, root_y, &window_x, &window_y, &ChildReturn); SDL_SendDropPosition(data->window, (float)window_x, (float)window_y); } @@ -1402,6 +1469,12 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); } break; + /* Use XInput2 instead of the xevents API if possible, for: + - MotionNotify + - ButtonPress + - ButtonRelease + XInput2 has more precise information, e.g., to distinguish different input devices. */ +#ifndef SDL_VIDEO_DRIVER_X11_XINPUT2 case MotionNotify: { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1416,55 +1489,15 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) case ButtonPress: { - int xticks = 0, yticks = 0; -#ifdef DEBUG_XEVENTS - printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent->xbutton.button); -#endif - if (X11_IsWheelEvent(display, xevent, &xticks, &yticks)) { - SDL_SendMouseWheel(0, data->window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL); - } else { - SDL_bool ignore_click = SDL_FALSE; - int button = xevent->xbutton.button; - if (button == Button1) { - if (ProcessHitTest(_this, data, xevent)) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); - break; /* don't pass this event on to app. */ - } - } else if (button > 7) { - /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ... - => subtract (8-SDL_BUTTON_X1) to get value SDL expects */ - button -= (8 - SDL_BUTTON_X1); - } - if (data->last_focus_event_time) { - const int X11_FOCUS_CLICK_TIMEOUT = 10; - if (SDL_GetTicks() < (data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) { - ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE); - } - data->last_focus_event_time = 0; - } - if (!ignore_click) { - SDL_SendMouseButton(0, data->window, 0, SDL_PRESSED, button); - } - } - X11_UpdateUserTime(data, xevent->xbutton.time); + X11_HandleButtonPress(_this, data, xevent->xbutton.button, + xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.time); } break; case ButtonRelease: { - int button = xevent->xbutton.button; - /* The X server sends a Release event for each Press for wheels. Ignore them. */ - int xticks = 0, yticks = 0; -#ifdef DEBUG_XEVENTS - printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button); -#endif - if (!X11_IsWheelEvent(display, xevent, &xticks, &yticks)) { - if (button > 7) { - /* see explanation at case ButtonPress */ - button -= (8 - SDL_BUTTON_X1); - } - SDL_SendMouseButton(0, data->window, 0, SDL_RELEASED, button); - } + X11_HandleButtonRelease(_this, data, xevent->xbutton.button); } break; +#endif /* !SDL_VIDEO_DRIVER_X11_XINPUT2 */ case PropertyNotify: { diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index 58cdb8dabb307..02c666540514e 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -29,5 +29,9 @@ extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window); extern int X11_SuspendScreenSaver(SDL_VideoDevice *_this); extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this); extern void X11_GetBorderValues(SDL_WindowData *data); +extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time); +extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button); +extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window); +extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y); #endif /* SDL_x11events_h_ */ diff --git a/src/video/x11/SDL_x11pen.c b/src/video/x11/SDL_x11pen.c new file mode 100644 index 0000000000000..94b4a5c1b94c8 --- /dev/null +++ b/src/video/x11/SDL_x11pen.c @@ -0,0 +1,694 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 + +#include "../../events/SDL_pen_c.h" +#include "../SDL_sysvideo.h" +#include "SDL_pen.h" +#include "SDL_x11pen.h" +#include "SDL_x11video.h" +#include "SDL_x11xinput2.h" + +#define PEN_ERASER_ID_MAXLEN 256 /* Max # characters of device name to scan */ +#define PEN_ERASER_NAME_TAG "eraser" /* String constant to identify erasers */ + +#define DEBUG_PEN (SDL_PEN_DEBUG_NOID | SDL_PEN_DEBUG_NONWACOM | SDL_PEN_DEBUG_UNKNOWN_WACOM | SDL_PEN_DEBUG_NOSERIAL_WACOM) + +#define SDL_PEN_AXIS_VALUATOR_MISSING -1 + +/* X11-specific information attached to each pen */ +typedef struct xinput2_pen +{ + float axis_min[SDL_PEN_NUM_AXES]; + float axis_max[SDL_PEN_NUM_AXES]; + float slider_bias; /* shift value to add to PEN_AXIS_SLIDER (before normalisation) */ + float rotation_bias; /* rotation to add to PEN_AXIS_ROTATION (after normalisation) */ + Sint8 valuator_for_axis[SDL_PEN_NUM_AXES]; /* SDL_PEN_AXIS_VALUATOR_MISSING if not supported */ +} xinput2_pen; + +/* X11 atoms */ +static struct +{ + int initialized; /* initialised to 0 */ + Atom device_product_id; + Atom abs_pressure; + Atom abs_tilt_x; + Atom abs_tilt_y; + Atom wacom_serial_ids; + Atom wacom_tool_type; +} pen_atoms; + +/* + * Mapping from X11 device IDs to pen IDs + * + * In X11, the same device ID may represent any number of pens. We + * thus cannot directly use device IDs as pen IDs. + */ +static struct +{ + int num_pens_known; /* Number of currently known pens (based on their GUID); used to give pen ID to new pens */ + int num_entries; /* Number of X11 device IDs that correspond to pens */ + + struct pen_device_id_mapping + { + Uint32 deviceid; + Uint32 pen_id; + } * entries; /* Current pen to device ID mappings */ +} pen_map; + +typedef enum +{ + SDL_PEN_VENDOR_UNKNOWN = 0, + SDL_PEN_VENDOR_WACOM +} sdl_pen_vendor; + +/* Information to identify pens during discovery */ +typedef struct +{ + sdl_pen_vendor vendor; + SDL_GUID guid; + SDL_PenSubtype heuristic_type; /* Distinguish pen+eraser devices with shared bus ID */ + Uint32 devicetype_id, serial; /* used by PEN_VENDOR_WACOM */ + Uint32 deviceid; +} pen_identity; + +int X11_PenIDFromDeviceID(int deviceid) +{ + int i; + for (i = 0; i < pen_map.num_entries; ++i) { + if (pen_map.entries[i].deviceid == deviceid) { + return pen_map.entries[i].pen_id; + } + } + return SDL_PEN_INVALID; +} + +static void pen_atoms_ensure_initialized(SDL_VideoDevice *_this) +{ + SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + + if (pen_atoms.initialized) { + return; + } + /* Create atoms if they don't exist yet to pre-empt hotplugging updates */ + pen_atoms.device_product_id = X11_XInternAtom(data->display, "Device Product ID", False); + pen_atoms.wacom_serial_ids = X11_XInternAtom(data->display, "Wacom Serial IDs", False); + pen_atoms.wacom_tool_type = X11_XInternAtom(data->display, "Wacom Tool Type", False); + pen_atoms.abs_pressure = X11_XInternAtom(data->display, "Abs Pressure", True); + pen_atoms.abs_tilt_x = X11_XInternAtom(data->display, "Abs Tilt X", True); + pen_atoms.abs_tilt_y = X11_XInternAtom(data->display, "Abs Tilt Y", True); + + pen_atoms.initialized = 1; +} + +/* Read out an integer property and store into a preallocated Sint32 array, extending 8 and 16 bit values suitably. + Returns number of Sint32s written (<= max_words), or 0 on error. */ +static size_t xinput2_pen_get_int_property(SDL_VideoDevice *_this, int deviceid, Atom property, Sint32 *dest, size_t max_words) +{ + const SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + Atom type_return; + int format_return; + unsigned long num_items_return; + unsigned long bytes_after_return; + unsigned char *output; + + if (property == None) { + return 0; + } + + if (Success != X11_XIGetProperty(data->display, deviceid, + property, + 0, max_words, False, + XA_INTEGER, &type_return, &format_return, + &num_items_return, &bytes_after_return, + &output) || + num_items_return == 0 || output == NULL) { + return 0; + } + + if (type_return == XA_INTEGER) { + int k; + const int to_copy = SDL_min(max_words, num_items_return); + + if (format_return == 8) { + Sint8 *numdata = (Sint8 *)output; + for (k = 0; k < to_copy; ++k) { + dest[k] = numdata[k]; + } + } else if (format_return == 16) { + Sint16 *numdata = (Sint16 *)output; + for (k = 0; k < to_copy; ++k) { + dest[k] = numdata[k]; + } + } else { + SDL_memcpy(dest, output, sizeof(Sint32) * to_copy); + } + X11_XFree(output); + return to_copy; + } + return 0; /* type mismatch */ +} + +/* 32 bit vendor + device ID from evdev */ +static Uint32 xinput2_pen_evdevid(SDL_VideoDevice *_this, int deviceid) +{ +#if !(SDL_PEN_DEBUG_NOID) + Sint32 ids[2]; + + pen_atoms_ensure_initialized(_this); + + if (2 != xinput2_pen_get_int_property(_this, deviceid, pen_atoms.device_product_id, ids, 2)) { + return 0; + } + return ((ids[0] << 16) | (ids[1] & 0xffff)); +#else /* Testing: pretend that we have no ID (not sure if this can happen IRL) */ + return 0; +#endif +} + +/* Gets reasonably-unique GUID for the device */ +static void xinput2_pen_update_generic_guid(SDL_VideoDevice *_this, pen_identity *pident, int deviceid) +{ + Uint32 evdevid = xinput2_pen_evdevid(_this, deviceid); /* also initialises pen_atoms */ + + if (!evdevid) { + /* Fallback: if no evdevid is available; try to at least distinguish devices within the + current session. This is a poor GUID and our last resort. */ + evdevid = deviceid; + } + SDL_PenUpdateGUIDForGeneric(&pident->guid, 0, evdevid); +} + +/* Identify Wacom devices (if SDL_TRUE is returned) and extract their device type and serial IDs */ +static SDL_bool xinput2_wacom_deviceid(SDL_VideoDevice *_this, int deviceid, Uint32 *wacom_devicetype_id, Uint32 *wacom_serial) +{ +#if !(SDL_PEN_DEBUG_NONWACOM) /* Can be disabled for testing */ + Sint32 serial_id_buf[3]; + int result; + + pen_atoms_ensure_initialized(_this); + + if ((result = xinput2_pen_get_int_property(_this, deviceid, pen_atoms.wacom_serial_ids, serial_id_buf, 3)) == 3) { + *wacom_devicetype_id = serial_id_buf[2]; + *wacom_serial = serial_id_buf[1]; +#if SDL_PEN_DEBUG_NOSERIAL_WACOM /* Disabled for testing? */ + *wacom_serial = 0; +#endif + return SDL_TRUE; + } +#endif + return SDL_FALSE; +} + +/* Heuristically determines if device is an eraser */ +static SDL_bool xinput2_pen_is_eraser(SDL_VideoDevice *_this, int deviceid, char *devicename) +{ + SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + char dev_name[PEN_ERASER_ID_MAXLEN]; + int k; + + pen_atoms_ensure_initialized(_this); + + if (pen_atoms.wacom_tool_type != None) { + Atom type_return; + int format_return; + unsigned long num_items_return; + unsigned long bytes_after_return; + unsigned char *tooltype_name_info = NULL; + + /* Try Wacom-specific method */ + if (Success == X11_XIGetProperty(data->display, deviceid, + pen_atoms.wacom_tool_type, + 0, 32, False, + AnyPropertyType, &type_return, &format_return, + &num_items_return, &bytes_after_return, + &tooltype_name_info) && + tooltype_name_info != NULL && num_items_return > 0) { + + SDL_bool result = SDL_FALSE; + char *tooltype_name = NULL; + + if (type_return == XA_ATOM) { + /* Atom instead of string? Un-intern */ + Atom atom = *((Atom *)tooltype_name_info); + if (atom != None) { + tooltype_name = X11_XGetAtomName(data->display, atom); + } + } else if (type_return == XA_STRING && format_return == 8) { + tooltype_name = (char *)tooltype_name_info; + } + + if (tooltype_name) { + if (0 == SDL_strcasecmp(tooltype_name, PEN_ERASER_NAME_TAG)) { + result = SDL_TRUE; + } + X11_XFree(tooltype_name_info); + + return result; + } + } + } + /* Non-Wacom device? */ + + /* We assume that a device is an eraser if its name contains the string "eraser". + * Unfortunately there doesn't seem to be a clean way to distinguish these cases (as of 2022-03). */ + + SDL_strlcpy(dev_name, devicename, PEN_ERASER_ID_MAXLEN); + /* lowercase device name string so we can use strstr() */ + for (k = 0; dev_name[k]; ++k) { + dev_name[k] = tolower(dev_name[k]); + } + + return (SDL_strstr(dev_name, PEN_ERASER_NAME_TAG)) ? SDL_TRUE : SDL_FALSE; +} + +/* Gets GUID and other identifying information for the device using the best known method */ +static pen_identity xinput2_identify_pen(SDL_VideoDevice *_this, int deviceid, char *name) +{ + pen_identity pident; + + pident.devicetype_id = 0ul; + pident.serial = 0ul; + pident.deviceid = deviceid; + pident.heuristic_type = SDL_PEN_TYPE_PEN; + SDL_memset(pident.guid.data, 0, sizeof(pident.guid.data)); + + if (xinput2_pen_is_eraser(_this, deviceid, name)) { + pident.heuristic_type = SDL_PEN_TYPE_ERASER; + } + + if (xinput2_wacom_deviceid(_this, deviceid, &pident.devicetype_id, &pident.serial)) { + pident.vendor = SDL_PEN_VENDOR_WACOM; + SDL_PenUpdateGUIDForWacom(&pident.guid, pident.devicetype_id, pident.serial); + +#if DEBUG_PEN + printf("[pen] Pen %d reports Wacom device_id %x\n", + deviceid, pident.devicetype_id); +#endif + + } else { + pident.vendor = SDL_PEN_VENDOR_UNKNOWN; + } + if (!pident.serial) { + /* If the pen has a serial number, we can move it across tablets and retain its identity. + Otherwise, we use the evdev ID as part of its GUID, which may mean that we identify it with the tablet. */ + xinput2_pen_update_generic_guid(_this, &pident, deviceid); + } + SDL_PenUpdateGUIDForType(&pident.guid, pident.heuristic_type); + return pident; +} + +static void xinput2_pen_free_deviceinfo(Uint32 deviceid, void *x11_peninfo, void *context) +{ + SDL_free(x11_peninfo); +} + +static void xinput2_merge_deviceinfo(xinput2_pen *dest, xinput2_pen *src) +{ + *dest = *src; +} + +/** + * Fill in vendor-specific device information, if available + * + * For Wacom pens: identify number of buttons and extra axis (if present) + * + * \param _this global state + * \param dev The device to analyse + * \param pen The pen to initialise + * \param pident Pen identity information + * \param[out] valuator_5 Meaning of the valuator with offset 5, if any + * (written only if known and if the device has a 6th axis, + * e.g., for the Wacom Art Pen and Wacom Airbrush Pen) + * \param[out] axes Bitmask of all possibly supported axes + * + * This function identifies Wacom device types through a Wacom-specific device ID. + * It then fills in pen details from an internal database. + * If the device seems to be a Wacom pen/eraser but can't be identified, the function + * leaves "axes" untouched and sets the other outputs to common defaults. + * + * There is no explicit support for other vendors, though vendors that + * emulate the Wacom API might be supported. + * + * Unsupported devices will keep the default settings. + */ +static void xinput2_vendor_peninfo(SDL_VideoDevice *_this, const XIDeviceInfo *dev, SDL_Pen *pen, pen_identity pident, int *valuator_5, Uint32 *axes) +{ + switch (pident.vendor) { + case SDL_PEN_VENDOR_WACOM: + { + if (SDL_PenModifyForWacomID(pen, pident.devicetype_id, axes)) { + if (*axes & SDL_PEN_AXIS_SLIDER_MASK) { + /* Air Brush Pen or eraser */ + *valuator_5 = SDL_PEN_AXIS_SLIDER; + } else if (*axes & SDL_PEN_AXIS_ROTATION_MASK) { + /* Art Pen or eraser, or 6D Art Pen */ + *valuator_5 = SDL_PEN_AXIS_ROTATION; + } + return; + } else { +#if DEBUG_PEN + printf("[pen] Could not identify wacom pen %d with device id %x, using default settings\n", + pident.deviceid, pident.devicetype_id); +#endif + break; + } + } + + default: +#if DEBUG_PEN + printf("[pen] Pen %d is not from a known vendor\n", pident.deviceid); +#endif + break; + } + + /* Fall back to default heuristics for identifying device type */ + + SDL_strlcpy(pen->name, dev->name, SDL_PEN_MAX_NAME); + + pen->type = pident.heuristic_type; +} + +/* Does this device have a valuator for pressure sensitivity? */ +static SDL_bool xinput2_device_is_pen(const XIDeviceInfo *dev) +{ + int classct; + for (classct = 0; classct < dev->num_classes; ++classct) { + const XIAnyClassInfo *classinfo = dev->classes[classct]; + + switch (classinfo->type) { + case XIValuatorClass: + { + XIValuatorClassInfo *val_classinfo = (XIValuatorClassInfo *)classinfo; + Atom vname = val_classinfo->label; + + if (vname == pen_atoms.abs_pressure) { + return SDL_TRUE; + } + } + } + } + return SDL_FALSE; +} + +void X11_InitPen(SDL_VideoDevice *_this) +{ + SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + int i; + XIDeviceInfo *device_info; + int num_device_info; + + device_info = X11_XIQueryDevice(data->display, XIAllDevices, &num_device_info); + if (!device_info) { + return; + } + + /* Reset the device id -> pen map */ + if (pen_map.entries) { + SDL_free(pen_map.entries); + pen_map.entries = NULL; + pen_map.num_entries = 0; + } + + SDL_PenGCMark(); + + for (i = 0; i < num_device_info; ++i) { + const XIDeviceInfo *dev = &device_info[i]; + int classct; + xinput2_pen pen_device; + Uint32 capabilities = 0; + Uint32 axis_mask = ~0; /* Permitted axes (default: all) */ + int valuator_5_axis = -1; /* For Wacom devices, the 6th valuator (offset 5) has a model-specific meaning */ + pen_identity pident; + SDL_PenID pen_id; + SDL_Pen *pen; + int old_num_pens_known = pen_map.num_pens_known; + int k; + + /* Only track physical devices that are enabled */ + if (dev->use != XISlavePointer || dev->enabled == 0 || !xinput2_device_is_pen(dev)) { + continue; + } + + pen_device.slider_bias = 0.0f; + pen_device.rotation_bias = 0.0f; + for (k = 0; k < SDL_PEN_NUM_AXES; ++k) { + pen_device.valuator_for_axis[k] = SDL_PEN_AXIS_VALUATOR_MISSING; + } + + pident = xinput2_identify_pen(_this, dev->deviceid, dev->name); + + pen_id = SDL_GetPenFromGUID(pident.guid); + if (pen_id == SDL_PEN_INVALID) { + /* We have never met this pen */ + pen_id = ++pen_map.num_pens_known; /* start at 1 */ + } + pen = SDL_PenModifyBegin(pen_id); + + /* Complement XF86 driver information with vendor-specific details */ + xinput2_vendor_peninfo(_this, dev, pen, pident, &valuator_5_axis, &axis_mask); + + for (classct = 0; classct < dev->num_classes; ++classct) { + const XIAnyClassInfo *classinfo = dev->classes[classct]; + + switch (classinfo->type) { + case XIValuatorClass: + { + XIValuatorClassInfo *val_classinfo = (XIValuatorClassInfo *)classinfo; + Sint8 valuator_nr = val_classinfo->number; + Atom vname = val_classinfo->label; + int axis = -1; + + float min = val_classinfo->min; + float max = val_classinfo->max; + + if (vname == pen_atoms.abs_pressure) { + axis = SDL_PEN_AXIS_PRESSURE; + } else if (vname == pen_atoms.abs_tilt_x) { + axis = SDL_PEN_AXIS_XTILT; + } else if (vname == pen_atoms.abs_tilt_y) { + axis = SDL_PEN_AXIS_YTILT; + } + + if (axis == -1 && valuator_nr == 5) { + /* Wacom model-specific axis support */ + /* The meaning of the various axes is highly underspecitied in Xinput2. + * As of 2023-08-26, Wacom seems to be the only vendor to support these axes, so the code below + * captures the de-facto standard. */ + axis = valuator_5_axis; + + switch (axis) { + case SDL_PEN_AXIS_SLIDER: + /* cf. xinput2_wacom_peninfo for how this axis is used. + In all current cases, our API wants this value in 0..1, but the xf86 driver + starts at a negative offset, so we normalise here. */ + pen_device.slider_bias = -min; + max -= min; + min = 0.0f; + break; + + case SDL_PEN_AXIS_ROTATION: + /* The "0" value points to the left, rather than up, so we must + rotate 90 degrees counter-clockwise to have 0 point to the top. */ + + pen_device.rotation_bias = -90.0f; + break; + + default: + break; + } + } + + if (axis >= 0) { + capabilities |= SDL_PEN_AXIS_CAPABILITY(axis); + + pen_device.valuator_for_axis[axis] = valuator_nr; + pen_device.axis_min[axis] = min; + pen_device.axis_max[axis] = max; + } + break; + } + default: + break; + } + } + + /* We have a pen if and only if the device measures pressure */ + if (capabilities & SDL_PEN_AXIS_PRESSURE_MASK) { + xinput2_pen *xinput2_deviceinfo; + Uint64 guid_a, guid_b; + + /* Done collecting data, write to pen */ + SDL_PenModifyAddCapabilities(pen, capabilities); + pen->guid = pident.guid; + + if (pen->deviceinfo) { + /* Updating a known pen */ + xinput2_deviceinfo = (xinput2_pen *)pen->deviceinfo; + xinput2_merge_deviceinfo(xinput2_deviceinfo, &pen_device); + } else { + /* Registering a new pen */ + xinput2_deviceinfo = SDL_malloc(sizeof(xinput2_pen)); + SDL_memcpy(xinput2_deviceinfo, &pen_device, sizeof(xinput2_pen)); + } + pen->deviceinfo = xinput2_deviceinfo; + +#if DEBUG_PEN + printf("[pen] pen %d [%04x] valuators pressure=%d, xtilt=%d, ytilt=%d [%s]\n", + pen->header.id, pen->header.flags, + pen_device.valuator_for_axis[SDL_PEN_AXIS_PRESSURE], + pen_device.valuator_for_axis[SDL_PEN_AXIS_XTILT], + pen_device.valuator_for_axis[SDL_PEN_AXIS_YTILT], + pen->name); +#endif + SDL_memcpy(&guid_a, &pen->guid.data[0], 8); + SDL_memcpy(&guid_b, &pen->guid.data[8], 8); + if (!(guid_a | guid_b)) { +#if DEBUG_PEN + printf("[pen] (pen eliminated due to zero GUID)\n"); +#endif + pen->type = SDL_PEN_TYPE_NONE; + } + + } else { + /* Not a pen, mark for deletion */ + pen->type = SDL_PEN_TYPE_NONE; + } + SDL_PenModifyEnd(pen, SDL_TRUE); + + if (pen->type != SDL_PEN_TYPE_NONE) { + const int map_pos = pen_map.num_entries; + + /* We found a pen: add mapping */ + if (pen_map.entries == NULL) { + pen_map.entries = SDL_calloc(sizeof(struct pen_device_id_mapping), 1); + pen_map.num_entries = 1; + } else { + pen_map.num_entries += 1; + pen_map.entries = SDL_realloc(pen_map.entries, + pen_map.num_entries * (sizeof(struct pen_device_id_mapping))); + } + pen_map.entries[map_pos].deviceid = dev->deviceid; + pen_map.entries[map_pos].pen_id = pen_id; + } else { + /* Revert pen number allocation */ + pen_map.num_pens_known = old_num_pens_known; + } + } + X11_XIFreeDeviceInfo(device_info); + + SDL_PenGCSweep(NULL, xinput2_pen_free_deviceinfo); +} + +static void xinput2_normalize_pen_axes(const SDL_Pen *peninfo, + const xinput2_pen *xpen, + /* inout-mode paramters: */ + float *coords) +{ + int axis; + + /* Normalise axes */ + for (axis = 0; axis < SDL_PEN_NUM_AXES; ++axis) { + int valuator = xpen->valuator_for_axis[axis]; + if (valuator != SDL_PEN_AXIS_VALUATOR_MISSING) { + float value = coords[axis]; + float min = xpen->axis_min[axis]; + float max = xpen->axis_max[axis]; + + if (axis == SDL_PEN_AXIS_SLIDER) { + value += xpen->slider_bias; + } + + /* min ... 0 ... max */ + if (min < 0.0) { + /* Normalise so that 0 remains 0.0 */ + if (value < 0) { + value = value / (-min); + } else { + if (max == 0.0) { + value = 0.0f; + } else { + value = value / max; + } + } + } else { + /* 0 ... min ... max */ + /* including 0.0 = min */ + if (max == 0.0) { + value = 0.0f; + } else { + value = (value - min) / max; + } + } + + switch (axis) { + case SDL_PEN_AXIS_XTILT: + case SDL_PEN_AXIS_YTILT: + if (peninfo->info.max_tilt > 0.0f) { + value *= peninfo->info.max_tilt; /* normalise to physical max */ + } + break; + + case SDL_PEN_AXIS_ROTATION: + /* normalised to -1..1, so let's convert to degrees */ + value *= 180.0; + value += xpen->rotation_bias; + + /* handle simple over/underflow */ + if (value >= 180.0f) { + value -= 360.0f; + } else if (value < -180.0f) { + value += 360.0f; + } + break; + + default: + break; + } + coords[axis] = value; + } + } +} + +void X11_PenAxesFromValuators(const SDL_Pen *peninfo, + const double *input_values, const unsigned char *mask, const int mask_len, + /* out-mode parameters: */ + float axis_values[SDL_PEN_NUM_AXES]) +{ + const xinput2_pen *pen = (xinput2_pen *)peninfo->deviceinfo; + int i; + + for (i = 0; i < SDL_PEN_NUM_AXES; ++i) { + const int valuator = pen->valuator_for_axis[i]; + if (valuator == SDL_PEN_AXIS_VALUATOR_MISSING || valuator >= mask_len * 8 || !(XIMaskIsSet(mask, valuator))) { + axis_values[i] = 0.0f; + } else { + axis_values[i] = input_values[valuator]; + } + } + xinput2_normalize_pen_axes(peninfo, pen, axis_values); +} + +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11pen.h b/src/video/x11/SDL_x11pen.h new file mode 100644 index 0000000000000..04de528c879e5 --- /dev/null +++ b/src/video/x11/SDL_x11pen.h @@ -0,0 +1,54 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_x11pen_h_ +#define SDL_x11pen_h_ + +#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 + +#include "SDL_x11video.h" +#include "../../events/SDL_pen_c.h" + +/* Pressure-sensitive pen */ + +/* Forward definition for SDL_x11video.h */ +struct SDL_VideoData; + +/* Function definitions */ + +/* Detect XINPUT2 devices that are pens / erasers, or update the list after hotplugging */ +extern void X11_InitPen(SDL_VideoDevice *_this); + +/* Converts XINPUT2 valuators into pen axis information, including normalisation */ +extern void X11_PenAxesFromValuators(const SDL_Pen *pen, + const double *input_values, const unsigned char *mask, const int mask_len, + /* out-mode parameters: */ + float axis_values[SDL_PEN_NUM_AXES]); + +/* Map X11 device ID to pen ID */ +extern int X11_PenIDFromDeviceID(int deviceid); + +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */ + +#endif /* SDL_x11pen_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index fea44c9b86073..67f74d4b0f0a9 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -289,6 +289,7 @@ SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return) SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return) SDL_X11_SYM(Bool,XIGetClientPointer,(Display *a,Window b,int *c),(a,b,c),return) SDL_X11_SYM(Bool,XIWarpPointer,(Display *a,int b,Window c,Window d,double e,double f,int g,int h,double i,double j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(Status,XIGetProperty,(Display *a,int b,Atom c,long d,long e,Bool f, Atom g, Atom *h, int *i, unsigned long *j, unsigned long *k, unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return); #endif /* XRandR support */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index a27e409815fe5..1def27f26c7d3 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -24,16 +24,17 @@ #include /* For getpid() and readlink() */ -#include "../SDL_sysvideo.h" -#include "../SDL_pixels_c.h" #include "../../core/linux/SDL_system_theme.h" +#include "../SDL_pixels_c.h" +#include "../SDL_sysvideo.h" -#include "SDL_x11video.h" #include "SDL_x11framebuffer.h" +#include "SDL_x11pen.h" #include "SDL_x11shape.h" #include "SDL_x11touch.h" -#include "SDL_x11xinput2.h" +#include "SDL_x11video.h" #include "SDL_x11xfixes.h" +#include "SDL_x11xinput2.h" #ifdef SDL_VIDEO_OPENGL_EGL #include "SDL_x11opengles.h" @@ -432,6 +433,10 @@ int X11_VideoInit(SDL_VideoDevice *_this) X11_InitTouch(_this); +#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 + X11_InitPen(_this); +#endif + return 0; } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 459a55a55fc89..1f3e9090dbd76 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -592,8 +592,8 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_ConstrainPopup(window); } SDL_RelativeToGlobalForWindow(window, - window->windowed.x, window->windowed.y, - &win_x, &win_y); + window->windowed.x, window->windowed.y, + &win_x, &win_y); /* Always create this with the window->windowed.* fields; if we're creating a windowed mode window, that's fine. If we're creating a @@ -754,12 +754,20 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_Xinput2SelectTouch(_this, window); - X11_XSelectInput(display, w, - (FocusChangeMask | EnterWindowMask | LeaveWindowMask | - ExposureMask | ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | KeyPressMask | KeyReleaseMask | - PropertyChangeMask | StructureNotifyMask | - KeymapStateMask | fevent)); + { + unsigned int x11_pointer_events = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; + if (X11_Xinput2SelectMouse(_this, window)) { + /* If XInput2 can handle pointer events, we don't track them here */ + x11_pointer_events = 0; + } + + X11_XSelectInput(display, w, + (FocusChangeMask | EnterWindowMask | LeaveWindowMask | ExposureMask | + x11_pointer_events | + KeyPressMask | KeyReleaseMask | + PropertyChangeMask | StructureNotifyMask | + KeymapStateMask | fevent)); + } /* For _ICC_PROFILE. */ X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask); @@ -832,7 +840,8 @@ static int X11_CatchAnyError(Display *d, XErrorEvent *e) return 0; } -enum check_method { +enum check_method +{ COMPARE_POSITION = 1, COMPARE_SIZE = 2, COMPARE_DOUBLE_ATTEMPT = 3, @@ -842,8 +851,8 @@ enum check_method { /* Wait a brief time, or not, to see if the window manager decided to move/resize the window. * Send MOVED and RESIZED window events */ static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, enum check_method method, - int orig_x, int orig_y, int dest_x, int dest_y, - int orig_w, int orig_h, int dest_w, int dest_h) + int orig_x, int orig_y, int dest_x, int dest_y, + int orig_w, int orig_h, int dest_w, int dest_h) { SDL_WindowData *data = window->driverdata; Display *display = data->videodata->display; @@ -934,7 +943,6 @@ static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, e caught_x11_error = SDL_FALSE; } - int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon) { SDL_WindowData *data = window->driverdata; @@ -974,8 +982,8 @@ int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i } X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL, - 32, PropModeReplace, (unsigned char *)propdata, - propsize); + 32, PropModeReplace, (unsigned char *)propdata, + propsize); SDL_free(propdata); if (caught_x11_error) { @@ -1351,7 +1359,6 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) { X11_GetBorderValues(data); } - } void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1485,7 +1492,6 @@ static void X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, S /* Send MOVED/RESIZED event, if needed. Compare with initial position and size. Timeout 1000 */ X11_WaitAndSendWindowEvents(window, 1000, COMPARE_ORIG, orig_x, orig_y, 0, 0, orig_w, orig_h, 0, 0); - } else { X11_SetNetWMState(_this, data->xwindow, window->flags); } diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index eb7f89a747dc9..68eaaf5d889d9 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -22,9 +22,12 @@ #ifdef SDL_VIDEO_DRIVER_X11 +#include "SDL_x11pen.h" #include "SDL_x11video.h" #include "SDL_x11xinput2.h" +#include "../../events/SDL_events_c.h" #include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_pen_c.h" #include "../../events/SDL_touch_c.h" #define MAX_AXIS 16 @@ -74,19 +77,25 @@ static SDL_bool xinput2_version_atleast(const int version, const int wantmajor, return version >= ((wantmajor * 1000) + wantminor); } -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH -static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window) +static SDL_WindowData *xinput2_get_sdlwindowdata(SDL_VideoData *videodata, Window window) { int i; for (i = 0; i < videodata->numwindows; i++) { SDL_WindowData *d = videodata->windowlist[i]; if (d->xwindow == window) { - return d->window; + return d; } } return NULL; } +static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window) +{ + const SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, window); + return windowdata ? windowdata->window : NULL; +} + +#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y) { if (window) { @@ -262,18 +271,51 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, return devinfo; } + +static void xinput2_pen_ensure_window(SDL_VideoDevice *_this, const SDL_Pen *pen, Window window) +{ + /* When "flipping" a Wacom eraser pen, we get an XI_DeviceChanged event + * with the newly-activated pen, but this event is global for the display. + * We won't get a window until the pen starts triggering motion or + * button events, so we instead hook the pen to its window at that point. */ + const SDL_WindowData *windowdata = X11_FindWindow(_this, window); + if (windowdata) { + SDL_SendPenWindowEvent(0, pen->header.id, windowdata->window); + } +} #endif -int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie) +int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) { #ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + if (cookie->extension != xinput2_opcode) { return 0; } switch (cookie->evtype) { + case XI_PropertyEvent: + case XI_DeviceChanged: + { + X11_InitPen(_this); + } break; + + case XI_Enter: + case XI_Leave: + { + const XIEnterEvent *enterev = (const XIEnterEvent *)cookie->data; + const SDL_WindowData *windowdata = X11_FindWindow(_this, enterev->event); + const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(enterev->sourceid)); + SDL_Window *window = (windowdata && (cookie->evtype == XI_Enter)) ? windowdata->window : NULL; + if (pen) { + SDL_SendPenWindowEvent(0, pen->header.id, window); + } + } break; + case XI_RawMotion: { const XIRawEvent *rawev = (const XIRawEvent *)cookie->data; + const SDL_bool is_pen = X11_PenIDFromDeviceID(rawev->sourceid) != SDL_PEN_INVALID; SDL_Mouse *mouse = SDL_GetMouse(); SDL_XInput2DeviceInfo *devinfo; double coords[2]; @@ -281,6 +323,11 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie int i; videodata->global_mouse_changed = SDL_TRUE; + if (is_pen) { + return 0; /* Pens check for XI_Motion instead */ + } + + /* Non-pen: */ if (!mouse->relative_mode || mouse->relative_mode_warp) { return 0; @@ -317,6 +364,7 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie xinput2_remove_device_info(videodata, hierev->info[i].deviceid); } } + X11_InitPen(_this); } break; case XI_RawButtonPress: @@ -326,17 +374,94 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie case XI_RawTouchUpdate: case XI_RawTouchEnd: #endif + { videodata->global_mouse_changed = SDL_TRUE; - break; + } break; -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - /* With multitouch, register to receive XI_Motion (which desctivates MotionNotify), - * so that we can distinguish real mouse motions from synthetic one. */ + case XI_ButtonPress: + case XI_ButtonRelease: + { + const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; + const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid)); + const int button = xev->detail; + const SDL_bool pressed = (cookie->evtype == XI_ButtonPress) ? SDL_TRUE : SDL_FALSE; + + if (pen) { + xinput2_pen_ensure_window(_this, pen, xev->event); + + /* Only report button event; if there was also pen movement / pressure changes, we expect + an XI_Motion event first anyway */ + if (button == 1) { + /* button 1 is the pen tip */ + if (pressed && SDL_PenPerformHitTest()) { + /* Check whether we should handle window resize / move events */ + const SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event); + + if (X11_ProcessHitTest(_this, windowdata, pen->last.x, pen->last.y)) { + SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); + return 1; /* Don't pass on this event */ + } + } + SDL_SendPenTipEvent(0, pen->header.id, + pressed ? SDL_PRESSED : SDL_RELEASED); + } else { + SDL_SendPenButton(0, pen->header.id, + pressed ? SDL_PRESSED : SDL_RELEASED, + button - 1); + } + return 1; + } else { + /* Otherwise assume a regular mouse */ + SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event); + + if (xev->deviceid != xev->sourceid) { + /* Discard events from "Master" devices to avoid duplicates. */ + return 1; + } + + if (pressed) { + X11_HandleButtonPress(_this, windowdata, button, + xev->event_x, xev->event_y, xev->time); + } else { + X11_HandleButtonRelease(_this, windowdata, button); + } + } + } break; + + /* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish + real mouse motions from synthetic ones, for multitouch and pen support. */ case XI_Motion: { const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; + const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid)); +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH int pointer_emulated = (xev->flags & XIPointerEmulated); +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */ + + if (xev->deviceid != xev->sourceid) { + /* Discard events from "Master" devices to avoid duplicates. */ + return 1; + } + + if (pen) { + SDL_PenStatusInfo pen_status; + + pen_status.x = xev->event_x; + pen_status.y = xev->event_y; + + X11_PenAxesFromValuators(pen, + xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len, + &pen_status.axes[0]); + + xinput2_pen_ensure_window(_this, pen, xev->event); + SDL_SendPenMotion(0, pen->header.id, + SDL_TRUE, + &pen_status); + return 1; + } + +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH if (!pointer_emulated) { SDL_Mouse *mouse = SDL_GetMouse(); if (!mouse->relative_mode || mouse->relative_mode_warp) { @@ -347,8 +472,10 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie } } return 1; +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */ } break; +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH case XI_TouchBegin: { const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; @@ -376,10 +503,9 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie SDL_SendTouchMotion(0, xev->sourceid, xev->detail, window, x, y, 1.0); return 1; } break; - -#endif +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */ } -#endif +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */ return 0; } @@ -460,6 +586,38 @@ int X11_Xinput2IsInitialized(void) #endif } +SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window) +{ +#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 + const SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + XIEventMask eventmask; + unsigned char mask[4] = { 0, 0, 0, 0 }; + SDL_WindowData *window_data = (SDL_WindowData *)window->driverdata; + + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + eventmask.deviceid = XIAllDevices; + + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + XISetMask(mask, XI_Enter); + XISetMask(mask, XI_Leave); + /* Hotplugging: */ + XISetMask(mask, XI_DeviceChanged); + XISetMask(mask, XI_HierarchyChanged); + XISetMask(mask, XI_PropertyEvent); /* E.g., when swapping tablet pens */ + + if (X11_XISelectEvents(data->display, + window_data->xwindow, + &eventmask, 1) == Success) { + return SDL_TRUE; + } + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Could not enable XInput2 mouse event handling\n"); +#endif + return SDL_FALSE; +} + int X11_Xinput2IsMultitouchSupported(void) { #ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH diff --git a/src/video/x11/SDL_x11xinput2.h b/src/video/x11/SDL_x11xinput2.h index 2d4573a81a41b..4fea6465b4576 100644 --- a/src/video/x11/SDL_x11xinput2.h +++ b/src/video/x11/SDL_x11xinput2.h @@ -32,11 +32,12 @@ typedef struct XGenericEventCookie XGenericEventCookie; extern void X11_InitXinput2(SDL_VideoDevice *_this); extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this); -extern int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie); +extern int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie); extern int X11_Xinput2IsInitialized(void); extern int X11_Xinput2IsMultitouchSupported(void); extern void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window); extern void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window); extern void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window); +extern SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_x11xinput2_h_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bac37027a2cbd..9171dfd1cd3c6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -328,6 +328,7 @@ add_sdl_test_executable(testgles2 SOURCES testgles2.c) add_sdl_test_executable(testgles2_sdf NEEDS_RESOURCES TESTUTILS SOURCES testgles2_sdf.c) add_sdl_test_executable(testhaptic SOURCES testhaptic.c) add_sdl_test_executable(testhotplug SOURCES testhotplug.c) +add_sdl_test_executable(testpen SOURCES testpen.c) add_sdl_test_executable(testrumble SOURCES testrumble.c) add_sdl_test_executable(testthread NONINTERACTIVE NONINTERACTIVE_TIMEOUT 40 SOURCES testthread.c) add_sdl_test_executable(testiconv NEEDS_RESOURCES TESTUTILS SOURCES testiconv.c) diff --git a/test/testautomation.c b/test/testautomation.c index 9a5bf803db7de..40dda20c49474 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -33,6 +33,7 @@ static SDLTest_TestSuiteReference *testSuites[] = { &mainTestSuite, &mathTestSuite, &mouseTestSuite, + &penTestSuite, &pixelsTestSuite, &platformTestSuite, &propertiesTestSuite, diff --git a/test/testautomation_pen.c b/test/testautomation_pen.c new file mode 100644 index 0000000000000..d200656603964 --- /dev/null +++ b/test/testautomation_pen.c @@ -0,0 +1,1908 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +/** + * Pen test suite + */ + +#define SDL_internal_h_ /* Inhibit dynamic symbol redefinitions that clash with ours */ + +/* ================= System Under Test (SUT) ================== */ +/* Renaming SUT operations to avoid link-time symbol clashes */ +#define SDL_GetPens SDL_SUT_GetPens +#define SDL_GetPenStatus SDL_SUT_GetPenStatus +#define SDL_GetPenFromGUID SDL_SUT_GetPenFromGUID +#define SDL_GetPenGUID SDL_SUT_GetPenGUID +#define SDL_PenConnected SDL_SUT_PenConnected +#define SDL_GetPenName SDL_SUT_GetPenName +#define SDL_GetPenCapabilities SDL_SUT_GetPenCapabilities +#define SDL_GetPenType SDL_SUT_GetPenType + +#define SDL_GetPenPtr SDL_SUT_GetPenPtr +#define SDL_PenModifyBegin SDL_SUT_PenModifyBegin +#define SDL_PenModifyAddCapabilities SDL_SUT_PenModifyAddCapabilities +#define SDL_PenModifyForWacomID SDL_SUT_PenModifyForWacomID +#define SDL_PenUpdateGUIDForWacom SDL_SUT_PenUpdateGUIDForWacom +#define SDL_PenUpdateGUIDForType SDL_SUT_PenUpdateGUIDForType +#define SDL_PenUpdateGUIDForGeneric SDL_SUT_PenUpdateGUIDForGeneric +#define SDL_PenModifyEnd SDL_SUT_PenModifyEnd +#define SDL_PenGCMark SDL_SUT_PenGCMark +#define SDL_PenGCSweep SDL_SUT_PenGCSweep +#define SDL_SendPenMotion SDL_SUT_SendPenMotion +#define SDL_SendPenButton SDL_SUT_SendPenButton +#define SDL_SendPenTipEvent SDL_SUT_SendPenTipEvent +#define SDL_SendPenWindowEvent SDL_SUT_SendPenWindowEvent +#define SDL_PenPerformHitTest SDL_SUT_PenPerformHitTest +#define SDL_PenInit SDL_SUT_PenInit + +/* ================= Mock API ================== */ + +#include +#include +#include +/* For SDL_Window, SDL_Mouse, SDL_MouseID: */ +#include "../src/events/SDL_mouse_c.h" +/* Divert calls to mock mouse API: */ +#define SDL_SendMouseMotion SDL_Mock_SendMouseMotion +#define SDL_SendMouseButton SDL_Mock_SendMouseButton +#define SDL_GetMouse SDL_Mock_GetMouse +#define SDL_MousePositionInWindow SDL_Mock_MousePositionInWindow +#define SDL_SetMouseFocus SDL_Mock_SetMouseFocus + +/* Mock mouse API */ +static int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y); +static int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button); +static SDL_Mouse *SDL_GetMouse(void); +static SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y); +static void SDL_SetMouseFocus(SDL_Window *window); + +/* Import SUT code with macro-renamed function names */ +#define SDL_waylanddyn_h_ /* hack: suppress spurious build problem with libdecor.h on Wayland */ +#include "../src/events/SDL_pen.c" +#include "../src/events/SDL_pen_c.h" + + +/* ================= Internal SDL API Compatibility ================== */ +/* Mock implementations of Pen -> Mouse calls */ +/* Not thread-safe! */ + +static SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y) +{ + return SDL_TRUE; +} + +static int _mouseemu_last_event = 0; +static float _mouseemu_last_x = 0.0f; +static float _mouseemu_last_y = 0.0f; +static int _mouseemu_last_mouseid = 0; +static int _mouseemu_last_button = 0; +static int _mouseemu_last_relative = 0; +static int _mouseemu_last_focus = -1; + +static int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button) +{ + if (mouseID == SDL_PEN_MOUSEID) { + _mouseemu_last_event = (state == SDL_PRESSED) ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; + _mouseemu_last_button = button; + _mouseemu_last_mouseid = mouseID; + } + return 1; +} + +static int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y) +{ + if (mouseID == SDL_PEN_MOUSEID) { + _mouseemu_last_event = SDL_EVENT_MOUSE_MOTION; + _mouseemu_last_x = x; + _mouseemu_last_y = y; + _mouseemu_last_mouseid = mouseID; + _mouseemu_last_relative = relative; + } + return 1; +} + +static SDL_Mouse *SDL_GetMouse(void) +{ + static SDL_Mouse dummy_mouse; + + dummy_mouse.focus = NULL; + dummy_mouse.mouseID = 0; + + return &dummy_mouse; +} + +static void SDL_SetMouseFocus(SDL_Window *window) +{ + _mouseemu_last_focus = window ? 1 : 0; +} + +/* ================= Test Case Support ================== */ + +#define PEN_NUM_TEST_IDS 8 + +/* Helper functions */ + +/* Iterate over all pens to find index for pen ID, otherwise -1 */ +static int _pen_iterationFindsPenIDAt(SDL_PenID needle) +{ + int i; + int num_pens = -1; + + SDL_PenID *pens = SDL_GetPens(&num_pens); + /* Check for (a) consistency and (b) ability to handle NULL parameter */ + SDL_PenID *pens2 = SDL_GetPens(NULL); + + SDLTest_AssertCheck(num_pens >= 0, + "SDL_GetPens() yielded %d pens", num_pens); + SDLTest_AssertCheck(pens[num_pens] == 0, + "SDL_GetPens() not 0 terminated (num_pens = %d)", num_pens); + SDLTest_AssertCheck(pens2[num_pens] == 0, + "SDL_GetPens(NULL) not 0 terminated (num_pens = %d)", num_pens); + + for (i = 0; i < num_pens; ++i) { + SDLTest_AssertCheck(pens[i] == pens2[i], + "SDL_GetPens(&i) and SDL_GetPens(NULL) disagree at index %d/%d", i, num_pens); + SDLTest_AssertCheck(pens[i] != SDL_PEN_INVALID, + "Invalid pen ID %08lx at index %d/%d after SDL_GetPens()", (unsigned long) pens[i], i, num_pens); + } + SDL_free(pens2); + + for (i = 0; pens[i]; ++i) { + SDL_PenID pen_id = pens[i]; + + SDLTest_AssertCheck(pen_id != SDL_PEN_INVALID, + "Invalid pen ID %08lx at index %d/%d after SDL_GetPens()", (unsigned long) pen_id, i, num_pens); + if (pen_id == needle) { + SDL_free(pens); + return i; + } + } + SDL_free(pens); + return -1; +} + +/* Retrieve number of pens and sanity-check SDL_GetPens() */ +static int +_num_pens(void) +{ + int num_pens = -1; + SDL_PenID *pens = SDL_GetPens(&num_pens); + SDLTest_AssertCheck(pens != NULL, + "SDL_GetPens() => NULL"); + SDLTest_AssertCheck(num_pens >= 0, + "SDL_GetPens() reports %d pens", num_pens); + SDLTest_AssertCheck(pens[num_pens] == 0, + "SDL_GetPens()[%d] != 0", num_pens); + SDL_free(pens); + return num_pens; +} + +/* Assert number of pens is as expected */ +static void _AssertCheck_num_pens(int expected, char *location) +{ + int num_pens = _num_pens(); + SDLTest_AssertCheck(expected == num_pens, + "Expected SDL_GetPens() =>count = %d, actual = %d: %s", expected, num_pens, location); +} + +/* ---------------------------------------- */ +/* Test device deallocation */ + +typedef struct /* Collection of pen (de)allocation information */ +{ + unsigned int deallocated_id_flags; /* ith bits set to 1 if the ith test_id is deallocated */ + unsigned int deallocated_deviceinfo_flags; /* ith bits set to 1 if deviceinfo as *int with value i was deallocated */ + SDL_PenID ids[PEN_NUM_TEST_IDS]; + SDL_GUID guids[PEN_NUM_TEST_IDS]; + SDL_Window *window; + int num_ids; + int initial_pen_count; +} pen_testdata; + +/* SDL_PenGCSweep(): callback for tracking pen deallocation */ +static void _pen_testdata_callback(Uint32 deviceid, void *deviceinfo, void *tracker_ref) +{ + pen_testdata *tracker = (pen_testdata *)tracker_ref; + int offset = -1; + int i; + + for (i = 0; i < tracker->num_ids; ++i) { + if (deviceid == tracker->ids[i]) { + tracker->deallocated_id_flags |= (1 << i); + } + } + + SDLTest_AssertCheck(deviceinfo != NULL, + "Device %lu has deviceinfo", + (unsigned long) deviceid); + offset = *((int *)deviceinfo); + SDLTest_AssertCheck(offset >= 0 && offset <= 31, + "Device %lu has well-formed deviceinfo %d", + (unsigned long) deviceid, offset); + tracker->deallocated_deviceinfo_flags |= 1 << offset; + SDL_free(deviceinfo); +} + +/* GC Sweep tracking: update "tracker->deallocated_id_flags" and "tracker->deallocated_deviceinfo_flags" to record deallocations */ +static void _pen_trackGCSweep(pen_testdata *tracker) +{ + tracker->deallocated_id_flags = 0; + tracker->deallocated_deviceinfo_flags = 0; + SDL_PenGCSweep(tracker, _pen_testdata_callback); +} + +/* Finds a number of unused pen IDs (does not allocate them). Also initialises GUIDs. */ +static void _pen_unusedIDs(pen_testdata *tracker, int count) +{ + static int guidmod = 0; /* Ensure uniqueness as long as we use no more than 256 test pens */ + Uint32 synthetic_penid = 1000u; + int index = 0; + + tracker->num_ids = count; + SDLTest_AssertCheck(count < PEN_NUM_TEST_IDS, "Test setup: Valid number of test IDs requested: %d", (int)count); + + while (count--) { + int k; + + while (SDL_GetPenPtr(synthetic_penid)) { + ++synthetic_penid; + } + tracker->ids[index] = synthetic_penid; + for (k = 0; k < 15; ++k) { + tracker->guids[index].data[k] = (16 * k) + index; + } + tracker->guids[index].data[15] = ++guidmod; + + ++synthetic_penid; + ++index; + } +} + +#define DEVICEINFO_UNCHANGED -17 + +/* Allocate deviceinfo for pen */ +static void _pen_setDeviceinfo(SDL_Pen *pen, int deviceinfo) +{ + if (deviceinfo == DEVICEINFO_UNCHANGED) { + SDLTest_AssertCheck(pen->deviceinfo != NULL, + "pen->deviceinfo was already set for %p (%lu), as expected", + pen, (unsigned long) pen->header.id); + } else { + int *data = (int *)SDL_malloc(sizeof(int)); + *data = deviceinfo; + + SDLTest_AssertCheck(pen->deviceinfo == NULL, + "pen->deviceinfo was NULL for %p (%lu) when requesting deviceinfo %d", + pen, (unsigned long) pen->header.id, deviceinfo); + + pen->deviceinfo = data; + } + SDL_PenModifyEnd(pen, SDL_TRUE); +} + +/* ---------------------------------------- */ +/* Back up and restore device information */ + +typedef struct deviceinfo_backup +{ + Uint32 deviceid; + void *deviceinfo; + struct deviceinfo_backup *next; +} deviceinfo_backup; + +/* SDL_PenGCSweep(): Helper callback for collecting all deviceinfo records */ +static void _pen_accumulate_gc_sweep(Uint32 deviceid, void *deviceinfo, void *backup_ref) +{ + deviceinfo_backup **db_ref = (deviceinfo_backup **)backup_ref; + deviceinfo_backup *next = *db_ref; + + *db_ref = SDL_calloc(sizeof(deviceinfo_backup), 1); + (*db_ref)->deviceid = deviceid; + (*db_ref)->deviceinfo = deviceinfo; + (*db_ref)->next = next; +} + +/* SDL_PenGCSweep(): Helper callback that must never be called */ +static void _pen_assert_impossible(Uint32 deviceid, void *deviceinfo, void *backup_ref) +{ + SDLTest_AssertCheck(0, "Deallocation for deviceid %lu during enableAndRestore: not expected", + (unsigned long) deviceid); +} + +/* Disable all pens and store their status */ +static deviceinfo_backup *_pen_disableAndBackup(void) +{ + deviceinfo_backup *backup = NULL; + + SDL_PenGCMark(); + SDL_PenGCSweep(&backup, _pen_accumulate_gc_sweep); + return backup; +} + +/* Restore all pens to their previous status */ +static void _pen_enableAndRestore(deviceinfo_backup *backup, int test_marksweep) +{ + if (test_marksweep) { + SDL_PenGCMark(); + } + while (backup) { + SDL_Pen *disabledpen = SDL_GetPenPtr(backup->deviceid); + deviceinfo_backup *next = backup->next; + + SDL_PenModifyEnd(SDL_PenModifyBegin(disabledpen->header.id), + SDL_TRUE); + disabledpen->deviceinfo = backup->deviceinfo; + + SDL_free(backup); + backup = next; + } + if (test_marksweep) { + SDL_PenGCSweep(NULL, _pen_assert_impossible); + } +} + +static struct SDL_Window _test_window = { 0 }; + +/* ---------------------------------------- */ +/* Default set-up and tear down routines */ + +/* Back up existing pens, allocate fresh ones but don't assign them yet */ +static deviceinfo_backup *_setup_test(pen_testdata *ptest, int pens_for_testing) +{ + int i; + deviceinfo_backup *backup; + + /* Get number of pens */ + SDL_free(SDL_GetPens(&ptest->initial_pen_count)); + + /* Provide fake window for window enter/exit simulation */ + _test_window.id = 0x7e57da7a; + _test_window.w = 1600; + _test_window.h = 1200; + ptest->window = &_test_window; + + /* Grab unused pen IDs for testing */ + _pen_unusedIDs(ptest, pens_for_testing); + for (i = 0; i < pens_for_testing; ++i) { + int index = _pen_iterationFindsPenIDAt(ptest->ids[i]); + SDLTest_AssertCheck(-1 == index, + "Registered PenID(%lu) since index %d == -1", + (unsigned long) ptest->ids[i], index); + } + + /* Remove existing pens, but back up */ + backup = _pen_disableAndBackup(); + + _AssertCheck_num_pens(0, "after disabling and backing up all current pens"); + SDLTest_AssertPass("Removed existing pens"); + + return backup; +} + +static void _teardown_test_general(pen_testdata *ptest, deviceinfo_backup *backup, int with_gc_test) +{ + /* Restore previously existing pens */ + _pen_enableAndRestore(backup, with_gc_test); + + /* validate */ + SDLTest_AssertPass("Restored pens to pre-test state"); + _AssertCheck_num_pens(ptest->initial_pen_count, "after restoring all initial pens"); +} + +static void _teardown_test(pen_testdata *ptest, deviceinfo_backup *backup) +{ + _teardown_test_general(ptest, backup, 0); +} + +static void _teardown_test_with_gc(pen_testdata *ptest, deviceinfo_backup *backup) +{ + _teardown_test_general(ptest, backup, 1); +} + +/* ---------------------------------------- */ +/* Pen simulation */ + +#define SIMPEN_ACTION_DONE 0 +#define SIMPEN_ACTION_MOVE_X 1 +#define SIMPEN_ACTION_MOVE_Y 2 +#define SIMPEN_ACTION_AXIS 3 +#define SIMPEN_ACTION_MOTION_EVENT 4 /* epxlicit motion event */ +#define SIMPEN_ACTION_MOTION_EVENT_S 5 /* send motion event but expect it to be suppressed */ +#define SIMPEN_ACTION_PRESS 6 /* implicit update event */ +#define SIMPEN_ACTION_RELEASE 7 /* implicit update event */ +#define SIMPEN_ACTION_DOWN 8 /* implicit update event */ +#define SIMPEN_ACTION_UP 9 /* implicit update event */ +#define SIMPEN_ACTION_ERASER_MODE 10 + +/* Individual action in pen simulation script */ +typedef struct simulated_pen_action +{ + int type; + int pen_index; /* index into the list of simulated pens */ + int index; /* button or axis number, if needed */ + float update; /* x,y; for AXIS, update[0] is the updated axis */ +} simulated_pen_action; + +static simulated_pen_action _simpen_event(int type, int pen_index, int index, float v, int line_nr) +{ + simulated_pen_action action; + action.type = type; + action.pen_index = pen_index; + action.index = index; + action.update = v; + + /* Sanity check-- turned out to be necessary */ + if ((type == SIMPEN_ACTION_PRESS || type == SIMPEN_ACTION_RELEASE) && index == 0) { + SDL_Log("Error: SIMPEN_EVENT_BUTTON must have button > 0 (first button has number 1!), in line %d!", line_nr); + exit(1); + } + return action; +} + +/* STEP is passed in later (C macros use dynamic scoping) */ + +#define SIMPEN_DONE() \ + STEP _simpen_event(SIMPEN_ACTION_DONE, 0, 0, 0.0f, __LINE__) +#define SIMPEN_MOVE(pen_index, x, y) \ + STEP _simpen_event(SIMPEN_ACTION_MOVE_X, (pen_index), 0, (x), __LINE__); \ + STEP _simpen_event(SIMPEN_ACTION_MOVE_Y, (pen_index), 0, (y), __LINE__) + +#define SIMPEN_AXIS(pen_index, axis, y) \ + STEP _simpen_event(SIMPEN_ACTION_AXIS, (pen_index), (axis), (y), __LINE__) + +#define SIMPEN_EVENT_MOTION(pen_index) \ + STEP _simpen_event(SIMPEN_ACTION_MOTION_EVENT, (pen_index), 0, 0.0f, __LINE__) + +#define SIMPEN_EVENT_MOTION_SUPPRESSED(pen_index) \ + STEP _simpen_event(SIMPEN_ACTION_MOTION_EVENT_S, (pen_index), 0, 0.0f, __LINE__) + +#define SIMPEN_EVENT_BUTTON(pen_index, push, button) \ + STEP _simpen_event((push) ? SIMPEN_ACTION_PRESS : SIMPEN_ACTION_RELEASE, (pen_index), (button), 0.0f, __LINE__) + +#define SIMPEN_EVENT_TIP(pen_index, touch, tip) \ + STEP _simpen_event((touch) ? SIMPEN_ACTION_DOWN : SIMPEN_ACTION_UP, (pen_index), tip, 0.0f, __LINE__) + +#define SIMPEN_SET_ERASER(pen_index, eraser_mode) \ + STEP _simpen_event(SIMPEN_ACTION_ERASER_MODE, (pen_index), eraser_mode, 0.0f, __LINE__) + +static void +_pen_dump(const char *prefix, SDL_Pen *pen) +{ + int i; + char *axes_str; + + if (!pen) { + SDL_Log("(NULL pen)"); + return; + } + + axes_str = SDL_strdup(""); + for (i = 0; i < SDL_PEN_NUM_AXES; ++i) { + char *old_axes_str = axes_str; + SDL_asprintf(&axes_str, "%s\t%f", old_axes_str, pen->last.axes[i]); + SDL_free(old_axes_str); + } + SDL_Log("%s: pen %lu (%s): status=%04lx, flags=%lx, x,y=(%f, %f) axes = %s", + prefix, + (unsigned long) pen->header.id, + pen->name, + (unsigned long) pen->last.buttons, + (unsigned long) pen->header.flags, + pen->last.x, pen->last.y, + axes_str); + SDL_free(axes_str); +} + +/* Runs until the next event has been issued or we are done and returns pointer to it. + Returns NULL once we hit SIMPEN_ACTION_DONE. + Updates simulated_pens accordingly. There must be as many simulated_pens as the highest pen_index used in + any of the "steps". + Also validates the internal state with expectations (via SDL_GetPenStatus()) and updates the, but does not poll SDL events. */ +static simulated_pen_action * +_pen_simulate(simulated_pen_action *steps, int *step_counter, SDL_Pen *simulated_pens, int num_pens) +{ + SDL_bool done = SDL_FALSE; + SDL_bool dump_pens = SDL_FALSE; + unsigned int mask; + int pen_nr; + + do { + simulated_pen_action step = steps[*step_counter]; + SDL_Pen *simpen = &simulated_pens[step.pen_index]; + + if (step.pen_index >= num_pens) { + SDLTest_AssertCheck(0, + "Unexpected pen index %d at step %d, action %d", step.pen_index, *step_counter, step.type); + return NULL; + } + + switch (step.type) { + case SIMPEN_ACTION_DONE: + SDLTest_AssertPass("SIMPEN_ACTION_DONE"); + return NULL; + + case SIMPEN_ACTION_MOVE_X: + SDLTest_AssertPass("SIMPEN_ACTION_MOVE_X [pen %d] : y <- %f", step.pen_index, step.update); + simpen->last.x = step.update; + break; + + case SIMPEN_ACTION_MOVE_Y: + SDLTest_AssertPass("SIMPEN_ACTION_MOVE_Y [pen %d] : x <- %f", step.pen_index, step.update); + simpen->last.y = step.update; + break; + + case SIMPEN_ACTION_AXIS: + SDLTest_AssertPass("SIMPEN_ACTION_AXIS [pen %d] : axis[%d] <- %f", step.pen_index, step.index, step.update); + simpen->last.axes[step.index] = step.update; + break; + + case SIMPEN_ACTION_MOTION_EVENT: + done = SDL_TRUE; + SDLTest_AssertCheck(SDL_SendPenMotion(0, simpen->header.id, SDL_TRUE, + &simpen->last), + "SIMPEN_ACTION_MOTION_EVENT [pen %d]", step.pen_index); + break; + + case SIMPEN_ACTION_MOTION_EVENT_S: + SDLTest_AssertCheck(!SDL_SendPenMotion(0, simpen->header.id, SDL_TRUE, + &simpen->last), + "SIMPEN_ACTION_MOTION_EVENT_SUPPRESSED [pen %d]", step.pen_index); + break; + + case SIMPEN_ACTION_PRESS: + mask = (1 << (step.index - 1)); + simpen->last.buttons |= mask; + SDLTest_AssertCheck(SDL_SendPenButton(0, simpen->header.id, SDL_PRESSED, step.index), + "SIMPEN_ACTION_PRESS [pen %d]: button %d (mask %x)", step.pen_index, step.index, mask); + done = SDL_TRUE; + break; + + case SIMPEN_ACTION_RELEASE: + mask = ~(1 << (step.index - 1)); + simpen->last.buttons &= mask; + SDLTest_AssertCheck(SDL_SendPenButton(0, simpen->header.id, SDL_RELEASED, step.index), + "SIMPEN_ACTION_RELEASE [pen %d]: button %d (mask %x)", step.pen_index, step.index, mask); + done = SDL_TRUE; + break; + + case SIMPEN_ACTION_DOWN: + simpen->last.buttons |= SDL_PEN_DOWN_MASK; + SDLTest_AssertCheck(SDL_SendPenTipEvent(0, simpen->header.id, SDL_PRESSED), + "SIMPEN_ACTION_DOWN [pen %d]: (mask %lx)", step.pen_index, SDL_PEN_DOWN_MASK); + done = SDL_TRUE; + break; + + case SIMPEN_ACTION_UP: + simpen->last.buttons &= ~SDL_PEN_DOWN_MASK; + SDLTest_AssertCheck(SDL_SendPenTipEvent(0, simpen->header.id, SDL_RELEASED), + "SIMPEN_ACTION_UP [pen %d]: (mask %lx)", step.pen_index, ~SDL_PEN_DOWN_MASK); + done = SDL_TRUE; + break; + + case SIMPEN_ACTION_ERASER_MODE: { + Uint32 pmask; + SDL_Pen *pen = SDL_PenModifyBegin(simpen->header.id); + + if (step.index) { + pmask = SDL_PEN_ERASER_MASK; + } else { + pmask = SDL_PEN_INK_MASK; + } + + SDL_PenModifyAddCapabilities(pen, pmask); + SDL_PenModifyEnd(pen, SDL_TRUE); + + simpen->header.flags &= ~(SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK); + simpen->header.flags |= pmask; + break; + } + + default: + SDLTest_AssertCheck(0, + "Unexpected pen simulation action %d", step.type); + return NULL; + } + ++(*step_counter); + } while (!done); + + for (pen_nr = 0; pen_nr < num_pens; ++pen_nr) { + SDL_Pen *simpen = &simulated_pens[pen_nr]; + float x = -1.0f, y = -1.0f; + float axes[SDL_PEN_NUM_AXES]; + Uint32 actual_flags = SDL_GetPenStatus(simpen->header.id, &x, &y, axes, SDL_PEN_NUM_AXES); + int i; + + if (simpen->last.x != x || simpen->last.y != y) { + SDLTest_AssertCheck(0, "Coordinate mismatch in pen %d", pen_nr); + dump_pens = SDL_TRUE; + } + if ((actual_flags & ~(SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK)) != (simpen->last.buttons & ~(SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK))) { + SDLTest_AssertCheck(0, "Status mismatch in pen %d (reported: %08x)", pen_nr, (unsigned int)actual_flags); + dump_pens = SDL_TRUE; + } + if ((actual_flags & (SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK)) != (simpen->header.flags & (SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK))) { + SDLTest_AssertCheck(0, "Flags mismatch in pen %d (reported: %08x)", pen_nr, (unsigned int)actual_flags); + dump_pens = SDL_TRUE; + } + for (i = 0; i < SDL_PEN_NUM_AXES; ++i) { + if (axes[i] != simpen->last.axes[i]) { + SDLTest_AssertCheck(0, "Axis %d mismatch in pen %d", pen_nr, i); + dump_pens = SDL_TRUE; + } + } + } + + if (dump_pens) { + int i; + for (i = 0; i < num_pens; ++i) { + SDL_Log("==== pen #%d", i); + _pen_dump("expect", simulated_pens + i); + _pen_dump("actual", SDL_GetPenPtr(simulated_pens[i].header.id)); + } + } + + return &steps[(*step_counter) - 1]; +} + +/* Init simulated_pens with suitable initial state */ +static void +_pen_simulate_init(pen_testdata *ptest, SDL_Pen *simulated_pens, int num_pens) +{ + int i; + for (i = 0; i < num_pens; ++i) { + simulated_pens[i] = *SDL_GetPenPtr(ptest->ids[i]); + } +} + +/* ---------------------------------------- */ +/* Other helper functions */ + +/* "standard" pen registration process */ +static SDL_Pen * +_pen_register(SDL_PenID penid, SDL_GUID guid, char *name, Uint32 flags) +{ + SDL_Pen *pen = SDL_PenModifyBegin(penid); + pen->guid = guid; + SDL_strlcpy(pen->name, name, SDL_PEN_MAX_NAME); + SDL_PenModifyAddCapabilities(pen, flags); + return pen; +} + +/* Test whether EXPECTED and ACTUAL of type TY agree. Their C format string must be FMT. + MESSAGE is a string with one format string, passed as ARG0. */ +#define SDLTest_AssertEq1(TY, FMT, EXPECTED, ACTUAL, MESSAGE, ARG0) \ + { \ + TY _t_expect = (EXPECTED); \ + TY _t_actual = (ACTUAL); \ + SDLTest_AssertCheck(_t_expect == _t_actual, "L%d: " MESSAGE ": expected " #EXPECTED " = " FMT ", actual = " FMT, __LINE__, (ARG0), _t_expect, _t_actual); \ + } + +/* ================= Test Case Implementation ================== */ + +/** + * @brief Check basic pen device introduction and iteration, as well as basic queries + * + * @sa SDL_GetPens, SDL_GetPenName, SDL_GetPenCapabilities + */ +static int +pen_iteration(void *arg) +{ + pen_testdata ptest; + int i; + char long_pen_name[SDL_PEN_MAX_NAME + 10]; + const char *name; + deviceinfo_backup *backup; + + /* Check initial pens */ + SDL_PumpEvents(); + SDLTest_AssertPass("SDL_GetPens() => count = %d", _num_pens()); + + /* Grab unused pen IDs for testing */ + backup = _setup_test(&ptest, 3); /* validates that we have zero pens */ + + /* Re-run GC, track deallocations */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _AssertCheck_num_pens(0, "after second GC pass"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0, "No unexpected device deallocations"); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0, "No unexpected deviceinfo deallocations"); + SDLTest_AssertPass("Validated that GC on empty pen set is idempotent"); + + /* Add three pens, validate */ + SDL_PenGCMark(); + + SDL_memset(long_pen_name, 'x', sizeof(long_pen_name)); /* Include pen name that is too long */ + long_pen_name[sizeof(long_pen_name) - 1] = 0; + + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "pen 0", + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 16); + _pen_setDeviceinfo(_pen_register(ptest.ids[2], ptest.guids[2], long_pen_name, + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK), + 20); + _pen_setDeviceinfo(_pen_register(ptest.ids[1], ptest.guids[1], "pen 1", + SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT_MASK), + 24); + _pen_trackGCSweep(&ptest); + + _AssertCheck_num_pens(3, "after allocating three pens"); + + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0, "No unexpected device deallocations"); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0, "No unexpected deviceinfo deallocations"); + + for (i = 0; i < 3; ++i) { + /* Check that all pens are accounted for */ + int index = _pen_iterationFindsPenIDAt(ptest.ids[i]); + SDLTest_AssertCheck(-1 != index, "Found PenID(%lu)", (unsigned long) ptest.ids[i]); + } + SDLTest_AssertPass("Validated that all three pens are indexable"); + + /* Check pen properties */ + SDLTest_AssertCheck(0 == SDL_strcmp("pen 0", SDL_GetPenName(ptest.ids[0])), + "Pen #0 name"); + SDLTest_AssertCheck((SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK) == SDL_GetPenCapabilities(ptest.ids[0], NULL), + "Pen #0 capabilities"); + + SDLTest_AssertCheck(0 == SDL_strcmp("pen 1", SDL_GetPenName(ptest.ids[1])), + "Pen #1 name"); + SDLTest_AssertCheck((SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT_MASK) == SDL_GetPenCapabilities(ptest.ids[1], NULL), + "Pen #1 capabilities"); + + name = SDL_GetPenName(ptest.ids[2]); + SDLTest_AssertCheck(SDL_PEN_MAX_NAME - 1 == SDL_strlen(name), + "Pen #2 name length"); + SDLTest_AssertCheck(0 == SDL_memcmp(name, long_pen_name, SDL_PEN_MAX_NAME - 1), + "Pen #2 name contents"); + SDLTest_AssertCheck((SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK) == SDL_GetPenCapabilities(ptest.ids[2], NULL), + "Pen #2 capabilities"); + SDLTest_AssertPass("Pen registration and basic queries"); + + /* Re-run GC, track deallocations */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _AssertCheck_num_pens(0, "after third GC pass"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0x07, + "No unexpected device deallocation : %08x", ptest.deallocated_id_flags); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0x01110000, + "No unexpected deviceinfo deallocation : %08x ", ptest.deallocated_deviceinfo_flags); + SDLTest_AssertPass("Validated that GC on empty pen set is idempotent"); + + /* tear down and finish */ + _teardown_test(&ptest, backup); + return TEST_COMPLETED; +} + +static void +_expect_pen_attached(SDL_PenID penid) +{ + SDLTest_AssertCheck(-1 != _pen_iterationFindsPenIDAt(penid), + "Found PenID(%lu)", (unsigned long) penid); + SDLTest_AssertCheck(SDL_PenConnected(penid), + "Pen %lu was attached, as expected", (unsigned long) penid); +} + +static void +_expect_pen_detached(SDL_PenID penid) +{ + SDLTest_AssertCheck(-1 == _pen_iterationFindsPenIDAt(penid), + "Did not find PenID(%lu), as expected", (unsigned long) penid); + SDLTest_AssertCheck(!SDL_PenConnected(penid), + "Pen %lu was detached, as expected", (unsigned long) penid); +} + +#define ATTACHED(i) (1 << (i)) + +static void +_expect_pens_attached_or_detached(SDL_PenID *pen_ids, int ids, Uint32 mask) +{ + int i; + int attached_count = 0; + for (i = 0; i < ids; ++i) { + if (mask & (1 << i)) { + ++attached_count; + _expect_pen_attached(pen_ids[i]); + } else { + _expect_pen_detached(pen_ids[i]); + } + } + _AssertCheck_num_pens(attached_count, "While checking attached/detached status"); +} + +/** + * @brief Check pen device hotplugging + * + * @sa SDL_GetPens, SDL_GetPenName, SDL_GetPenCapabilities, SDL_PenConnected + */ +static int +pen_hotplugging(void *arg) +{ + pen_testdata ptest; + deviceinfo_backup *backup = _setup_test(&ptest, 3); + SDL_GUID checkguid; + + /* Add two pens */ + SDL_PenGCMark(); + + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "pen 0", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 16); + _pen_setDeviceinfo(_pen_register(ptest.ids[2], ptest.guids[2], "pen 2", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 24); + _pen_trackGCSweep(&ptest); + + _AssertCheck_num_pens(2, "after allocating two pens (pass 1)"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0, "No unexpected device deallocation (pass 1)"); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0, "No unexpected deviceinfo deallocation (pass 1)"); + + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(0) | ATTACHED(2)); + SDLTest_AssertPass("Validated hotplugging (pass 1): attachmend of two pens"); + + /* Introduce pen #1, remove pen #2 */ + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "pen 0", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + DEVICEINFO_UNCHANGED); + _pen_setDeviceinfo(_pen_register(ptest.ids[1], ptest.guids[1], "pen 1", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 20); + _pen_trackGCSweep(&ptest); + + _AssertCheck_num_pens(2, "after allocating two pens (pass 2)"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0x04, "No unexpected device deallocation (pass 2): %x", ptest.deallocated_id_flags); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0x01000000, "No unexpected deviceinfo deallocation (pass 2): %x", ptest.deallocated_deviceinfo_flags); + + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(0) | ATTACHED(1)); + SDLTest_AssertPass("Validated hotplugging (pass 2): unplug one, attach another"); + + /* Return to previous state (#0 and #2 attached) */ + SDL_PenGCMark(); + + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "pen 0", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT), + DEVICEINFO_UNCHANGED); + _pen_setDeviceinfo(_pen_register(ptest.ids[2], ptest.guids[2], "pen 2", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 24); + _pen_trackGCSweep(&ptest); + + _AssertCheck_num_pens(2, "after allocating two pens (pass 3)"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0x02, "No unexpected device deallocation (pass 3)"); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0x00100000, "No unexpected deviceinfo deallocation (pass 3)"); + + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(0) | ATTACHED(2)); + SDLTest_AssertPass("Validated hotplugging (pass 3): return to state of pass 1"); + + /* Introduce pen #1, remove pen #0 */ + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[1], ptest.guids[1], "pen 1", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 20); + _pen_setDeviceinfo(_pen_register(ptest.ids[2], ptest.guids[2], "pen 2", SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + DEVICEINFO_UNCHANGED); + _pen_trackGCSweep(&ptest); + + _AssertCheck_num_pens(2, "after allocating two pens (pass 4)"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0x01, "No unexpected device deallocation (pass 4): %x", ptest.deallocated_id_flags); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0x00010000, "No unexpected deviceinfo deallocation (pass 4): %x", ptest.deallocated_deviceinfo_flags); + + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(1) | ATTACHED(2)); + SDLTest_AssertPass("Validated hotplugging (pass 5)"); + + /* Check detached pen */ + SDLTest_AssertCheck(0 == SDL_strcmp("pen 0", SDL_GetPenName(ptest.ids[0])), + "Pen #0 name"); + checkguid = SDL_GetPenGUID(ptest.ids[0]); + SDLTest_AssertCheck(0 == SDL_memcmp(ptest.guids[0].data, checkguid.data, sizeof(ptest.guids[0].data)), + "Pen #0 guid"); + SDLTest_AssertCheck((SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT) == SDL_GetPenCapabilities(ptest.ids[0], NULL), + "Pen #0 capabilities"); + SDLTest_AssertPass("Validated that detached pens retained name, GUID, axis info after pass 5"); + + /* Individually detach #1 dn #2 */ + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(1) | ATTACHED(2)); + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[1]), SDL_FALSE); + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(2)); + + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[2]), SDL_FALSE); + _expect_pens_attached_or_detached(ptest.ids, 3, 0); + + SDLTest_AssertPass("Validated individual hotplugging (pass 6)"); + + /* Individually attach all */ + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[2]), SDL_TRUE); + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(2)); + + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[0]), SDL_TRUE); + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(0) | ATTACHED(2)); + + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[1]), SDL_TRUE); + _expect_pens_attached_or_detached(ptest.ids, 3, ATTACHED(0) | ATTACHED(1) | ATTACHED(2)); + SDLTest_AssertPass("Validated individual hotplugging (pass 7)"); + + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _AssertCheck_num_pens(0, "after hotplugging test (cleanup)"); + SDLTest_AssertCheck(ptest.deallocated_id_flags == 0x06, "No unexpected device deallocation (cleanup): %x", ptest.deallocated_id_flags); + SDLTest_AssertCheck(ptest.deallocated_deviceinfo_flags == 0x01100000, "No unexpected deviceinfo deallocation (pass 4): %x", ptest.deallocated_deviceinfo_flags); + + _teardown_test_with_gc(&ptest, backup); + + return TEST_COMPLETED; +} + +/** + * @brief Check pen device GUID handling + * + * @sa SDL_GetPenGUID + */ +static int +pen_GUIDs(void *arg) +{ + int i; + char *names[4] = { "pen 0", "pen 1", "pen 2", "pen 3" }; + pen_testdata ptest; + deviceinfo_backup *backup; + + backup = _setup_test(&ptest, 4); + + /* Define four pens */ + SDL_PenGCMark(); + for (i = 0; i < 4; ++i) { + _pen_setDeviceinfo(_pen_register(ptest.ids[i], ptest.guids[i], names[i], SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + 20); + } + _pen_trackGCSweep(&ptest); + + /* Detach pens 0 and 2 */ + SDL_PenGCMark(); + for (i = 1; i < 4; i += 2) { + _pen_setDeviceinfo(_pen_register(ptest.ids[i], ptest.guids[i], names[i], SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK), + DEVICEINFO_UNCHANGED); + } + _pen_trackGCSweep(&ptest); + + for (i = 0; i < 4; ++i) { + SDLTest_AssertCheck(ptest.ids[i] == SDL_GetPenFromGUID(ptest.guids[i]), + "GUID search succeeded for %d", i); + } + + /* detach all */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + + _teardown_test(&ptest, backup); + SDLTest_AssertPass("Pen ID lookup by GUID"); + + return TEST_COMPLETED; +} + +/** + * @brief Check pen device button reporting + * + */ +static int +pen_buttonReporting(void *arg) +{ + int i; + int button_nr, pen_nr; + pen_testdata ptest; + SDL_Event event; + SDL_PenStatusInfo update; + float axes[SDL_PEN_NUM_AXES + 1]; + const float expected_x[2] = { 10.0f, 20.0f }; + const float expected_y[2] = { 11.0f, 21.0f }; + const Uint32 all_axes = SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK | SDL_PEN_AXIS_SLIDER_MASK; + + /* Register pen */ + deviceinfo_backup *backup = _setup_test(&ptest, 2); + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "test pen", + SDL_PEN_INK_MASK | all_axes), + 20); + _pen_setDeviceinfo(_pen_register(ptest.ids[1], ptest.guids[1], "test eraser", + SDL_PEN_ERASER_MASK | all_axes), + 24); + _pen_trackGCSweep(&ptest); + + /* Position mouse suitably before we start */ + for (i = 0; i <= SDL_PEN_NUM_AXES; ++i) { + axes[i] = 0.0625f * i; /* initialise with numbers that can be represented precisely in IEEE 754 and + are > 0.0f and <= 1.0f */ + } + + /* Let pens enter the test window */ + SDL_SendPenWindowEvent(0, ptest.ids[0], ptest.window); + SDL_SendPenWindowEvent(0, ptest.ids[1], ptest.window); + + update.x = expected_x[0]; + update.y = expected_y[0]; + SDL_memcpy(update.axes, axes, sizeof(float) * SDL_PEN_NUM_AXES); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + update.x = expected_x[1]; + update.y = expected_y[1]; + SDL_memcpy(update.axes, axes + 1, sizeof(float) * SDL_PEN_NUM_AXES); + SDL_SendPenMotion(0, ptest.ids[1], SDL_TRUE, &update); + + while (SDL_PollEvent(&event)) + ; /* Flush event queue */ + + /* Trigger pen tip events for PEN_DOWN */ + SDLTest_AssertPass("Touch pens to surface"); + + for (pen_nr = 0; pen_nr < 2; ++pen_nr) { + float *expected_axes = axes + pen_nr; + SDL_bool found_event = SDL_FALSE; + Uint16 pen_state = 0x0000 | SDL_PEN_DOWN_MASK; + Uint8 tip = SDL_PEN_TIP_INK; + + if (pen_nr == 1) { + pen_state |= SDL_PEN_ERASER_MASK; + tip = SDL_PEN_TIP_ERASER; + } + + SDL_SendPenTipEvent(0, ptest.ids[pen_nr], SDL_PRESSED); + + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_PEN_DOWN) { + SDLTest_AssertCheck(event.ptip.which == ptest.ids[pen_nr], + "Received SDL_EVENT_PEN_DOWN from correct pen"); + SDLTest_AssertCheck(event.ptip.tip == (pen_nr == 0)? SDL_PEN_TIP_INK : SDL_PEN_TIP_ERASER, + "Received SDL_EVENT_PEN_DOWN for correct tip"); + SDLTest_AssertCheck(event.ptip.state == SDL_PRESSED, + "Received SDL_EVENT_PEN_DOWN but and marked SDL_PRESSED"); + SDLTest_AssertCheck(event.ptip.tip == tip, + "Received tip %x but expected %x", event.ptip.tip, tip); + SDLTest_AssertCheck(event.ptip.pen_state == pen_state, + "Received SDL_EVENT_PEN_DOWN, and state %04x == %04x (expected)", + event.pbutton.pen_state, pen_state); + SDLTest_AssertCheck((event.ptip.x == expected_x[pen_nr]) && (event.ptip.y == expected_y[pen_nr]), + "Received SDL_EVENT_PEN_DOWN event at correct coordinates: (%f, %f) vs (%f, %f) (expected)", + event.pbutton.x, event.pbutton.y, expected_x[pen_nr], expected_y[pen_nr]); + SDLTest_AssertCheck(0 == SDL_memcmp(expected_axes, event.pbutton.axes, sizeof(float) * SDL_PEN_NUM_AXES), + "Received SDL_EVENT_PEN_DOWN event with correct axis values"); + found_event = SDL_TRUE; + } + SDLTest_AssertCheck(found_event, + "Received the expected SDL_EVENT_PEN_DOWN event"); + } + } + + SDLTest_AssertPass("Pen and eraser set up for button testing"); + + /* Actual tests start: pen, then eraser */ + for (pen_nr = 0; pen_nr < 2; ++pen_nr) { + Uint16 pen_state = 0x0000 | SDL_PEN_DOWN_MASK; + float *expected_axes = axes + pen_nr; + + if (pen_nr == 1) { + pen_state |= SDL_PEN_ERASER_MASK; + } + for (button_nr = 1; button_nr <= 8; ++button_nr) { + SDL_bool found_event = SDL_FALSE; + pen_state |= (1 << (button_nr - 1)); + + SDL_SendPenButton(0, ptest.ids[pen_nr], SDL_PRESSED, button_nr); + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_PEN_BUTTON_DOWN) { + SDLTest_AssertCheck(event.pbutton.which == ptest.ids[pen_nr], + "Received SDL_EVENT_PEN_BUTTON_DOWN from correct pen"); + SDLTest_AssertCheck(event.pbutton.button == button_nr, + "Received SDL_EVENT_PEN_BUTTON_DOWN from correct button"); + SDLTest_AssertCheck(event.pbutton.state == SDL_PRESSED, + "Received SDL_EVENT_PEN_BUTTON_DOWN but and marked SDL_PRESSED"); + SDLTest_AssertCheck(event.pbutton.pen_state == pen_state, + "Received SDL_EVENT_PEN_BUTTON_DOWN, and state %04x == %04x (expected)", + event.pbutton.pen_state, pen_state); + SDLTest_AssertCheck((event.pbutton.x == expected_x[pen_nr]) && (event.pbutton.y == expected_y[pen_nr]), + "Received SDL_EVENT_PEN_BUTTON_DOWN event at correct coordinates: (%f, %f) vs (%f, %f) (expected)", + event.pbutton.x, event.pbutton.y, expected_x[pen_nr], expected_y[pen_nr]); + SDLTest_AssertCheck(0 == SDL_memcmp(expected_axes, event.pbutton.axes, sizeof(float) * SDL_PEN_NUM_AXES), + "Received SDL_EVENT_PEN_BUTTON_DOWN event with correct axis values"); + if (0 != SDL_memcmp(expected_axes, event.pbutton.axes, sizeof(float) * SDL_PEN_NUM_AXES)) { + int ax; + for (ax = 0; ax < SDL_PEN_NUM_AXES; ++ax) { + SDL_Log("\tax %d\t%.5f\t%.5f expected (equal=%d)", + ax, + event.pbutton.axes[ax], expected_axes[ax], + event.pbutton.axes[ax] == expected_axes[ax]); + } + } + found_event = SDL_TRUE; + } + } + SDLTest_AssertCheck(found_event, + "Received the expected SDL_EVENT_PEN_BUTTON_DOWN event"); + } + } + SDLTest_AssertPass("Pressed all buttons"); + + /* Release every other button */ + for (pen_nr = 0; pen_nr < 2; ++pen_nr) { + Uint16 pen_state = 0x00ff | SDL_PEN_DOWN_MASK; /* 8 buttons pressed */ + float *expected_axes = axes + pen_nr; + + if (pen_nr == 1) { + pen_state |= SDL_PEN_ERASER_MASK; + } + for (button_nr = pen_nr + 1; button_nr <= 8; button_nr += 2) { + SDL_bool found_event = SDL_FALSE; + pen_state &= ~(1 << (button_nr - 1)); + + SDL_SendPenButton(0, ptest.ids[pen_nr], SDL_RELEASED, button_nr); + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_PEN_BUTTON_UP) { + SDLTest_AssertCheck(event.pbutton.which == ptest.ids[pen_nr], + "Received SDL_EVENT_PEN_BUTTON_UP from correct pen"); + SDLTest_AssertCheck(event.pbutton.button == button_nr, + "Received SDL_EVENT_PEN_BUTTON_UP from correct button"); + SDLTest_AssertCheck(event.pbutton.state == SDL_RELEASED, + "Received SDL_EVENT_PEN_BUTTON_UP and is marked SDL_RELEASED"); + SDLTest_AssertCheck(event.pbutton.pen_state == pen_state, + "Received SDL_EVENT_PEN_BUTTON_UP, and state %04x == %04x (expected)", + event.pbutton.pen_state, pen_state); + SDLTest_AssertCheck((event.pbutton.x == expected_x[pen_nr]) && (event.pbutton.y == expected_y[pen_nr]), + "Received SDL_EVENT_PEN_BUTTON_UP event at correct coordinates"); + SDLTest_AssertCheck(0 == SDL_memcmp(expected_axes, event.pbutton.axes, sizeof(float) * SDL_PEN_NUM_AXES), + "Received SDL_EVENT_PEN_BUTTON_UP event with correct axis values"); + found_event = SDL_TRUE; + } + } + SDLTest_AssertCheck(found_event, + "Received the expected SDL_EVENT_PEN_BUTTON_UP event"); + } + } + SDLTest_AssertPass("Released every other button"); + + /* Trigger pen tip events for PEN_UP */ + SDLTest_AssertPass("Remove pens from surface"); + + for (pen_nr = 0; pen_nr < 2; ++pen_nr) { + float *expected_axes = axes + pen_nr; + SDL_bool found_event = SDL_FALSE; + Uint16 pen_state = 0x0000; + Uint8 tip = SDL_PEN_TIP_INK; + + if (pen_nr == 1) { + pen_state |= SDL_PEN_ERASER_MASK; + tip = SDL_PEN_TIP_ERASER; + } + + SDL_SendPenTipEvent(0, ptest.ids[pen_nr], SDL_RELEASED); + + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_PEN_UP) { + SDLTest_AssertCheck(event.ptip.which == ptest.ids[pen_nr], + "Received SDL_EVENT_PEN_UP from correct pen"); + SDLTest_AssertCheck(event.ptip.tip == (pen_nr == 0)? SDL_PEN_TIP_INK : SDL_PEN_TIP_ERASER, + "Received SDL_EVENT_PEN_UP for correct tip"); + SDLTest_AssertCheck(event.ptip.state == SDL_RELEASED, + "Received SDL_EVENT_PEN_UP but and marked SDL_RELEASED"); + SDLTest_AssertCheck(event.ptip.tip == tip, + "Received tip %x but expected %x", event.ptip.tip, tip); + SDLTest_AssertCheck((event.ptip.pen_state & 0xff00) == (pen_state & 0xff00), + "Received SDL_EVENT_PEN_UP, and state %04x == %04x (expected)", + event.pbutton.pen_state, pen_state); + SDLTest_AssertCheck((event.ptip.x == expected_x[pen_nr]) && (event.ptip.y == expected_y[pen_nr]), + "Received SDL_EVENT_PEN_UP event at correct coordinates: (%f, %f) vs (%f, %f) (expected)", + event.pbutton.x, event.pbutton.y, expected_x[pen_nr], expected_y[pen_nr]); + SDLTest_AssertCheck(0 == SDL_memcmp(expected_axes, event.pbutton.axes, sizeof(float) * SDL_PEN_NUM_AXES), + "Received SDL_EVENT_PEN_UP event with correct axis values"); + found_event = SDL_TRUE; + } + SDLTest_AssertCheck(found_event, + "Received the expected SDL_EVENT_PEN_UP event"); + } + } + + /* Cleanup */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _teardown_test(&ptest, backup); + + return TEST_COMPLETED; +} + +/** + * @brief Check pen device movement and axis update reporting + * + * Also tests SDL_GetPenStatus for agreement with the most recently reported events + * + * @sa SDL_GetPenStatus + */ +static int +pen_movementAndAxes(void *arg) +{ + pen_testdata ptest; + SDL_Event event; +#define MAX_STEPS 80 + /* Pen simulation */ + simulated_pen_action steps[MAX_STEPS]; + size_t num_steps = 0; + + SDL_Pen simulated_pens[2]; + int sim_pc = 0; + simulated_pen_action *last_action; + + /* Register pen */ + deviceinfo_backup *backup = _setup_test(&ptest, 2); + + /* Pen simulation program */ +#define STEP steps[num_steps++] = + + /* #1: Check basic reporting */ + /* Hover eraser, tilt axes */ + SIMPEN_MOVE(0, 30.0f, 31.0f); + SIMPEN_AXIS(0, SDL_PEN_AXIS_PRESSURE, 0.0f); + SIMPEN_AXIS(0, SDL_PEN_AXIS_XTILT, 22.5f); + SIMPEN_AXIS(0, SDL_PEN_AXIS_YTILT, 45.0f); + SIMPEN_EVENT_MOTION(0); + + /* #2: Check that motion events without motion aren't reported */ + SIMPEN_EVENT_MOTION_SUPPRESSED(0); + SIMPEN_EVENT_MOTION_SUPPRESSED(0); + + /* #3: Check multiple pens being reported */ + /* Move pen and touch surface, don't tilt */ + SIMPEN_MOVE(1, 40.0f, 41.0f); + SIMPEN_AXIS(1, SDL_PEN_AXIS_PRESSURE, 0.25f); + SIMPEN_EVENT_MOTION(1); + + /* $4: Multi-buttons */ + /* Press eraser buttons */ + SIMPEN_EVENT_TIP(0, "down", SDL_PEN_TIP_ERASER); + SIMPEN_EVENT_BUTTON(0, "push", 2); + SIMPEN_EVENT_BUTTON(0, "push", 1); + SIMPEN_EVENT_BUTTON(0, 0, 2); /* release again */ + SIMPEN_EVENT_BUTTON(0, "push", 3); + + /* #5: Check move + button actions connecting */ + /* Move and tilt pen, press some pen buttons */ + SIMPEN_MOVE(1, 3.0f, 8.0f); + SIMPEN_AXIS(1, SDL_PEN_AXIS_PRESSURE, 0.5f); + SIMPEN_AXIS(1, SDL_PEN_AXIS_XTILT, -21.0f); + SIMPEN_AXIS(1, SDL_PEN_AXIS_YTILT, -25.0f); + SIMPEN_EVENT_MOTION(1); + SIMPEN_EVENT_BUTTON(1, "push", 2); + SIMPEN_EVENT_TIP(1, "down", SDL_PEN_TIP_INK); + + /* #6: Check nonterference between pens */ + /* Eraser releases buttons */ + SIMPEN_EVENT_BUTTON(0, 0, 1); + SIMPEN_EVENT_TIP(0, 0, SDL_PEN_TIP_ERASER); + + /* #7: Press-move-release action */ + /* Eraser press-move-release */ + SIMPEN_EVENT_BUTTON(0, "push", 1); + SIMPEN_MOVE(0, 99.0f, 88.0f); + SIMPEN_AXIS(0, SDL_PEN_AXIS_PRESSURE, 0.625f); + SIMPEN_EVENT_MOTION(0); + SIMPEN_MOVE(0, 44.5f, 42.25f); + SIMPEN_EVENT_MOTION(0); + SIMPEN_EVENT_BUTTON(0, 0, 1); + + /* #8: Intertwining button release actions some more */ + /* Pen releases button */ + SIMPEN_EVENT_BUTTON(1, 0, 2); + SIMPEN_EVENT_TIP(1, 0, SDL_PEN_TIP_INK); + + /* Push one more pen button, then release all ereaser buttons */ + SIMPEN_EVENT_TIP(1, "down", SDL_PEN_TIP_INK); + SIMPEN_EVENT_BUTTON(0, 0, 2); + SIMPEN_EVENT_BUTTON(0, 0, 3); + + /* Lift up pen, flip it so it becomes an eraser, and touch it again */ + SIMPEN_EVENT_TIP(1, 0, SDL_PEN_TIP_INK); + SIMPEN_SET_ERASER(1, 1); + SIMPEN_EVENT_TIP(1, "push", SDL_PEN_TIP_ERASER); + + /* And back again */ + SIMPEN_EVENT_TIP(1, 0, SDL_PEN_TIP_ERASER); + SIMPEN_SET_ERASER(1, 0); + SIMPEN_EVENT_TIP(1, "push", SDL_PEN_TIP_INK); + + /* #9: Suppress move on unsupported axis */ + SIMPEN_AXIS(1, SDL_PEN_AXIS_DISTANCE, 0.25f); + SIMPEN_EVENT_MOTION_SUPPRESSED(0); + + SIMPEN_DONE(); +#undef STEP + /* End of pen simulation program */ + + SDLTest_AssertCheck(num_steps < MAX_STEPS, "Pen simulation program does not exceed buffer size"); +#undef MAX_STEPS + + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "test eraser", + SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK), + 20); + _pen_setDeviceinfo(_pen_register(ptest.ids[1], ptest.guids[1], "test pen", + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK), + 24); + _pen_trackGCSweep(&ptest); + SDL_SendPenWindowEvent(0, ptest.ids[0], ptest.window); + SDL_SendPenWindowEvent(0, ptest.ids[1], ptest.window); + while (SDL_PollEvent(&event)) + ; /* Flush event queue */ + SDLTest_AssertPass("Pen and eraser set up for testing"); + + _pen_simulate_init(&ptest, simulated_pens, 2); + /* Simulate pen movements */ + while ((last_action = _pen_simulate(steps, &sim_pc, &simulated_pens[0], 2))) { + int attempts = 0; + SDL_Pen *simpen = &simulated_pens[last_action->pen_index]; + SDL_PenID reported_which = -1; + float reported_x = -1.0f, reported_y = -1.0f; + float *reported_axes = NULL; + Uint32 reported_pen_state = 0; + Uint32 expected_pen_state = simpen->header.flags & SDL_PEN_ERASER_MASK; + SDL_bool dump_pens = SDL_FALSE; + + do { + SDL_PumpEvents(); + SDL_PollEvent(&event); + if (++attempts > 10000) { + SDLTest_AssertCheck(0, "Never got the anticipated event"); + return TEST_ABORTED; + } + } while (event.type != SDL_EVENT_PEN_DOWN + && event.type != SDL_EVENT_PEN_UP + && event.type != SDL_EVENT_PEN_MOTION + && event.type != SDL_EVENT_PEN_BUTTON_UP + && event.type != SDL_EVENT_PEN_BUTTON_DOWN); /* skip boring events */ + + expected_pen_state |= simpen->last.buttons; + + SDLTest_AssertCheck(0 != event.type, + "Received the anticipated event"); + + switch (last_action->type) { + case SIMPEN_ACTION_MOTION_EVENT: + SDLTest_AssertCheck(event.type == SDL_EVENT_PEN_MOTION, "Expected pen motion event (but got 0x%lx)", (unsigned long) event.type); + reported_which = event.pmotion.which; + reported_x = event.pmotion.x; + reported_y = event.pmotion.y; + reported_pen_state = event.pmotion.pen_state; + reported_axes = &event.pmotion.axes[0]; + break; + + case SIMPEN_ACTION_PRESS: + SDLTest_AssertCheck(event.type == SDL_EVENT_PEN_BUTTON_DOWN, "Expected PENBUTTONDOWN event (but got 0x%lx)", (unsigned long) event.type); + SDLTest_AssertCheck(event.pbutton.state == SDL_PRESSED, "Expected PRESSED button"); + /* Fall through */ + case SIMPEN_ACTION_RELEASE: + if (last_action->type == SIMPEN_ACTION_RELEASE) { + SDLTest_AssertCheck(event.type == SDL_EVENT_PEN_BUTTON_UP, "Expected PENBUTTONUP event (but got 0x%lx)", (unsigned long) event.type); + SDLTest_AssertCheck(event.pbutton.state == SDL_RELEASED, "Expected RELEASED button"); + } + SDLTest_AssertCheck(event.pbutton.button == last_action->index, "Expected button %d, but got %d", + last_action->index, event.pbutton.button); + reported_which = event.pbutton.which; + reported_x = event.pbutton.x; + reported_y = event.pbutton.y; + reported_pen_state = event.pbutton.pen_state; + reported_axes = &event.pbutton.axes[0]; + break; + + case SIMPEN_ACTION_DOWN: + SDLTest_AssertCheck(event.type == SDL_EVENT_PEN_DOWN, "Expected PENBUTTONDOWN event (but got 0x%lx)", (unsigned long) event.type); + SDLTest_AssertCheck(event.ptip.state == SDL_PRESSED, "Expected PRESSED button"); + /* Fall through */ + case SIMPEN_ACTION_UP: + if (last_action->type == SIMPEN_ACTION_UP) { + SDLTest_AssertCheck(event.type == SDL_EVENT_PEN_UP, "Expected PENBUTTONUP event (but got 0x%lx)", (unsigned long) event.type); + SDLTest_AssertCheck(event.ptip.state == SDL_RELEASED, "Expected RELEASED button"); + } + SDLTest_AssertCheck(event.ptip.tip == last_action->index, "Expected tip %d, but got %d", + last_action->index, event.ptip.tip); + reported_which = event.ptip.which; + reported_x = event.ptip.x; + reported_y = event.ptip.y; + reported_pen_state = event.ptip.pen_state; + reported_axes = &event.ptip.axes[0]; + break; + + case SIMPEN_ACTION_ERASER_MODE: + break; + + default: + SDLTest_AssertCheck(0, "Error in pen simulator: unexpected action %d", last_action->type); + return TEST_ABORTED; + } + + if (reported_which != simpen->header.id) { + dump_pens = SDL_TRUE; + SDLTest_AssertCheck(0, "Expected report for pen %lu but got report for pen %lu", + (unsigned long) simpen->header.id, + (unsigned long) reported_which); + } + if (reported_x != simpen->last.x || reported_y != simpen->last.y) { + dump_pens = SDL_TRUE; + SDLTest_AssertCheck(0, "Mismatch in pen coordinates"); + } + if (reported_x != simpen->last.x || reported_y != simpen->last.y) { + dump_pens = SDL_TRUE; + SDLTest_AssertCheck(0, "Mismatch in pen coordinates"); + } + if (reported_pen_state != expected_pen_state) { + dump_pens = SDL_TRUE; + SDLTest_AssertCheck(0, "Mismatch in pen state: %lx vs %lx (expected)", + (unsigned long) reported_pen_state, + (unsigned long) expected_pen_state); + } + if (0 != SDL_memcmp(reported_axes, simpen->last.axes, sizeof(float) * SDL_PEN_NUM_AXES)) { + dump_pens = SDL_TRUE; + SDLTest_AssertCheck(0, "Mismatch in axes"); + } + + if (dump_pens) { + SDL_Log("----- Pen #%d:", last_action->pen_index); + _pen_dump("expect", simpen); + _pen_dump("actual", SDL_GetPenPtr(simpen->header.id)); + } + } + SDLTest_AssertPass("Pen and eraser move and report events correctly and independently"); + + /* Cleanup */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _teardown_test(&ptest, backup); + return TEST_COMPLETED; +} + +static void +_expect_pen_config(SDL_PenID penid, + SDL_GUID expected_guid, + SDL_bool expected_attached, + char *expected_name, + int expected_type, + int expected_num_buttons, + float expected_max_tilt, + int expected_axes) +{ + SDL_PenCapabilityInfo actual_info = { 0 }; + const char *actual_name = SDL_GetPenName(penid); + + if (penid == SDL_PEN_INVALID) { + SDLTest_Assert(0, "Invalid pen ID"); + return; + } + + SDLTest_AssertEq1(int, "%d", 0, SDL_GUIDCompare(expected_guid, SDL_GetPenGUID(penid)), + "Pen %lu guid equality", (unsigned long) penid); + + SDLTest_AssertCheck(0 == SDL_strcmp(expected_name, actual_name), + "Expected name='%s' vs actual='%s'", expected_name, actual_name); + + SDLTest_AssertEq1(int, "%d", expected_attached, SDL_PenConnected(penid), + "Pen %lu is attached", (unsigned long) penid); + SDLTest_AssertEq1(int, "%d", expected_type, SDL_GetPenType(penid), + "Pen %lu type", (unsigned long) penid); + SDLTest_AssertEq1(int, "%x", expected_axes, SDL_GetPenCapabilities(penid, &actual_info), + "Pen %lu axis flags", (unsigned long) penid); + SDLTest_AssertEq1(int, "%d", expected_num_buttons, actual_info.num_buttons, + "Pen %lu number of buttons", (unsigned long) penid); + SDLTest_AssertEq1(float, "%f", expected_max_tilt, actual_info.max_tilt, + "Pen %lu max tilt", (unsigned long) penid); +} + +/** + * @brief Check backend pen iniitalisation and pen meta-information + * + * @sa SDL_GetPenCapabilities, SDL_PenAxisInfo + */ +static int +pen_initAndInfo(void *arg) +{ + pen_testdata ptest; + SDL_Pen *pen; + Uint32 mask; + char strbuf[SDL_PEN_MAX_NAME]; + + /* Init */ + deviceinfo_backup *backup = _setup_test(&ptest, 7); + + /* Register default pen */ + _expect_pens_attached_or_detached(ptest.ids, 7, 0); + + /* Register completely default pen */ + pen = SDL_PenModifyBegin(ptest.ids[0]); + SDL_memcpy(pen->guid.data, ptest.guids[0].data, sizeof(ptest.guids[0].data)); + SDL_PenModifyEnd(pen, SDL_TRUE); + + SDL_snprintf(strbuf, sizeof(strbuf), + "Pen %lu", (unsigned long) ptest.ids[0]); + _expect_pen_config(ptest.ids[0], ptest.guids[0], SDL_TRUE, + strbuf, SDL_PEN_TYPE_PEN, SDL_PEN_INFO_UNKNOWN, 0.0f, + SDL_PEN_INK_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0)); + SDLTest_AssertPass("Pass #1: default pen"); + + /* Register mostly-default pen with buttons and custom name */ + pen = SDL_PenModifyBegin(ptest.ids[1]); + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_PRESSURE_MASK); + SDL_memcpy(pen->guid.data, ptest.guids[1].data, sizeof(ptest.guids[1].data)); + SDL_strlcpy(strbuf, "My special test pen", SDL_PEN_MAX_NAME); + SDL_strlcpy(pen->name, strbuf, SDL_PEN_MAX_NAME); + pen->info.num_buttons = 7; + SDL_PenModifyEnd(pen, SDL_TRUE); + + _expect_pen_config(ptest.ids[1], ptest.guids[1], SDL_TRUE, + strbuf, SDL_PEN_TYPE_PEN, 7, 0.0f, + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1)); + SDLTest_AssertPass("Pass #2: default pen with button and name info"); + + /* Register eraser with default name, but keep initially detached */ + pen = SDL_PenModifyBegin(ptest.ids[2]); + SDL_memcpy(pen->guid.data, ptest.guids[2].data, sizeof(ptest.guids[2].data)); + pen->type = SDL_PEN_TYPE_ERASER; + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK); + SDL_PenModifyEnd(pen, SDL_FALSE); + + SDL_snprintf(strbuf, sizeof(strbuf), + "Eraser %lu", (unsigned long) ptest.ids[2]); + _expect_pen_config(ptest.ids[2], ptest.guids[2], SDL_FALSE, + strbuf, SDL_PEN_TYPE_ERASER, SDL_PEN_INFO_UNKNOWN, SDL_PEN_INFO_UNKNOWN, + SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1)); + /* now make available */ + SDL_PenModifyEnd(SDL_PenModifyBegin(ptest.ids[2]), SDL_TRUE); + _expect_pen_config(ptest.ids[2], ptest.guids[2], SDL_TRUE, + strbuf, SDL_PEN_TYPE_ERASER, SDL_PEN_INFO_UNKNOWN, SDL_PEN_INFO_UNKNOWN, + SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1) | ATTACHED(2)); + SDLTest_AssertPass("Pass #3: eraser-type pen initially detached, then attached"); + + /* Abort pen registration */ + pen = SDL_PenModifyBegin(ptest.ids[3]); + SDL_memcpy(pen->guid.data, ptest.guids[3].data, sizeof(ptest.guids[3].data)); + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK); + pen->type = SDL_PEN_TYPE_NONE; + SDL_PenModifyEnd(pen, SDL_TRUE); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1) | ATTACHED(2)); + SDLTest_AssertCheck(NULL == SDL_GetPenName(ptest.ids[3]), "Pen with aborted registration remains unknown"); + SDLTest_AssertPass("Pass #4: aborted pen registration"); + + /* Brush with custom axes */ + pen = SDL_PenModifyBegin(ptest.ids[4]); + SDL_memcpy(pen->guid.data, ptest.guids[4].data, sizeof(ptest.guids[4].data)); + SDL_strlcpy(pen->name, "Testish Brush", SDL_PEN_MAX_NAME); + pen->type = SDL_PEN_TYPE_BRUSH; + pen->info.num_buttons = 1; + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_ROTATION_MASK); + pen->info.max_tilt = 72.5f; + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_XTILT_MASK); + SDL_PenModifyAddCapabilities(pen, SDL_PEN_AXIS_PRESSURE_MASK); + SDL_PenModifyEnd(pen, SDL_TRUE); + _expect_pen_config(ptest.ids[4], ptest.guids[4], SDL_TRUE, + "Testish Brush", SDL_PEN_TYPE_BRUSH, 1, 72.5f, + SDL_PEN_INK_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_ROTATION_MASK | SDL_PEN_AXIS_PRESSURE_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1) | ATTACHED(2) | ATTACHED(4)); + SDLTest_AssertPass("Pass #5: brush-type pen with unusual axis layout"); + + /* Wacom airbrush pen */ + { + const Uint32 wacom_type_id = 0x0912; + const Uint32 wacom_serial_id = 0xa0b1c2d3; + SDL_GUID guid = { + { 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 } + }; + guid.data[0] = (wacom_serial_id >> 0) & 0xff; + guid.data[1] = (wacom_serial_id >> 8) & 0xff; + guid.data[2] = (wacom_serial_id >> 16) & 0xff; + guid.data[3] = (wacom_serial_id >> 24) & 0xff; + guid.data[4] = (wacom_type_id >> 0) & 0xff; + guid.data[5] = (wacom_type_id >> 8) & 0xff; + guid.data[6] = (wacom_type_id >> 16) & 0xff; + guid.data[7] = (wacom_type_id >> 24) & 0xff; + + pen = SDL_PenModifyBegin(ptest.ids[5]); + SDL_PenModifyForWacomID(pen, wacom_type_id, &mask); + SDL_PenUpdateGUIDForWacom(&pen->guid, wacom_type_id, wacom_serial_id); + SDL_PenModifyAddCapabilities(pen, mask); + SDL_PenModifyEnd(pen, SDL_TRUE); + _expect_pen_config(ptest.ids[5], guid, SDL_TRUE, + "Wacom Airbrush Pen", SDL_PEN_TYPE_AIRBRUSH, 1, 64.0f, /* Max tilt angle */ + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK); + _expect_pens_attached_or_detached(ptest.ids, 7, ATTACHED(0) | ATTACHED(1) | ATTACHED(2) | ATTACHED(4) | ATTACHED(5)); + } + SDLTest_AssertPass("Pass #6: wacom airbrush pen"); + + /* Cleanup */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _teardown_test(&ptest, backup); + return TEST_COMPLETED; +} + +#define SET_POS(update, xpos, ypos) \ + (update).x = (xpos); \ + (update).y = (ypos); + +static void +_penmouse_expect_button(int type, int button) +{ + SDL_bool press = type == SDL_PRESSED; + SDLTest_AssertCheck((press ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP) == _mouseemu_last_event, + "Mouse button %s: %x", + (press ? "press" : "release"), _mouseemu_last_event); + SDLTest_AssertCheck(button == _mouseemu_last_button, + "Observed the expected simulated button: %d", _mouseemu_last_button); + SDLTest_AssertCheck(SDL_PEN_MOUSEID == _mouseemu_last_mouseid, + "Observed the expected mouse ID: 0x%x", _mouseemu_last_mouseid); + + _mouseemu_last_event = 0; +} + +/** + * @brief Check pen device mouse emulation and event suppression without SDL_HINT_PEN_DELAY_MOUSE_BUTTON + * + * Since we include SDL_pen.c, we link it against our own mock implementations of SDL_PSendMouseButton + * and SDL_SendMouseMotion; see tehere for details. + */ +static int +pen_mouseEmulation(void *arg) +{ + pen_testdata ptest; + SDL_Event event; + int i; + SDL_PenStatusInfo update; + deviceinfo_backup *backup; + + pen_delay_mouse_button_mode = 0; + pen_mouse_emulation_mode = PEN_MOUSE_EMULATE; /* to trigger our own SDL_SendMouseButton */ + + /* Register pen */ + backup = _setup_test(&ptest, 1); + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "testpen", + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT | SDL_PEN_AXIS_YTILT), + 20); + _pen_trackGCSweep(&ptest); + + /* Move pen into window */ + SDL_SendPenWindowEvent(0, ptest.ids[0], ptest.window); + + /* Initialise pen location */ + SDL_memset(update.axes, 0, sizeof(update.axes)); + SET_POS(update, 100.0f, 100.0f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + while (SDL_PollEvent(&event)) + ; /* Flush event queue */ + + /* Test motion forwarding */ + _mouseemu_last_event = 0; + SET_POS(update, 121.25f, 110.75f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + SDLTest_AssertCheck(SDL_EVENT_MOUSE_MOTION == _mouseemu_last_event, + "Mouse motion event: %d", _mouseemu_last_event); + SDLTest_AssertCheck(121.25f == _mouseemu_last_x && 110.75f == _mouseemu_last_y, + "Motion to correct position: %f,%f", _mouseemu_last_x, _mouseemu_last_y); + SDLTest_AssertCheck(SDL_PEN_MOUSEID == _mouseemu_last_mouseid, + "Observed the expected mouse ID: 0x%x", _mouseemu_last_mouseid); + SDLTest_AssertCheck(0 == _mouseemu_last_relative, + "Absolute motion event"); + SDLTest_AssertPass("Motion emulation"); + + /* Test redundant motion report suppression */ + _mouseemu_last_event = 0; + + SET_POS(update, 121.25f, 110.75f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + + SET_POS(update, 121.25f, 110.75f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + + update.axes[0] = 1.0f; + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + + SET_POS(update, 121.25f, 110.75f); + update.axes[0] = 0.0f; + update.axes[1] = 0.75f; + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Redundant mouse motion suppressed: %d", _mouseemu_last_event); + SDLTest_AssertPass("Redundant motion suppression"); + + /* Test button press reporting */ + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_PRESSED); + _penmouse_expect_button(SDL_PRESSED, 1); + + for (i = 1; i <= 3; ++i) { + SDL_SendPenButton(0, ptest.ids[0], SDL_PRESSED, i); + _penmouse_expect_button(SDL_PRESSED, i + 1); + } + SDLTest_AssertPass("Button press mouse emulation"); + + /* Test button release reporting */ + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_RELEASED); + _penmouse_expect_button(SDL_RELEASED, 1); + + for (i = 1; i <= 3; ++i) { + SDL_SendPenButton(0, ptest.ids[0], SDL_RELEASED, i); + _penmouse_expect_button(SDL_RELEASED, i + 1); + } + SDLTest_AssertPass("Button release mouse emulation"); + + /* Cleanup */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _teardown_test(&ptest, backup); + return TEST_COMPLETED; +} + +/** + * @brief Check pen device mouse emulation when SDL_HINT_PEN_DELAY_MOUSE_BUTTON is enabled (default) + */ +static int +pen_mouseEmulationDelayed(void *arg) +{ + pen_testdata ptest; + SDL_Event event; + int i; + SDL_PenStatusInfo update; + deviceinfo_backup *backup; + + pen_delay_mouse_button_mode = 1; + pen_mouse_emulation_mode = PEN_MOUSE_EMULATE; /* to trigger our own SDL_SendMouseButton */ + + /* Register pen */ + backup = _setup_test(&ptest, 1); + SDL_PenGCMark(); + _pen_setDeviceinfo(_pen_register(ptest.ids[0], ptest.guids[0], "testpen", + SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT | SDL_PEN_AXIS_YTILT), + 20); + _pen_trackGCSweep(&ptest); + + /* Move pen into window */ + SDL_SendPenWindowEvent(0, ptest.ids[0], ptest.window); + + /* Initialise pen location */ + SDL_memset(update.axes, 0, sizeof(update.axes)); + SET_POS(update, 100.0f, 100.0f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + while (SDL_PollEvent(&event)) + ; /* Flush event queue */ + + /* Test motion forwarding */ + _mouseemu_last_event = 0; + SET_POS(update, 121.25f, 110.75f); + SDL_SendPenMotion(0, ptest.ids[0], SDL_TRUE, &update); + SDLTest_AssertCheck(SDL_EVENT_MOUSE_MOTION == _mouseemu_last_event, + "Mouse motion event: %d", _mouseemu_last_event); + SDLTest_AssertCheck(121.25f == _mouseemu_last_x && 110.75f == _mouseemu_last_y, + "Motion to correct position: %f,%f", _mouseemu_last_x, _mouseemu_last_y); + SDLTest_AssertCheck(SDL_PEN_MOUSEID == _mouseemu_last_mouseid, + "Observed the expected mouse ID: 0x%x", _mouseemu_last_mouseid); + SDLTest_AssertCheck(0 == _mouseemu_last_relative, + "Absolute motion event"); + SDLTest_AssertPass("Motion emulation"); + _mouseemu_last_event = 0; + + /* Test button press reporting */ + for (i = 1; i <= 2; ++i) { + SDL_SendPenButton(0, ptest.ids[0], SDL_PRESSED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button press suppressed: %d", _mouseemu_last_event); + SDL_SendPenButton(0, ptest.ids[0], SDL_RELEASED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button release suppressed: %d", _mouseemu_last_event); + } + + /* Touch surface */ + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_PRESSED); + _penmouse_expect_button(SDL_PRESSED, 1); + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_RELEASED); + _penmouse_expect_button(SDL_RELEASED, 1); + + /* Test button press reporting, releasing extra button AFTER lifting pen */ + for (i = 1; i <= 2; ++i) { + SDL_SendPenButton(0, ptest.ids[0], SDL_PRESSED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button press suppressed (A.1): %d", _mouseemu_last_event); + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_PRESSED); + _penmouse_expect_button(SDL_PRESSED, i + 1); + + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_RELEASED); + _penmouse_expect_button(SDL_RELEASED, i + 1); + + SDL_SendPenButton(0, ptest.ids[0], SDL_RELEASED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button press suppressed (A.2): %d", _mouseemu_last_event); + } + SDLTest_AssertPass("Delayed button press mouse emulation, touching without releasing button"); + + /* Test button press reporting, releasing extra button BEFORE lifting pen */ + for (i = 1; i <= 2; ++i) { + SDL_SendPenButton(0, ptest.ids[0], SDL_PRESSED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button press suppressed (B.1): %d", _mouseemu_last_event); + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_PRESSED); + _penmouse_expect_button(SDL_PRESSED, i + 1); + + SDL_SendPenButton(0, ptest.ids[0], SDL_RELEASED, i); + SDLTest_AssertCheck(0 == _mouseemu_last_event, + "Non-touching button press suppressed (B.2): %d", _mouseemu_last_event); + SDL_SendPenTipEvent(0, ptest.ids[0], SDL_RELEASED); + _penmouse_expect_button(SDL_RELEASED, i + 1); + } + SDLTest_AssertPass("Delayed button press mouse emulation, touching and then releasing button"); + + /* Cleanup */ + SDL_PenGCMark(); + _pen_trackGCSweep(&ptest); + _teardown_test(&ptest, backup); + return TEST_COMPLETED; +} + +/** + * @brief Ensure that all SDL_Pen*Event structures have compatible memory layout, as expected by SDL_pen.c + */ +static int +pen_memoryLayout(void *arg) +{ +#define LAYOUT_COMPATIBLE(field) \ + SDLTest_AssertCheck(offsetof(SDL_PenTipEvent, field) == offsetof(SDL_PenMotionEvent, field), \ + "Memory layout SDL_PenTipEvent and SDL_PenMotionEvent compatibility: '" #field "'"); \ + SDLTest_AssertCheck(offsetof(SDL_PenTipEvent, field) == offsetof(SDL_PenButtonEvent, field), \ + "Memory layout SDL_PenTipEvent and SDL_PenBUttonEvent compatibility: '" #field "'"); + + LAYOUT_COMPATIBLE(which); + LAYOUT_COMPATIBLE(x); + LAYOUT_COMPATIBLE(y); + LAYOUT_COMPATIBLE(axes); + + return TEST_COMPLETED; +} + +/* ================= Test References ================== */ + +/* Mouse test cases */ +static const SDLTest_TestCaseReference penTest1 = { (SDLTest_TestCaseFp)pen_iteration, "pen_iteration", "Iterate over all pens with SDL_PenIDForIndex", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest2 = { (SDLTest_TestCaseFp)pen_hotplugging, "pen_hotplugging", "Hotplug pens and validate their status, including SDL_PenConnected", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest3 = { (SDLTest_TestCaseFp)pen_GUIDs, "pen_GUIDs", "Check Pen SDL_GUID operations", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest4 = { (SDLTest_TestCaseFp)pen_buttonReporting, "pen_buttonReporting", "Check pen button presses", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest5 = { (SDLTest_TestCaseFp)pen_movementAndAxes, "pen_movementAndAxes", "Check pen movement and axis update reporting", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest6 = { (SDLTest_TestCaseFp)pen_initAndInfo, "pen_info", "Check pen self-description and initialisation", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest7 = { (SDLTest_TestCaseFp)pen_mouseEmulation, "pen_mouseEmulation", "Check pen-as-mouse event forwarding (direct)", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest8 = { (SDLTest_TestCaseFp)pen_mouseEmulationDelayed, "pen_mouseEmulationDelayed", "Check pen-as-mouse event forwarding (delayed)", TEST_ENABLED }; + +static const SDLTest_TestCaseReference penTest9 = { (SDLTest_TestCaseFp)pen_memoryLayout, "pen_memoryLayout", "Check that all pen events have compatible layout (required by SDL_pen.c)", TEST_ENABLED }; + +/* Sequence of Mouse test cases */ +static const SDLTest_TestCaseReference *penTests[] = { + &penTest1, &penTest2, &penTest3, &penTest4, &penTest5, &penTest6, &penTest7, &penTest8, &penTest9, NULL +}; + +/* Mouse test suite (global) */ +SDLTest_TestSuiteReference penTestSuite = { + "Pen", + NULL, + penTests, + NULL +}; diff --git a/test/testautomation_suites.h b/test/testautomation_suites.h index 143ec15369a4a..6d04b4f9728f4 100644 --- a/test/testautomation_suites.h +++ b/test/testautomation_suites.h @@ -20,6 +20,7 @@ extern SDLTest_TestSuiteReference keyboardTestSuite; extern SDLTest_TestSuiteReference mainTestSuite; extern SDLTest_TestSuiteReference mathTestSuite; extern SDLTest_TestSuiteReference mouseTestSuite; +extern SDLTest_TestSuiteReference penTestSuite; extern SDLTest_TestSuiteReference pixelsTestSuite; extern SDLTest_TestSuiteReference platformTestSuite; extern SDLTest_TestSuiteReference propertiesTestSuite; diff --git a/test/testpen.c b/test/testpen.c new file mode 100644 index 0000000000000..aa92f7f54de6a --- /dev/null +++ b/test/testpen.c @@ -0,0 +1,496 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include +#include +#include +#include +#include + +#define WIDTH 1600 +#define HEIGHT 1200 + +#define VERBOSE 0 + +#define ALWAYS_SHOW_PRESSURE_BOX 1 + +static SDLTest_CommonState *state; +static int quitting = 0; + +static float last_x, last_y; +static float last_xtilt, last_ytilt, last_pressure, last_distance, last_rotation; +static int last_button; +static int last_touching; /* tip touches surface */ +static int last_was_eraser; + +static SDL_Texture *offscreen_texture = NULL; + +static void DrawScreen(SDL_Renderer *renderer) +{ + float xdelta, ydelta, endx, endy; + /* off-screen texture to render into */ + SDL_Texture *window_texture; + const float X = 128.0f, Y = 128.0f; /* mid-point in the off-screen texture */ + SDL_FRect dest_rect; + float tilt_vec_x = SDL_sinf(last_xtilt * SDL_PI_F / 180.0f); + float tilt_vec_y = SDL_sinf(last_ytilt * SDL_PI_F / 180.0f); + int color = last_button + 1; + + if (!renderer) { + return; + } + + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, 0x40, 0x40, 0x40, 0xff); + SDL_RenderClear(renderer); + + if (offscreen_texture == NULL) { + offscreen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, (int)(X * 2.0f), (int)(Y * 2.0f)); + } + + /* Render into off-screen texture so we can do pixel-precise rendering later */ + window_texture = SDL_GetRenderTarget(renderer); + SDL_SetRenderTarget(renderer, offscreen_texture); + + /* Rendering starts here */ + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, 0x40, 0x40, 0x40, 0xff); + SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, 0xa0, 0xa0, 0xa0, 0xff); + if (last_touching) { + SDL_FRect rect; + + rect.x = 0; + rect.y = 0; + rect.w = 2.0f * X - 1.0f; + rect.h = 2.0f * Y - 1.0f; + + SDL_RenderRect(renderer, &rect); + } else { + /* Show where the pen is rotating when it isn't touching the surface. + Otherwise we draw the rotation angle below together with pressure information. */ + float rot_vecx = SDL_sinf(last_rotation / 180.0f * SDL_PI_F); + float rot_vecy = -SDL_cosf(last_rotation / 180.0f * SDL_PI_F); + float px = X + rot_vecx * 100.0f; + float py = Y + rot_vecy * 100.0f; + float px2 = X + rot_vecx * 80.0f; + float py2 = Y + rot_vecy * 80.0f; + + SDL_RenderLine(renderer, + px, py, + px2 + rot_vecy * 20.0f, + py2 - rot_vecx * 20.0f); + SDL_RenderLine(renderer, + px, py, + px2 - rot_vecy * 20.0f, + py2 + rot_vecx * 20.0f); + } + + if (last_was_eraser) { + SDL_FRect rect; + + rect.x = X - 10.0f; + rect.y = Y - 10.0f; + rect.w = 21.0f; + rect.h = 21.0f; + + SDL_SetRenderDrawColor(renderer, 0x00, 0xff, 0xff, 0xff); + SDL_RenderFillRect(renderer, &rect); + } else { + float distance = last_distance * 50.0f; + + SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0xff); + SDL_RenderLine(renderer, + X - 10.0f - distance, Y, + X - distance, Y); + SDL_RenderLine(renderer, + X + 10.0f + distance, Y, + X + distance, Y); + SDL_RenderLine(renderer, + X, Y - 10.0f - distance, + X, Y - distance); + SDL_RenderLine(renderer, + X, Y + 10.0f + distance, + X, Y + distance); + + } + + /* Draw a cone based on the direction the pen is leaning as if it were shining a light. */ + /* Colour derived from pens, intensity based on pressure: */ + SDL_SetRenderDrawColor(renderer, + (color & 0x01) ? 0xff : 0, + (color & 0x02) ? 0xff : 0, + (color & 0x04) ? 0xff : 0, + (int)(0xff)); + + xdelta = -tilt_vec_x * 100.0f; + ydelta = -tilt_vec_y * 100.0f; + endx = X + xdelta; + endy = Y + ydelta; + SDL_RenderLine(renderer, X, Y, endx, endy); + + SDL_SetRenderDrawColor(renderer, + (color & 0x01) ? 0xff : 0, + (color & 0x02) ? 0xff : 0, + (color & 0x04) ? 0xff : 0, + (int)(0xff * last_pressure)); + /* Cone base width based on pressure: */ + SDL_RenderLine(renderer, X, Y, endx + (ydelta * last_pressure / 3.0f), endy - (xdelta * last_pressure / 3.0f)); + SDL_RenderLine(renderer, X, Y, endx - (ydelta * last_pressure / 3.0f), endy + (xdelta * last_pressure / 3.0f)); + + /* If tilt is very small (or zero, for pens that don't have tilt), add some extra lines, rotated by the current rotation value */ + if (ALWAYS_SHOW_PRESSURE_BOX || (fabs(tilt_vec_x) < 0.2f && fabs(tilt_vec_y) < 0.2f)) { + int rot; + float pressure = last_pressure * 80.0f; + + /* Four times, rotated 90 degrees, so that we get a box */ + for (rot = 0; rot < 4; ++rot) { + + float vecx = SDL_cosf((last_rotation + (rot * 90.0f)) / 180.0f * SDL_PI_F); + float vecy = SDL_sinf((last_rotation + (rot * 90.0f)) / 180.0f * SDL_PI_F); + + float px = X + vecx * pressure; + float py = Y + vecy * pressure; + + SDL_RenderLine(renderer, + px + vecy * 10.0f, py - vecx * 10.0f, + px - vecy * 10.0f, py + vecx * 10.0f); + + if (rot == 3) { + int r = 0; + for (; r >= 0; r -= 2) { + float delta = 10.0f - ((float) r); + + SDL_RenderLine(renderer, + px + vecy * delta, py - vecx * delta, + px + (vecx * pressure * 0.4f), + py + (vecy * pressure * 0.4f)); + SDL_RenderLine(renderer, + px - vecy * delta, py + vecx * delta, + px + (vecx * pressure * 0.4f), + py + (vecy * pressure * 0.4f)); + } + } + } + } + + SDL_SetRenderTarget(renderer, window_texture); + /* Now render to pixel-precise position */ + dest_rect.x = last_x - X; + dest_rect.y = last_y - Y; + dest_rect.w = X * 2.0f; + dest_rect.h = Y * 2.0f; + SDL_RenderTexture(renderer, offscreen_texture, NULL, &dest_rect); + SDL_RenderPresent(renderer); +} + +static void dump_state(void) +{ + int i; + int pens_nr; + + /* Make sure this also works with a NULL parameter */ + SDL_PenID* pens = SDL_GetPens(NULL); + if (pens) { + SDL_free(pens); + } + + pens = SDL_GetPens(&pens_nr); + if (!pens) { + SDL_Log("Couldn't get pens: %s\n", SDL_GetError()); + return; + } + SDL_Log("Found %d pens (terminated by %u)\n", pens_nr, (unsigned) pens[pens_nr]); + + for (i = 0; i < pens_nr; ++i) { + SDL_PenID penid = pens[i]; + SDL_GUID guid = SDL_GetPenGUID(penid); + char guid_str[33]; + float axes[SDL_PEN_NUM_AXES]; + float x, y; + int k; + SDL_PenCapabilityInfo info; + Uint32 status = SDL_GetPenStatus(penid, &x, &y, axes, SDL_PEN_NUM_AXES); + Uint32 capabilities = SDL_GetPenCapabilities(penid, &info); + char *type; + char *buttons_str; + + SDL_GUIDToString(guid, guid_str, 33); + + switch (SDL_GetPenType(penid)) { + case SDL_PEN_TYPE_ERASER: + type = "Eraser"; + break; + case SDL_PEN_TYPE_PEN: + type = "Pen"; + break; + case SDL_PEN_TYPE_PENCIL: + type = "Pencil"; + break; + case SDL_PEN_TYPE_BRUSH: + type = "Brush"; + break; + case SDL_PEN_TYPE_AIRBRUSH: + type = "Airbrush"; + break; + default: + type = "Unknown (bug?)"; + } + + switch (info.num_buttons) { + case SDL_PEN_INFO_UNKNOWN: + SDL_asprintf(&buttons_str, "? buttons"); + break; + case 1: + SDL_asprintf(&buttons_str, "1 button"); + break; + default: + SDL_asprintf(&buttons_str, "%d button", info.num_buttons); + break; + } + + SDL_Log("%s %lu: [%s] attached=%d, %s [cap= %08lx:%08lx =status] '%s'\n", + type, + (unsigned long) penid, guid_str, + SDL_PenConnected(penid), /* should always be SDL_TRUE during iteration */ + buttons_str, + (unsigned long) capabilities, + (unsigned long) status, + SDL_GetPenName(penid)); + SDL_free(buttons_str); + SDL_Log(" pos=(%.2f, %.2f)", x, y); + for (k = 0; k < SDL_PEN_NUM_AXES; ++k) { + SDL_bool supported = capabilities & SDL_PEN_AXIS_CAPABILITY(k); + if (supported) { + if (k == SDL_PEN_AXIS_XTILT || k == SDL_PEN_AXIS_YTILT) { + if (info.max_tilt == SDL_PEN_INFO_UNKNOWN) { + SDL_Log(" axis %d: %.3f (max tilt unknown)", k, axes[k]); + } else { + SDL_Log(" axis %d: %.3f (tilt -%.1f..%.1f)", k, axes[k], + info.max_tilt, info.max_tilt); + } + } else { + SDL_Log(" axis %d: %.3f", k, axes[k]); + } + } else { + SDL_Log(" axis %d: unsupported (%.3f)", k, axes[k]); + } + } + } + SDL_free(pens); +} + +static void update_axes(float *axes) +{ + last_xtilt = axes[SDL_PEN_AXIS_XTILT]; + last_ytilt = axes[SDL_PEN_AXIS_YTILT]; + last_pressure = axes[SDL_PEN_AXIS_PRESSURE]; + last_distance = axes[SDL_PEN_AXIS_DISTANCE]; + last_rotation = axes[SDL_PEN_AXIS_ROTATION]; +} + +static void process_event(SDL_Event event) +{ + SDLTest_CommonEvent(state, &event, &quitting); + + switch (event.type) { + case SDL_EVENT_KEY_DOWN: + { + dump_state(); + break; + } + case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: +#if VERBOSE + { + float x, y; + SDL_GetMouseState(&x, &y); + if (event.type == SDL_EVENT_MOUSE_MOTION) { + SDL_Log("[%lu] mouse motion: mouse ID %d is at (%.2f, %.2f) (state: %.2f,%.2f) delta (%.2f, %.2f)\n", + event.motion.timestamp, + event.motion.which, + event.motion.x, event.motion.y, + event.motion.xrel, event.motion.yrel, + x, y); + } else { + SDL_Log("[%lu] mouse button: mouse ID %d is at (%.2f, %.2f) (state: %.2f,%.2f)\n", + event.button.timestamp, + event.button.which, + event.button.x, event.button.y, + x, y); + } + } +#endif + if (event.motion.which != SDL_PEN_MOUSEID) { + SDL_ShowCursor(); + } break; + + case SDL_EVENT_PEN_MOTION: + { + SDL_PenMotionEvent *ev = &event.pmotion; + + SDL_HideCursor(); + last_x = ev->x; + last_y = ev->y; + update_axes(ev->axes); + last_was_eraser = ev->pen_state & SDL_PEN_ERASER_MASK; +#if VERBOSE + SDL_Log("[%lu] pen motion: %s %u at (%.4f, %.4f); pressure=%.3f, tilt=%.3f/%.3f, dist=%.3f [buttons=%02x]\n", + (unsigned long) ev->timestamp, + last_was_eraser ? "eraser" : "pen", + (unsigned int)ev->which, ev->x, ev->y, last_pressure, last_xtilt, last_ytilt, last_distance, + ev->pen_state); +#endif + } break; + + case SDL_EVENT_PEN_UP: + case SDL_EVENT_PEN_DOWN: { + SDL_PenTipEvent *ev = &event.ptip; + last_x = ev->x; + last_y = ev->y; + update_axes(ev->axes); + last_was_eraser = ev->tip == SDL_PEN_TIP_ERASER; + last_button = ev->pen_state & 0xf; /* button mask */ + last_touching = (event.type == SDL_EVENT_PEN_DOWN); + } break; + + case SDL_EVENT_PEN_BUTTON_UP: + case SDL_EVENT_PEN_BUTTON_DOWN: + { + SDL_PenButtonEvent *ev = &event.pbutton; + + SDL_HideCursor(); + last_x = ev->x; + last_y = ev->y; + update_axes(ev->axes); + if (last_pressure > 0.0f && !last_touching) { + SDL_LogWarn(SDL_LOG_CATEGORY_TEST, + "[%lu] : reported pressure %.5f even though pen is not touching surface", + (unsigned long) ev->timestamp, last_pressure); + + } + last_was_eraser = ev->pen_state & SDL_PEN_ERASER_MASK; + last_button = ev->pen_state & 0xf; /* button mask */ + if ((ev->pen_state & SDL_PEN_DOWN_MASK) && !last_touching) { + SDL_LogWarn(SDL_LOG_CATEGORY_TEST, + "[%lu] : reported flags %x (SDL_PEN_FLAG_DOWN_MASK) despite not receiving SDL_EVENT_PEN_DOWN", + (unsigned long) ev->timestamp, ev->pen_state); + + } + if (!(ev->pen_state & SDL_PEN_DOWN_MASK) && last_touching) { + SDL_LogWarn(SDL_LOG_CATEGORY_TEST, + "[%lu] : reported flags %x (no SDL_PEN_FLAG_DOWN_MASK) despite receiving SDL_EVENT_PEN_DOWN without SDL_EVENT_PEN_UP afterwards", + (unsigned long) ev->timestamp, ev->pen_state); + + } +#if VERBOSE + SDL_Log("[%lu] pen button: %s %u at (%.4f, %.4f); BUTTON %d reported %s with event %s [pressure=%.3f, tilt=%.3f/%.3f, dist=%.3f]\n", + (unsigned long) ev->timestamp, + last_was_eraser ? "eraser" : "pen", + (unsigned int)ev->which, ev->x, ev->y, + ev->button, + (ev->state == SDL_PRESSED) ? "PRESSED" + : ((ev->state == SDL_RELEASED) ? "RELEASED" : "--invalid--"), + event.type == SDL_EVENT_PEN_BUTTON_UP ? "PENBUTTONUP" : "PENBUTTONDOWN", + last_pressure, last_xtilt, last_ytilt, last_distance); +#endif + } break; + + case SDL_EVENT_WINDOW_PEN_ENTER: + SDL_Log("[%lu] Pen %lu entered window %lx", + (unsigned long) event.window.timestamp, + (unsigned long) event.window.data1, + (unsigned long) event.window.windowID); + break; + + case SDL_EVENT_WINDOW_PEN_LEAVE: + SDL_Log("[%lu] Pen %lu left window %lx", + (unsigned long) event.window.timestamp, + (unsigned long) event.window.data1, + (unsigned long) event.window.windowID); + break; + +#if VERBOSE + case SDL_EVENT_WINDOW_MOUSE_ENTER: + SDL_Log("[%lu] Mouse entered window %lx", + (unsigned long) event.window.timestamp, + (unsigned long) event.window.windowID); + break; + + case SDL_EVENT_WINDOW_MOUSE_LEAVE: + SDL_Log("[%lu] Mouse left window %lx", + (unsigned long) event.window.timestamp, + (unsigned long) event.window.windowID); + break; +#endif + + default: + break; + } +} + +static void loop(void) +{ + SDL_Event event; + int i; + + for (i = 0; i < state->num_windows; ++i) { + if (state->renderers[i]) { + DrawScreen(state->renderers[i]); + } + } + + if (SDL_WaitEventTimeout(&event, 10)) { + process_event(event); + } + while (SDL_PollEvent(&event)) { + process_event(event); + } +} + +int main(int argc, char *argv[]) +{ + state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); + if (!state) { + return 1; + } + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); + + state->window_title = "Pressure-Sensitive Pen Test"; + state->window_w = WIDTH; + state->window_h = HEIGHT; + state->skip_renderer = SDL_FALSE; + + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; + } + + while (!quitting) { + loop(); + } + + SDLTest_CommonQuit(state); + return 0; +} From 0907f345cb36c77bfdcc9e9f9f2942ecb42824a2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 09:47:31 -0800 Subject: [PATCH 332/725] Added property types: pointer, string, number, float --- include/SDL3/SDL_properties.h | 171 ++++++++- include/SDL3/SDL_render.h | 38 +- include/SDL3/SDL_video.h | 54 +-- src/SDL_properties.c | 345 ++++++++++++++++-- src/core/linux/SDL_fcitx.c | 6 +- src/core/linux/SDL_ibus.c | 6 +- src/dynapi/SDL_dynapi.sym | 8 + src/dynapi/SDL_dynapi_overrides.h | 8 + src/dynapi/SDL_dynapi_procs.h | 10 +- src/render/SDL_render.c | 2 +- src/render/direct3d/SDL_render_d3d.c | 2 +- src/render/direct3d11/SDL_render_d3d11.c | 2 +- src/render/direct3d11/SDL_render_winrt.cpp | 2 +- src/render/direct3d12/SDL_render_d3d12.c | 2 +- src/render/metal/SDL_render_metal.m | 12 +- src/render/opengl/SDL_render_gl.c | 10 +- src/render/opengles2/SDL_render_gles2.c | 8 +- src/video/SDL_video.c | 6 +- src/video/cocoa/SDL_cocoawindow.m | 2 +- src/video/dummy/SDL_nullframebuffer.c | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 4 +- src/video/n3ds/SDL_n3dsframebuffer.c | 2 +- .../offscreen/SDL_offscreenframebuffer.c | 2 +- src/video/uikit/SDL_uikitwindow.m | 2 +- src/video/x11/SDL_x11window.c | 4 +- test/testautomation_properties.c | 134 ++++++- test/testautomation_video.c | 19 +- test/testffmpeg.c | 6 +- 28 files changed, 727 insertions(+), 142 deletions(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 17b280ae19e0a..655a21d415518 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -39,6 +39,18 @@ extern "C" { */ typedef Uint32 SDL_PropertiesID; +/** + * SDL property type + */ +typedef enum +{ + SDL_PROPERTY_TYPE_INVALID, + SDL_PROPERTY_TYPE_POINTER, + SDL_PROPERTY_TYPE_STRING, + SDL_PROPERTY_TYPE_NUMBER, + SDL_PROPERTY_TYPE_FLOAT, +} SDL_PropertyType; + /** * Get the global SDL properties * @@ -105,6 +117,28 @@ extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props); */ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); +/** + * Set a property on a set of properties with a cleanup function that is + * called when the property is deleted + * + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property, or NULL to delete the property + * \param cleanup the function to call when this property is deleted, or NULL + * if no cleanup is necessary + * \param userdata a pointer that is passed to the cleanup function + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); + /** * Set a property on a set of properties * @@ -124,15 +158,11 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value); /** - * Set a property on a set of properties with a cleanup function that is - * called when the property is deleted + * Set a string property on a set of properties * * \param props the properties to modify * \param name the name of the property to modify * \param value the new value of the property, or NULL to delete the property - * \param cleanup the function to call when this property is deleted, or NULL - * if no cleanup is necessary - * \param userdata a pointer that is passed to the cleanup function * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * @@ -140,10 +170,56 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetProperty - * \sa SDL_SetProperty + * \sa SDL_GetStringProperty */ -extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); +extern DECLSPEC int SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value); + +/** + * Set an integer property on a set of properties + * + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumberProperty + */ +extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value); + +/** + * Set a floating point property on a set of properties + * + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetFloatProperty + */ +extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value); + +/** + * Get the type of a property on a set of properties + * + * \param props the properties to query + * \param name the name of the property to query + * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is not set. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name); /** * Get a property on a set of properties @@ -155,7 +231,8 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c * * \param props the properties to query * \param name the name of the property to query - * \returns the value of the property, or NULL if it is not set. + * \param default_value the default value of the property + * \returns the value of the property, or `default_value` if it is not set or not a pointer property. * * \threadsafety It is safe to call this function from any thread, although * the data returned is not protected and could potentially be @@ -165,9 +242,65 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetPropertyType * \sa SDL_SetProperty */ -extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name); +extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value); + +/** + * Get a string property on a set of properties + * + * \param props the properties to query + * \param name the name of the property to query + * \param default_value the default value of the property + * \returns the value of the property, or `default_value` if it is not set or not a string property. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPropertyType + * \sa SDL_SetStringProperty + */ +extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value); + +/** + * Get a number property on a set of properties + * + * You can use SDL_GetPropertyType() to query whether the property exists and is a number property. + * + * \param props the properties to query + * \param name the name of the property to query + * \param default_value the default value of the property + * \returns the value of the property, or `default_value` if it is not set or not a number property. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPropertyType + * \sa SDL_SetNumberProperty + */ +extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value); + +/** + * Get a floating point property on a set of properties + * + * You can use SDL_GetPropertyType() to query whether the property exists and is a floating point property. + * + * \param props the properties to query + * \param name the name of the property to query + * \param default_value the default value of the property + * \returns the value of the property, or `default_value` if it is not set or not a float property. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPropertyType + * \sa SDL_SetFloatProperty + */ +extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value); /** * Clear a property on a set of properties @@ -185,6 +318,24 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char */ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); +typedef void (SDLCALL *SDL_EnumeratePropertiesCallback)(void *userdata, SDL_PropertiesID props, const char *name); +/** + * Enumerate the properties on a set of properties + * + * The callback function is called for each property on the set of properties. The properties are locked during enumeration. + * + * \param props the properties to query + * \param callback the function to call for each property + * \param userdata a pointer that is passed to `callback` + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata); + /** * Destroy a set of properties * diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 120543dd436e9..72cb5d263d815 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -311,10 +311,10 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * The following properties are provided by SDL: * ``` - * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer - * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer - * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer + * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer + * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer + * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer + * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer * ``` * * \param renderer the rendering context @@ -424,33 +424,33 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * With the direct3d11 renderer: * ``` - * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture - * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture - * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture + * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture + * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture + * "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture * ``` * * With the direct3d12 renderer: * ``` - * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture - * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture - * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture + * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture + * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture + * "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture * ``` * * With the opengl renderer: * ``` - * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture - * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture - * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture - * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture + * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture + * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture + * "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) + * "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) * ``` * * With the opengles2 renderer: * ``` - * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture - * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture - * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture + * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture + * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture + * "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture * ``` * * \param texture the texture to query diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index e0363eccdfaf7..e8db562df8435 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -938,58 +938,58 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * On Android: * ``` - * "SDL.window.android.window" - the ANativeWindow associated with the window - * "SDL.window.android.surface" - the EGLSurface associated with the window + * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window + * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window * ``` * * On iOS: * ``` - * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window - * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window + * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window * ``` * * On KMS/DRM: * ``` - * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX) - * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window - * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window + * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX) + * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window + * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window * ``` * * On macOS: * ``` - * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window - * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window + * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window + * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window * ``` * * On Vivante: * ``` - * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window - * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window - * "SDL.window.vivante.surface" - the EGLSurface associated with the window + * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window + * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window + * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window * ``` * * On UWP: * ``` - * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window + * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window * ``` * * On Windows: * ``` - * "SDL.window.win32.hwnd" - the HWND associated with the window - * "SDL.window.win32.hdc" - the HDC associated with the window - * "SDL.window.win32.instance" - the HINSTANCE associated with the window + * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window + * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window + * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window * ``` * * On Wayland: * ``` - * "SDL.window.wayland.registry" - the wl_registry associated with the window - * "SDL.window.wayland.display" - the wl_display associated with the window - * "SDL.window.wayland.surface" - the wl_surface associated with the window - * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window - * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window - * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window - * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode + * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window + * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window + * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window + * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window + * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window + * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window + * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode * ``` * * Note: The xdg_* window objects do not internally persist across window show/hide calls. @@ -997,9 +997,9 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * On X11: * ``` - * "SDL.window.x11.display" - the X11 Display associated with the window - * "SDL.window.x11.screen" - the screen number associated with the window - * "SDL.window.x11.window" - the X11 Window associated with the window + * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window + * "SDL.window.x11.screen" (number) - the screen number associated with the window + * "SDL.window.x11.window" (number) - the X11 Window associated with the window * ``` * * \param window the window to query diff --git a/src/SDL_properties.c b/src/SDL_properties.c index de54ee8c30090..5b47b597ac985 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -25,7 +25,15 @@ typedef struct { - void *value; + SDL_PropertyType type; + + union { + void *pointer_value; + char *string_value; + Sint64 number_value; + float float_value; + } value; + void (SDLCALL *cleanup)(void *userdata, void *value); void *userdata; } SDL_Property; @@ -45,8 +53,19 @@ static SDL_PropertiesID SDL_global_properties; static void SDL_FreeProperty(const void *key, const void *value, void *data) { SDL_Property *property = (SDL_Property *)value; - if (property->cleanup) { - property->cleanup(property->userdata, property->value); + if (property) { + switch (property->type) { + case SDL_PROPERTY_TYPE_POINTER: + if (property->cleanup) { + property->cleanup(property->userdata, property->value.pointer_value); + } + break; + case SDL_PROPERTY_TYPE_STRING: + SDL_free(property->value.string_value); + break; + default: + break; + } } SDL_free((void *)key); SDL_free((void *)value); @@ -196,21 +215,17 @@ void SDL_UnlockProperties(SDL_PropertiesID props) SDL_UnlockMutex(properties->lock); } -int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) -{ - return SDL_SetPropertyWithCleanup(props, name, value, NULL, NULL); -} - -int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) +static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property) { SDL_Properties *properties = NULL; - SDL_Property *property = NULL; int result = 0; if (!props) { + SDL_FreeProperty(NULL, property, NULL); return SDL_InvalidParamError("props"); } if (!name || !*name) { + SDL_FreeProperty(NULL, property, NULL); return SDL_InvalidParamError("name"); } @@ -219,20 +234,10 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v SDL_UnlockRWLock(SDL_properties_lock); if (!properties) { + SDL_FreeProperty(NULL, property, NULL); return SDL_InvalidParamError("props"); } - if (value) { - property = (SDL_Property *)SDL_malloc(sizeof(*property)); - if (!property) { - return SDL_OutOfMemory(); - } - - property->value = value; - property->cleanup = cleanup; - property->userdata = userdata; - } - SDL_LockMutex(properties->lock); { SDL_RemoveFromHashTable(properties->props, name); @@ -249,18 +254,135 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v return result; } -void *SDL_GetProperty(SDL_PropertiesID props, const char *name) +int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) +{ + SDL_Property *property; + + if (!value) { + return SDL_ClearProperty(props, name); + } + + property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_POINTER; + property->value.pointer_value = value; + property->cleanup = cleanup; + property->userdata = userdata; + return SDL_PrivateSetProperty(props, name, property); +} + +int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) +{ + SDL_Property *property; + + if (!value) { + return SDL_ClearProperty(props, name); + } + + property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_POINTER; + property->value.pointer_value = value; + return SDL_PrivateSetProperty(props, name, property); +} + + +int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value) +{ + SDL_Property *property; + + if (!value) { + return SDL_ClearProperty(props, name); + } + + property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_STRING; + property->value.string_value = SDL_strdup(value); + if (!property->value.string_value) { + SDL_free(property); + return SDL_OutOfMemory(); + } + return SDL_PrivateSetProperty(props, name, property); +} + +int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value) +{ + SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_NUMBER; + property->value.number_value = value; + return SDL_PrivateSetProperty(props, name, property); +} + +int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value) +{ + SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_FLOAT; + property->value.float_value = value; + return SDL_PrivateSetProperty(props, name, property); +} + +SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) +{ + SDL_Properties *properties = NULL; + SDL_PropertyType type = SDL_PROPERTY_TYPE_INVALID; + + if (!props) { + SDL_InvalidParamError("props"); + return SDL_PROPERTY_TYPE_INVALID; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return SDL_PROPERTY_TYPE_INVALID; + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + SDL_InvalidParamError("props"); + return SDL_PROPERTY_TYPE_INVALID; + } + + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + type = property->type; + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return type; +} + +void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value) { SDL_Properties *properties = NULL; - void *value = NULL; + void *value = default_value; if (!props) { SDL_InvalidParamError("props"); - return NULL; + return value; } if (!name || !*name) { SDL_InvalidParamError("name"); - return NULL; + return value; } SDL_LockRWLockForReading(SDL_properties_lock); @@ -269,7 +391,7 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) if (!properties) { SDL_InvalidParamError("props"); - return NULL; + return value; } /* Note that taking the lock here only guarantees that we won't read the @@ -280,7 +402,140 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - value = property->value; + if (property->type == SDL_PROPERTY_TYPE_POINTER) { + value = property->value.pointer_value; + } else { + SDL_SetError("Property %s isn't a pointer value", name); + } + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return value; +} + +const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value) +{ + SDL_Properties *properties = NULL; + const char *value = default_value; + + if (!props) { + SDL_InvalidParamError("props"); + return value; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return value; + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + SDL_InvalidParamError("props"); + return value; + } + + /* Note that taking the lock here only guarantees that we won't read the + * hashtable while it's being modified. The value itself can easily be + * freed from another thread after it is returned here. + * + * FIXME: Should we SDL_strdup() the return value to avoid this? + */ + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + if (property->type == SDL_PROPERTY_TYPE_STRING) { + value = property->value.string_value; + } else { + SDL_SetError("Property %s isn't a string value", name); + } + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return value; +} + +Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value) +{ + SDL_Properties *properties = NULL; + Sint64 value = default_value; + + if (!props) { + SDL_InvalidParamError("props"); + return value; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return value; + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + SDL_InvalidParamError("props"); + return value; + } + + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + if (property->type == SDL_PROPERTY_TYPE_NUMBER) { + value = property->value.number_value; + } else { + SDL_SetError("Property %s isn't a string value", name); + } + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return value; +} + +float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value) +{ + SDL_Properties *properties = NULL; + float value = default_value; + + if (!props) { + SDL_InvalidParamError("props"); + return value; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return value; + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + SDL_InvalidParamError("props"); + return value; + } + + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + if (property->type == SDL_PROPERTY_TYPE_FLOAT) { + value = property->value.float_value; + } else { + SDL_SetError("Property %s isn't a float value", name); + } } else { SDL_SetError("Couldn't find property named %s", name); } @@ -292,7 +547,41 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name) int SDL_ClearProperty(SDL_PropertiesID props, const char *name) { - return SDL_SetProperty(props, name, NULL); + return SDL_PrivateSetProperty(props, name, NULL); +} + +int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata) +{ + SDL_Properties *properties = NULL; + + if (!props) { + return SDL_InvalidParamError("props"); + } + if (!callback) { + return SDL_InvalidParamError("callback"); + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + return SDL_InvalidParamError("props"); + } + + SDL_LockMutex(properties->lock); + { + void *iter; + const void *key, *value; + + iter = NULL; + while (SDL_IterateHashTable(properties->props, &key, &value, &iter)) { + callback(userdata, props, (const char *)key); + } + } + SDL_UnlockMutex(properties->lock); + + return 0; } void SDL_DestroyProperties(SDL_PropertiesID props) diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index 64a200e973752..5f67ffb049ab6 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -428,9 +428,9 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display"); - int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen"); - Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window"); + Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL); + int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0); + Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0); Window unused; if (x_disp && x_win) { X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused); diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 9b8214f73192e..d1ed37b63d559 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -705,9 +705,9 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display"); - int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen"); - Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window"); + Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL); + int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0); + Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0); Window unused; if (x_disp && x_win) { diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 972a6ee45dc5f..f0dbaf6d79947 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -956,6 +956,14 @@ SDL3_0.0.0 { SDL_GetPenName; SDL_GetPenCapabilities; SDL_GetPenType; + SDL_SetStringProperty; + SDL_SetNumberProperty; + SDL_SetFloatProperty; + SDL_GetPropertyType; + SDL_GetStringProperty; + SDL_GetNumberProperty; + SDL_GetFloatProperty; + SDL_EnumerateProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 41a95138b035a..8c7f5ea861b33 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -981,3 +981,11 @@ #define SDL_GetPenName SDL_GetPenName_REAL #define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL #define SDL_GetPenType SDL_GetPenType_REAL +#define SDL_SetStringProperty SDL_SetStringProperty_REAL +#define SDL_SetNumberProperty SDL_SetNumberProperty_REAL +#define SDL_SetFloatProperty SDL_SetFloatProperty_REAL +#define SDL_GetPropertyType SDL_GetPropertyType_REAL +#define SDL_GetStringProperty SDL_GetStringProperty_REAL +#define SDL_GetNumberProperty SDL_GetNumberProperty_REAL +#define SDL_GetFloatProperty SDL_GetFloatProperty_REAL +#define SDL_EnumerateProperties SDL_EnumerateProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 07f1bd1e2d887..3314f71bdd276 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -961,7 +961,7 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),return) @@ -1006,3 +1006,11 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return) SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return) +SDL_DYNAPI_PROC(int,SDL_SetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_PropertyType,SDL_GetPropertyType,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(const char*,SDL_GetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) +SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 55904a38c6810..8f987e84d0f77 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -994,7 +994,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) SDL_Renderer *SDL_GetRenderer(SDL_Window *window) { - return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA); + return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, NULL); } SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 4fd16b4e9ff18..7d6428932b3cf 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1602,7 +1602,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) } SDL_zero(pparams); - pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); + pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL); pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; pparams.BackBufferCount = 1; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 5b3b10e8fb015..4561dfe300d5e 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -825,7 +825,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) #endif } else { #if defined(__WIN32__) || defined(__WINGDK__) - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd"); + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL); result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory, (IUnknown *)data->d3dDevice, diff --git a/src/render/direct3d11/SDL_render_winrt.cpp b/src/render/direct3d11/SDL_render_winrt.cpp index 4ecd41908771d..34992d99cd450 100644 --- a/src/render/direct3d11/SDL_render_winrt.cpp +++ b/src/render/direct3d11/SDL_render_winrt.cpp @@ -44,7 +44,7 @@ using namespace Windows::Graphics::Display; extern "C" void * D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer) { - IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window"); + IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window", NULL); ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL; if (!window || FAILED(window->QueryInterface(&coreWindow))) { return NULL; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index bda1fbe0feeeb..1442be58ee13a 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1178,7 +1178,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h) swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | /* To support SetMaximumFrameLatency */ DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; /* To support presenting with allow tearing on */ - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd"); + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL); result = D3D_CALL(data->dxgiFactory, CreateSwapChainForHwnd, (IUnknown *)data->commandQueue, diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 606b17f17dc24..a215ff5c6298a 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1626,9 +1626,9 @@ static int METAL_SetVSync(SDL_Renderer *renderer, const int vsync) static SDL_MetalView GetWindowView(SDL_Window *window) { #ifdef SDL_VIDEO_DRIVER_COCOA - NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window"); - NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag"); - if (nswindow) { + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL); + NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag", 0); + if (nswindow && tag) { NSView *view = nswindow.contentView; if (view.subviews.count > 0) { view = view.subviews[0]; @@ -1640,9 +1640,9 @@ static SDL_MetalView GetWindowView(SDL_Window *window) #endif #ifdef SDL_VIDEO_DRIVER_UIKIT - UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window"); - NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag"); - if (uiwindow) { + UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window", NULL); + NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag", 0); + if (uiwindow && tag) { UIView *view = uiwindow.rootViewController.view; if (view.tag == tag) { return (SDL_MetalView)CFBridgingRetain(view); diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index bc86432f5b747..523e8ac7eec67 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -519,9 +519,9 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) data->texh = (GLfloat)texture->h / texture_h; } SDL_PropertiesID props = SDL_GetTextureProperties(texture); - SDL_SetProperty(props, "SDL.texture.opengl.texture", (void *)(uintptr_t)data->texture); - SDL_SetProperty(props, "SDL.texture.opengl.tex_w", (void *)(uintptr_t)(Uint32)(data->texw * 65536)); - SDL_SetProperty(props, "SDL.texture.opengl.tex_h", (void *)(uintptr_t)(Uint32)(data->texh * 65536)); + SDL_SetNumberProperty(props, "SDL.texture.opengl.texture", data->texture); + SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_w", data->texw); + SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_h", data->texh); data->format = format; data->formattype = type; @@ -594,7 +594,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); - SDL_SetProperty(props, "SDL.texture.opengl.texture_u", (void *)(uintptr_t)data->utexture); + SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_u", data->utexture); renderdata->glBindTexture(textype, data->vtexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, @@ -607,7 +607,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); - SDL_SetProperty(props, "SDL.texture.opengl.texture_v", (void *)(uintptr_t)data->vtexture); + SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_v", data->vtexture); } if (texture->format == SDL_PIXELFORMAT_NV12 || diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 21d04c45c37a7..cb03179ef8258 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1499,7 +1499,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", (void *)(uintptr_t)data->texture_v); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", data->texture_v); renderdata->glGenTextures(1, &data->texture_u); if (GL_CheckError("glGenTexures()", renderer) < 0) { @@ -1515,7 +1515,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", (void *)(uintptr_t)data->texture_u); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", data->texture_u); } else if (data->nv12) { renderdata->glGenTextures(1, &data->texture_u); @@ -1532,7 +1532,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", (void *)(uintptr_t)data->texture_u); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", data->texture_u); } #endif @@ -1553,7 +1553,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) return -1; } } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", (void *)(uintptr_t)data->texture); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", data->texture); if (texture->access == SDL_TEXTUREACCESS_TARGET) { data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index a293b7dc4ffcc..16010b810eb46 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -226,7 +226,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U { SDL_RendererInfo info; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA); + SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA, NULL); const SDL_bool transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; int i; int w, h; @@ -349,7 +349,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, SDL_GetWindowSizeInPixels(window, &w, &h); - data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL); if (!data || !data->texture) { return SDL_SetError("No window texture data"); } @@ -381,7 +381,7 @@ int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync) { SDL_WindowTextureData *data; - data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL); if (!data) { return -1; } diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index c7e004b220217..afbfb4352d211 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1864,7 +1864,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, "SDL.window.cocoa.window", (__bridge void *)data.nswindow); - SDL_SetProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG); + SDL_SetNumberProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG); /* All done! */ window->driverdata = (SDL_WindowData *)CFBridgingRetain(data); diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index d51b3c4085788..e67954e067fcb 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -60,7 +60,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window static int frame_number; SDL_Surface *surface; - surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE, NULL); if (!surface) { return SDL_SetError("Couldn't find dummy surface for window"); } diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 544cbff075478..ca283c1fe8b37 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1467,8 +1467,8 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) window->driverdata = windata; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.kmsdrm.dev_index", (void *)(intptr_t)viddata->devindex); - SDL_SetProperty(props, "SDL.window.kmsdrm.drm_fd", (void *)(intptr_t)viddata->drm_fd); + SDL_SetNumberProperty(props, "SDL.window.kmsdrm.dev_index", viddata->devindex); + SDL_SetNumberProperty(props, "SDL.window.kmsdrm.drm_fd", viddata->drm_fd); SDL_SetProperty(props, "SDL.window.kmsdrm.gbm_dev", viddata->gbm_dev); if (!is_vulkan && !vulkan_mode) { /* NON-Vulkan block. */ diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 502594d66d814..727dab6a842c4 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -72,7 +72,7 @@ int SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, u32 *framebuffer; u32 bufsize; - surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, NULL); if (!surface) { return SDL_SetError("%s: Unable to get the window surface.", __func__); } diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index cd9604f657916..6ca61316f0266 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -61,7 +61,7 @@ int SDL_OFFSCREEN_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi static int frame_number; SDL_Surface *surface; - surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE); + surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE, NULL); if (!surface) { return SDL_SetError("Couldn't find offscreen surface for window"); } diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 407e6edf4d518..54ba279bd2bb8 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -155,7 +155,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, "SDL.window.uikit.window", (__bridge void *)data.uiwindow); - SDL_SetProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG); + SDL_SetNumberProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG); return 0; } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 1f3e9090dbd76..0997fc7532455 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -386,8 +386,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, SDL_PropertiesID props = SDL_GetWindowProperties(window); int screen = (displaydata ? displaydata->screen : 0); SDL_SetProperty(props, "SDL.window.x11.display", data->videodata->display); - SDL_SetProperty(props, "SDL.window.x11.screen", (void *)(intptr_t)screen); - SDL_SetProperty(props, "SDL.window.x11.window", (void *)(uintptr_t)data->xwindow); + SDL_SetNumberProperty(props, "SDL.window.x11.screen", screen); + SDL_SetNumberProperty(props, "SDL.window.x11.window", data->xwindow); return 0; } diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index 75ddc35b99a60..d2936f119dbde 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -11,12 +11,28 @@ /** * Test basic functionality */ +static void SDLCALL count_properties(void *userdata, SDL_PropertiesID props, const char *name) +{ + int *count = (int *)userdata; + ++(*count); +} +static void SDLCALL count_foo_properties(void *userdata, SDL_PropertiesID props, const char *name) +{ + int *count = (int *)userdata; + if (SDL_strcmp(name, "foo") == 0) { + ++(*count); + } +} static int properties_testBasic(void *arg) { SDL_PropertiesID props; char key[2], expected_value[2]; + SDL_PropertyType type; void *value; - int i, result; + const char *value_string; + Sint64 value_number; + float value_float; + int i, result, count; props = SDL_CreateProperties(); SDLTest_AssertPass("Call to SDL_CreateProperties()"); @@ -30,24 +46,130 @@ static int properties_testBasic(void *arg) SDLTest_AssertPass("Call to SDL_SetProperty()"); SDLTest_AssertCheck(result == 0, "Verify property value was set, got: %d", result); - value = SDL_GetProperty(props, key); + value = SDL_GetProperty(props, key, NULL); SDLTest_AssertPass("Call to SDL_GetProperty()"); SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, expected_value) == 0, "Verify property value was set, got %s, expected %s", value ? (const char *)value : "NULL", expected_value); } + count = 0; + SDL_EnumerateProperties(props, count_properties, &count); + SDLTest_AssertCheck(count == 10, + "Verify property count, expected 10, got: %d", count); + for (i = 0; i < 10; ++i) { SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i); result = SDL_SetProperty(props, key, NULL); SDLTest_AssertPass("Call to SDL_SetProperty(NULL)"); SDLTest_AssertCheck(result == 0, "Verify property value was set, got: %d", result); - value = SDL_GetProperty(props, key); + value = SDL_GetProperty(props, key, NULL); SDLTest_AssertPass("Call to SDL_GetProperty()"); SDLTest_AssertCheck(value == NULL, "Verify property value was set, got %s, expected NULL", (const char *)value); } + count = 0; + SDL_EnumerateProperties(props, count_properties, &count); + SDLTest_AssertCheck(count == 0, + "Verify property count, expected 0, got: %d", count); + + /* Check default values */ + value = SDL_GetProperty(props, "foo", (void *)0xabcd); + SDLTest_AssertCheck(value == (void *)0xabcd, + "Verify property, expected 0xabcd, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", "abcd"); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "abcd") == 0, + "Verify string property, expected \"abcd\", got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 1234); + SDLTest_AssertCheck(value_number == 1234, + "Verify number property, expected 1234, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 1234.0f); + SDLTest_AssertCheck(value_float == 1234.0f, + "Verify float property, expected 1234, got: %f", value_float); + + /* Check data value */ + SDLTest_AssertPass("Call to SDL_SetProperty(\"foo\", 0x01)"); + SDL_SetProperty(props, "foo", (void *)0x01); + type = SDL_GetPropertyType(props, "foo"); + SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_POINTER, + "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_POINTER, type); + value = SDL_GetProperty(props, "foo", NULL); + SDLTest_AssertCheck(value == (void *)0x01, + "Verify property, expected 0x01, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", NULL); + SDLTest_AssertCheck(value_string == NULL, + "Verify string property, expected NULL, got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 0); + SDLTest_AssertCheck(value_number == 0, + "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 0.0f); + SDLTest_AssertCheck(value_float == 0.0f, + "Verify float property, expected 0, got: %f", value_float); + + /* Check string value */ + SDLTest_AssertPass("Call to SDL_SetStringProperty(\"foo\", \"bar\")"); + SDL_SetStringProperty(props, "foo", "bar"); + type = SDL_GetPropertyType(props, "foo"); + SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_STRING, + "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_STRING, type); + value = SDL_GetProperty(props, "foo", NULL); + SDLTest_AssertCheck(value == NULL, + "Verify property, expected NULL, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", NULL); + SDLTest_AssertCheck(value_string != NULL && SDL_strcmp(value_string, "bar") == 0, + "Verify string property, expected \"bar\", got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 0); + SDLTest_AssertCheck(value_number == 0, + "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 0.0f); + SDLTest_AssertCheck(value_float == 0.0f, + "Verify float property, expected 0, got: %f", value_float); + + /* Check number value */ + SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); + SDL_SetNumberProperty(props, "foo", 1); + type = SDL_GetPropertyType(props, "foo"); + SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_NUMBER, + "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_NUMBER, type); + value = SDL_GetProperty(props, "foo", NULL); + SDLTest_AssertCheck(value == NULL, + "Verify property, expected NULL, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", NULL); + SDLTest_AssertCheck(value_string == NULL, + "Verify string property, expected NULL, got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 0); + SDLTest_AssertCheck(value_number == 1, + "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 0.0f); + SDLTest_AssertCheck(value_float == 0.0f, + "Verify float property, expected 0, got: %f", value_float); + + /* Check float value */ + SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); + SDL_SetFloatProperty(props, "foo", 1.0f); + type = SDL_GetPropertyType(props, "foo"); + SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT, + "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_FLOAT, type); + value = SDL_GetProperty(props, "foo", NULL); + SDLTest_AssertCheck(value == NULL, + "Verify property, expected NULL, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", NULL); + SDLTest_AssertCheck(value_string == NULL, + "Verify string property, expected NULL, got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 0); + SDLTest_AssertCheck(value_number == 0, + "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 0.0f); + SDLTest_AssertCheck(value_float == 1.0f, + "Verify string property, expected 1, got: %f", value_float); + + /* Make sure we have exactly one property named foo */ + count = 0; + SDL_EnumerateProperties(props, count_foo_properties, &count); + SDLTest_AssertCheck(count == 1, + "Verify foo property count, expected 1, got: %d", count); + SDL_DestroyProperties(props); return TEST_COMPLETED; @@ -130,7 +252,7 @@ static int properties_testLocking(void *arg) { SDL_Delay(10); SDL_LockProperties(data.props); - value = SDL_GetProperty(data.props, "a"); + value = SDL_GetProperty(data.props, "a", NULL); SDL_UnlockProperties(data.props); if (!value || SDL_strcmp((const char *)value, "thread_loop") == 0) { @@ -144,7 +266,7 @@ static int properties_testLocking(void *arg) SDL_LockProperties(data.props); SDL_SetProperty(data.props, "a", "main"); SDL_Delay(100); - value = SDL_GetProperty(data.props, "a"); + value = SDL_GetProperty(data.props, "a", NULL); SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "main") == 0, "After 100ms sleep, property is %s, expected 'main'", value ? (const char *)value : "NULL"); SDL_UnlockProperties(data.props); @@ -152,7 +274,7 @@ static int properties_testLocking(void *arg) data.done = SDL_TRUE; SDL_WaitThread(thread, NULL); - value = SDL_GetProperty(data.props, "a"); + value = SDL_GetProperty(data.props, "a", NULL); SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_done") == 0, "After thread complete, property is %s, expected 'thread_done'", value ? (const char *)value : "NULL"); } diff --git a/test/testautomation_video.c b/test/testautomation_video.c index e5fbdee2885c9..14caeee49a7e5 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1492,7 +1492,7 @@ static int video_getSetWindowData(void *arg) } /* Get non-existent data */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1505,8 +1505,7 @@ static int video_getSetWindowData(void *arg) /* Get data (twice) */ for (iteration = 1; iteration <= 2; iteration++) { - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), - name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [iteration %d]", name, iteration); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1521,7 +1520,7 @@ static int video_getSetWindowData(void *arg) } /* Get data again */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again]", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1541,7 +1540,7 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Get new data */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata2, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1561,13 +1560,13 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2); /* Get non-existent data */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); /* Get non-existent data new name */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name2); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name2, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name2); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); SDLTest_AssertCheck(SDL_strcmp(referenceName2, name2) == 0, "Validate that name2 was not changed, expected: %s, got: %s", referenceName2, name2); @@ -1579,7 +1578,7 @@ static int video_getSetWindowData(void *arg) SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata); /* Get data (again) */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again, after clear]", name); SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result); SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name); @@ -1605,13 +1604,13 @@ static int video_getSetWindowData(void *arg) checkInvalidParameterError(); /* Get data with NULL name */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), NULL); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), NULL, NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(name=NULL)"); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); /* Get data with empty name */ - result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), ""); + result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), "", NULL); SDLTest_AssertPass("Call to SDL_GetWindowData(name='')"); SDLTest_AssertCheck(result == NULL, "Validate that result is NULL"); checkInvalidParameterError(); diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 1fd3816be6660..f28d60c3504c3 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -145,7 +145,7 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) #endif #ifdef __WIN32__ - d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device"); + d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", NULL); if (d3d11_device) { ID3D11Device_AddRef(d3d11_device); ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context); @@ -457,7 +457,7 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) case SDL_PIXELFORMAT_UNKNOWN: { SDL_PropertiesID props = SDL_GetTextureProperties(*texture); - struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY); + struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, NULL); if (!sws_container) { sws_container = (struct SwsContextContainer *)SDL_calloc(1, sizeof(*sws_container)); if (!sws_container) { @@ -625,7 +625,7 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) } } - ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture"); + ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture", NULL); if (!dx11_resource) { SDL_SetError("Couldn't get texture ID3D11Resource interface"); return SDL_FALSE; From 45fc828c95b1adf458873a454af3f6690cbf64f0 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Sun, 12 Nov 2023 23:02:10 +0300 Subject: [PATCH 333/725] move SDL_EVENT_WINDOW_PEN_ENTER and SDL_EVENT_WINDOW_PEN_LEAVE down ... to preserve compatibility with sdl2-compat. --- include/SDL3/SDL_events.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 186f9f40787a4..a49d30cc08ecf 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -114,8 +114,6 @@ typedef enum SDL_EVENT_WINDOW_RESTORED, /**< Window has been restored to normal size and position */ SDL_EVENT_WINDOW_MOUSE_ENTER, /**< Window has gained mouse focus */ SDL_EVENT_WINDOW_MOUSE_LEAVE, /**< Window has lost mouse focus */ - SDL_EVENT_WINDOW_PEN_ENTER, /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */ - SDL_EVENT_WINDOW_PEN_LEAVE, /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */ SDL_EVENT_WINDOW_FOCUS_GAINED, /**< Window has gained keyboard focus */ SDL_EVENT_WINDOW_FOCUS_LOST, /**< Window has lost keyboard focus */ SDL_EVENT_WINDOW_CLOSE_REQUESTED, /**< The window manager requests that the window be closed */ @@ -129,8 +127,10 @@ typedef enum in an event watcher, the window handle is still valid and can still be used to retrieve any userdata associated with the window. Otherwise, the handle has already been destroyed and all resources associated with it are invalid */ + SDL_EVENT_WINDOW_PEN_ENTER, /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */ + SDL_EVENT_WINDOW_PEN_LEAVE, /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */ SDL_EVENT_WINDOW_FIRST = SDL_EVENT_WINDOW_SHOWN, - SDL_EVENT_WINDOW_LAST = SDL_EVENT_WINDOW_DESTROYED, + SDL_EVENT_WINDOW_LAST = SDL_EVENT_WINDOW_PEN_LEAVE, /* Keyboard events */ SDL_EVENT_KEY_DOWN = 0x300, /**< Key pressed */ From 69cae07cc1c216e35ddf3df98048378ad7aeaf92 Mon Sep 17 00:00:00 2001 From: nia Date: Sun, 12 Nov 2023 20:22:23 +0100 Subject: [PATCH 334/725] cpuinfo: Fix detection of physical memory above 2GB on NetBSD Rework the code to clearly prefer 64-bit sysctls first, then legacy sysctls, and eliminate a second ifdef. Signed-off-by: Nia Alarie --- src/cpuinfo/SDL_cpuinfo.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 7eeb14e0cac3f..bed2a35122c32 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -1011,16 +1011,19 @@ int SDL_GetSystemRAM(void) #endif #ifdef HAVE_SYSCTLBYNAME if (SDL_SystemRAM <= 0) { -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__DragonFly__) -#ifdef HW_REALMEM +#ifdef HW_PHYSMEM64 + /* (64-bit): NetBSD since 2003, OpenBSD */ + int mib[2] = { CTL_HW, HW_PHYSMEM64 }; +#elif defined(HW_REALMEM) + /* (64-bit): FreeBSD since 2005, DragonFly */ int mib[2] = { CTL_HW, HW_REALMEM }; +#elif defined(HW_MEMSIZE) + /* (64-bit): Darwin */ + int mib[2] = { CTL_HW, HW_MEMSIZE }; #else - /* might only report up to 2 GiB */ + /* (32-bit): very old BSD, might only report up to 2 GiB */ int mib[2] = { CTL_HW, HW_PHYSMEM }; -#endif /* HW_REALMEM */ -#else - int mib[2] = { CTL_HW, HW_MEMSIZE }; -#endif /* __FreeBSD__ || __FreeBSD_kernel__ */ +#endif /* HW_PHYSMEM64 */ Uint64 memsize = 0; size_t len = sizeof(memsize); From 0efb3d90e0b112d7639a43a7eaa980360aa0b7e8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 10 Nov 2023 23:40:22 -0500 Subject: [PATCH 335/725] audio: removed a fixed FIXME comment. --- src/audio/SDL_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index a19807b48bdce..6bbd666c7604d 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1367,7 +1367,7 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * } int retval = -1; - SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); // !!! FIXME: this needs an ObtainBlahDefaultAllowed to catch default device changes. + SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); if (device) { SDL_copyp(spec, &device->spec); if (sample_frames) { From c47ac5b2dfec18972c0746ba48f7ec534b8bff9b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 12 Nov 2023 23:41:08 -0500 Subject: [PATCH 336/725] include: Fixed copy/paste error --- include/SDL3/SDL_gamepad.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 9d11b8efc5d23..f0bf60e1603f8 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -977,7 +977,7 @@ extern DECLSPEC Sint16 SDLCALL SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_Game * * \param str string representing a SDL_Gamepad axis * \returns the SDL_GamepadButton enum corresponding to the input string, or - * `SDL_GAMEPAD_AXIS_INVALID` if no match was found. + * `SDL_GAMEPAD_BUTTON_INVALID` if no match was found. * * \since This function is available since SDL 3.0.0. */ From bd269b0f4103581f7adc0ec30631a159f6caf3b1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 18:34:22 -0800 Subject: [PATCH 337/725] Added SDL_SetBooleanProperty() and SDL_GetBooleanProperty() --- include/SDL3/SDL_properties.h | 37 +++++++++++++++++++++ src/SDL_properties.c | 53 +++++++++++++++++++++++++++++++ src/dynapi/SDL_dynapi.sym | 2 ++ src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ test/testautomation_properties.c | 40 ++++++++++++++++++++++- 6 files changed, 135 insertions(+), 1 deletion(-) diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 655a21d415518..eedc178806f47 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -49,6 +49,7 @@ typedef enum SDL_PROPERTY_TYPE_STRING, SDL_PROPERTY_TYPE_NUMBER, SDL_PROPERTY_TYPE_FLOAT, + SDL_PROPERTY_TYPE_BOOLEAN, } SDL_PropertyType; /** @@ -208,6 +209,23 @@ extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const */ extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value); +/** + * Set a boolean property on a set of properties + * + * \param props the properties to modify + * \param name the name of the property to modify + * \param value the new value of the property + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetBooleanProperty + */ +extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value); + /** * Get the type of a property on a set of properties * @@ -302,6 +320,25 @@ extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, con */ extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value); +/** + * Get a boolean property on a set of properties + * + * You can use SDL_GetPropertyType() to query whether the property exists and is a boolean property. + * + * \param props the properties to query + * \param name the name of the property to query + * \param default_value the default value of the property + * \returns the value of the property, or `default_value` if it is not set or not a float property. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPropertyType + * \sa SDL_SetBooleanProperty + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value); + /** * Clear a property on a set of properties * diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 5b47b597ac985..e32d1d11c7595 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -32,6 +32,7 @@ typedef struct char *string_value; Sint64 number_value; float float_value; + SDL_bool boolean_value; } value; void (SDLCALL *cleanup)(void *userdata, void *value); @@ -334,6 +335,17 @@ int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value) return SDL_PrivateSetProperty(props, name, property); } +int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value) +{ + SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); + if (!property) { + return SDL_OutOfMemory(); + } + property->type = SDL_PROPERTY_TYPE_BOOLEAN; + property->value.boolean_value = value; + return SDL_PrivateSetProperty(props, name, property); +} + SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) { SDL_Properties *properties = NULL; @@ -545,6 +557,47 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau return value; } +SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value) +{ + SDL_Properties *properties = NULL; + SDL_bool value = default_value; + + if (!props) { + SDL_InvalidParamError("props"); + return value; + } + if (!name || !*name) { + SDL_InvalidParamError("name"); + return value; + } + + SDL_LockRWLockForReading(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + SDL_UnlockRWLock(SDL_properties_lock); + + if (!properties) { + SDL_InvalidParamError("props"); + return value; + } + + SDL_LockMutex(properties->lock); + { + SDL_Property *property = NULL; + if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { + if (property->type == SDL_PROPERTY_TYPE_BOOLEAN) { + value = property->value.boolean_value; + } else { + SDL_SetError("Property %s isn't a boolean value", name); + } + } else { + SDL_SetError("Couldn't find property named %s", name); + } + } + SDL_UnlockMutex(properties->lock); + + return value; +} + int SDL_ClearProperty(SDL_PropertiesID props, const char *name) { return SDL_PrivateSetProperty(props, name, NULL); diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index f0dbaf6d79947..46c1278c6b655 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -964,6 +964,8 @@ SDL3_0.0.0 { SDL_GetNumberProperty; SDL_GetFloatProperty; SDL_EnumerateProperties; + SDL_SetBooleanProperty; + SDL_GetBooleanProperty; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8c7f5ea861b33..a476b53fc07d9 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -989,3 +989,5 @@ #define SDL_GetNumberProperty SDL_GetNumberProperty_REAL #define SDL_GetFloatProperty SDL_GetFloatProperty_REAL #define SDL_EnumerateProperties SDL_EnumerateProperties_REAL +#define SDL_SetBooleanProperty SDL_SetBooleanProperty_REAL +#define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 3314f71bdd276..90be91d078994 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1014,3 +1014,5 @@ SDL_DYNAPI_PROC(const char*,SDL_GetStringProperty,(SDL_PropertiesID a, const cha SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index d2936f119dbde..3feca3e0429f8 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -32,6 +32,7 @@ static int properties_testBasic(void *arg) const char *value_string; Sint64 value_number; float value_float; + SDL_bool value_bool; int i, result, count; props = SDL_CreateProperties(); @@ -87,6 +88,9 @@ static int properties_testBasic(void *arg) value_float = SDL_GetFloatProperty(props, "foo", 1234.0f); SDLTest_AssertCheck(value_float == 1234.0f, "Verify float property, expected 1234, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_TRUE); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check data value */ SDLTest_AssertPass("Call to SDL_SetProperty(\"foo\", 0x01)"); @@ -106,6 +110,9 @@ static int properties_testBasic(void *arg) value_float = SDL_GetFloatProperty(props, "foo", 0.0f); SDLTest_AssertCheck(value_float == 0.0f, "Verify float property, expected 0, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); + SDLTest_AssertCheck(value_bool == SDL_FALSE, + "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check string value */ SDLTest_AssertPass("Call to SDL_SetStringProperty(\"foo\", \"bar\")"); @@ -125,6 +132,9 @@ static int properties_testBasic(void *arg) value_float = SDL_GetFloatProperty(props, "foo", 0.0f); SDLTest_AssertCheck(value_float == 0.0f, "Verify float property, expected 0, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); + SDLTest_AssertCheck(value_bool == SDL_FALSE, + "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check number value */ SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); @@ -144,9 +154,12 @@ static int properties_testBasic(void *arg) value_float = SDL_GetFloatProperty(props, "foo", 0.0f); SDLTest_AssertCheck(value_float == 0.0f, "Verify float property, expected 0, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); + SDLTest_AssertCheck(value_bool == SDL_FALSE, + "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check float value */ - SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); + SDLTest_AssertPass("Call to SDL_SetFloatProperty(\"foo\", 1)"); SDL_SetFloatProperty(props, "foo", 1.0f); type = SDL_GetPropertyType(props, "foo"); SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT, @@ -163,6 +176,31 @@ static int properties_testBasic(void *arg) value_float = SDL_GetFloatProperty(props, "foo", 0.0f); SDLTest_AssertCheck(value_float == 1.0f, "Verify string property, expected 1, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); + SDLTest_AssertCheck(value_bool == SDL_FALSE, + "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + + /* Check boolean value */ + SDLTest_AssertPass("Call to SDL_SetBooleanProperty(\"foo\", SDL_TRUE)"); + SDL_SetBooleanProperty(props, "foo", SDL_TRUE); + type = SDL_GetPropertyType(props, "foo"); + SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_BOOLEAN, + "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_BOOLEAN, type); + value = SDL_GetProperty(props, "foo", NULL); + SDLTest_AssertCheck(value == NULL, + "Verify property, expected NULL, got: %p", value); + value_string = SDL_GetStringProperty(props, "foo", NULL); + SDLTest_AssertCheck(value_string == NULL, + "Verify string property, expected NULL, got: %s", value_string); + value_number = SDL_GetNumberProperty(props, "foo", 0); + SDLTest_AssertCheck(value_number == 0, + "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + value_float = SDL_GetFloatProperty(props, "foo", 0.0f); + SDLTest_AssertCheck(value_float == 0.0f, + "Verify string property, expected 0, got: %f", value_float); + value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Make sure we have exactly one property named foo */ count = 0; From 6afae6681b2900964be5e3fc48aed9b68374d75c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 19:06:23 -0800 Subject: [PATCH 338/725] Allow casting properties of different types --- src/SDL_properties.c | 92 ++++++++++++++++++++++++++++---- test/testautomation_properties.c | 52 +++++++++--------- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index e32d1d11c7595..e447344940ba4 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -20,6 +20,7 @@ */ #include "SDL_internal.h" #include "SDL_hashtable.h" +#include "SDL_hints_c.h" #include "SDL_properties_c.h" @@ -35,6 +36,8 @@ typedef struct SDL_bool boolean_value; } value; + char *string_storage; + void (SDLCALL *cleanup)(void *userdata, void *value); void *userdata; } SDL_Property; @@ -67,6 +70,9 @@ static void SDL_FreeProperty(const void *key, const void *value, void *data) default: break; } + if (property->string_storage) { + SDL_free(property->string_storage); + } } SDL_free((void *)key); SDL_free((void *)value); @@ -342,7 +348,7 @@ int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool va return SDL_OutOfMemory(); } property->type = SDL_PROPERTY_TYPE_BOOLEAN; - property->value.boolean_value = value; + property->value.boolean_value = value ? SDL_TRUE : SDL_FALSE; return SDL_PrivateSetProperty(props, name, property); } @@ -461,10 +467,40 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_STRING) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: value = property->value.string_value; - } else { + break; + case SDL_PROPERTY_TYPE_NUMBER: + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_asprintf(&property->string_storage, "%" SDL_PRIs64 "", property->value.number_value); + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_OutOfMemory(); + } + } + break; + case SDL_PROPERTY_TYPE_FLOAT: + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_asprintf(&property->string_storage, "%f", property->value.float_value); + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_OutOfMemory(); + } + } + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = property->value.boolean_value ? "true" : "false"; + break; + default: SDL_SetError("Property %s isn't a string value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -502,10 +538,22 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_NUMBER) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = SDL_strtoll(property->value.string_value, NULL, 0); + break; + case SDL_PROPERTY_TYPE_NUMBER: value = property->value.number_value; - } else { - SDL_SetError("Property %s isn't a string value", name); + break; + case SDL_PROPERTY_TYPE_FLOAT: + value = (Sint64)SDL_round((double)property->value.float_value); + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = property->value.boolean_value; + break; + default: + SDL_SetError("Property %s isn't a number value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -543,10 +591,22 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_FLOAT) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = (float)SDL_atof(property->value.string_value); + break; + case SDL_PROPERTY_TYPE_NUMBER: + value = (float)property->value.number_value; + break; + case SDL_PROPERTY_TYPE_FLOAT: value = property->value.float_value; - } else { + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = (float)property->value.boolean_value; + break; + default: SDL_SetError("Property %s isn't a float value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -584,10 +644,22 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_BOOLEAN) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = SDL_GetStringBoolean(property->value.string_value, default_value); + break; + case SDL_PROPERTY_TYPE_NUMBER: + value = (property->value.number_value != 0); + break; + case SDL_PROPERTY_TYPE_FLOAT: + value = (property->value.float_value != 0.0f); + break; + case SDL_PROPERTY_TYPE_BOOLEAN: value = property->value.boolean_value; - } else { + break; + default: SDL_SetError("Property %s isn't a boolean value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index 3feca3e0429f8..7c05c240b9db5 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -81,7 +81,7 @@ static int properties_testBasic(void *arg) "Verify property, expected 0xabcd, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", "abcd"); SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "abcd") == 0, - "Verify string property, expected \"abcd\", got: %s", value_string); + "Verify string property, expected abcd, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 1234); SDLTest_AssertCheck(value_number == 1234, "Verify number property, expected 1234, got: %" SDL_PRIu64 "", value_number); @@ -125,7 +125,7 @@ static int properties_testBasic(void *arg) "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); SDLTest_AssertCheck(value_string != NULL && SDL_strcmp(value_string, "bar") == 0, - "Verify string property, expected \"bar\", got: %s", value_string); + "Verify string property, expected bar, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); SDLTest_AssertCheck(value_number == 0, "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); @@ -133,8 +133,8 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value_float == 0.0f, "Verify float property, expected 0, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check number value */ SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); @@ -146,21 +146,21 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1") == 0, + "Verify string property, expected 1, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); SDLTest_AssertCheck(value_number == 1, "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 0.0f, - "Verify float property, expected 0, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.0f, + "Verify float property, expected 1, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check float value */ SDLTest_AssertPass("Call to SDL_SetFloatProperty(\"foo\", 1)"); - SDL_SetFloatProperty(props, "foo", 1.0f); + SDL_SetFloatProperty(props, "foo", 1.75f); type = SDL_GetPropertyType(props, "foo"); SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT, "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_FLOAT, type); @@ -168,21 +168,21 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1.750000") == 0, + "Verify string property, expected 1.750000, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); - SDLTest_AssertCheck(value_number == 0, - "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + SDLTest_AssertCheck(value_number == 2, + "Verify number property, expected 2, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 1.0f, - "Verify string property, expected 1, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.75f, + "Verify float property, expected 1.75, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check boolean value */ SDLTest_AssertPass("Call to SDL_SetBooleanProperty(\"foo\", SDL_TRUE)"); - SDL_SetBooleanProperty(props, "foo", SDL_TRUE); + SDL_SetBooleanProperty(props, "foo", 3); /* Note we're testing non-true/false value here */ type = SDL_GetPropertyType(props, "foo"); SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_BOOLEAN, "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_BOOLEAN, type); @@ -190,14 +190,14 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "true") == 0, + "Verify string property, expected true, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); - SDLTest_AssertCheck(value_number == 0, - "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + SDLTest_AssertCheck(value_number == 1, + "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 0.0f, - "Verify string property, expected 0, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.0f, + "Verify float property, expected 1, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); SDLTest_AssertCheck(value_bool == SDL_TRUE, "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); From 1c4723ac66363c1b0dd08f2095869b810bfd16ec Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 21:37:00 -0800 Subject: [PATCH 339/725] SDL_CreateWindowFrom() now takes a set of properties that describe the native window and options. --- docs/README-migration.md | 5 ++++ include/SDL3/SDL_hints.h | 41 --------------------------- include/SDL3/SDL_video.h | 34 +++++++++++++++++----- src/dynapi/SDL_dynapi_procs.h | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 12 +++++--- src/video/cocoa/SDL_cocoawindow.h | 3 +- src/video/cocoa/SDL_cocoawindow.m | 29 +++++++++++++------ src/video/haiku/SDL_bvideo.cc | 1 - src/video/haiku/SDL_bwindow.cc | 33 --------------------- src/video/haiku/SDL_bwindow.h | 1 - src/video/kmsdrm/SDL_kmsdrmvideo.c | 6 ---- src/video/kmsdrm/SDL_kmsdrmvideo.h | 1 - src/video/psp/SDL_pspvideo.c | 6 ---- src/video/psp/SDL_pspvideo.h | 1 - src/video/raspberry/SDL_rpivideo.c | 6 ---- src/video/raspberry/SDL_rpivideo.h | 1 - src/video/vita/SDL_vitavideo.c | 6 ---- src/video/vita/SDL_vitavideo.h | 1 - src/video/windows/SDL_windowsopengl.c | 15 ---------- src/video/windows/SDL_windowsopengl.h | 1 - src/video/windows/SDL_windowswindow.c | 37 ++++++++++++------------ src/video/windows/SDL_windowswindow.h | 2 +- src/video/x11/SDL_x11window.c | 7 +++-- src/video/x11/SDL_x11window.h | 2 +- test/testautomation_hints.c | 2 -- test/testnative.c | 6 +++- 27 files changed, 94 insertions(+), 169 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 6e64bf126099c..d0eda28d593bf 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -559,7 +559,10 @@ The following hints have been removed: * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer * SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowFrom() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowFrom() * SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled +* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowFrom() * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend @@ -1260,6 +1263,8 @@ Rather than iterating over displays using display index, there is a new function SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithPosition() if you need to set the window position when creating it. +SDL_CreateWindowFrom() now takes a set of properties that describe the native window and options. + The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag. diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 91d7f0670ca5d..bac7e5086682b 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1801,47 +1801,6 @@ extern "C" { */ #define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" -/** -* A variable that is the address of another SDL_Window* (as a hex string formatted with "%p"). -* -* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has -* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly -* created SDL_Window: -* -* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is -* needed for example when sharing an OpenGL context across multiple windows. -* -* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for -* OpenGL rendering. -* -* This variable can be set to the following values: -* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should -* share a pixel format with. -*/ -#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT" - -/** - * When calling SDL_CreateWindowFrom(), make the window compatible with OpenGL. - * - * This variable can be set to the following values: - * "0" - Don't add any graphics flags to the SDL_WindowFlags - * "1" - Add SDL_WINDOW_OPENGL to the SDL_WindowFlags - * - * By default SDL will not make the foreign window compatible with OpenGL. - */ -#define SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL "SDL_VIDEO_FOREIGN_WINDOW_OPENGL" - -/** - * When calling SDL_CreateWindowFrom(), make the window compatible with Vulkan. - * - * This variable can be set to the following values: - * "0" - Don't add any graphics flags to the SDL_WindowFlags - * "1" - Add SDL_WINDOW_VULKAN to the SDL_WindowFlags - * - * By default SDL will not make the foreign window compatible with Vulkan. - */ -#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN "SDL_VIDEO_FOREIGN_WINDOW_VULKAN" - /** * A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries * diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index e8db562df8435..262409f9e7c66 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -868,14 +868,34 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *tit extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags); /** - * Create an SDL window from an existing native window. + * Create an SDL window from properties representing an existing native window. * - * In some cases (e.g. OpenGL) and on some platforms (e.g. Microsoft Windows) - * the hint `SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT` needs to be configured - * before using SDL_CreateWindowFrom(). + * These are the supported properties: * - * \param data a pointer to driver-dependent window creation data, typically - * your native window cast to a void* + * On macOS: + * ``` + * "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window + * "cocoa.view" (pointer) - optional, the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] + * ``` + * + * On Windows: + * ``` + * "win32.hwnd" (pointer) - the HWND associated with the window + * "win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows + * ``` + * + * On X11: + * ``` + * "x11.window" (number) - the X11 Window associated with the window + * ``` + * + * On all platforms: + * ``` + * "opengl" (boolean) - optional, true if the window will be used with OpenGL rendering + * "vulkan" (boolean) - optional, true if the window will be used with Vulkan rendering + * ``` + * + * \param props a set of properties describing the native window and options * \returns the window that was created or NULL on failure; call * SDL_GetError() for more information. * @@ -884,7 +904,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * \sa SDL_CreateWindow * \sa SDL_DestroyWindow */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowFrom(const void *data); +extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowFrom(SDL_PropertiesID props); /** * Get the numeric ID of a window. diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 90be91d078994..309249d97f9d5 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -157,7 +157,7 @@ SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTexture,(SDL_Renderer *a, Uint32 b, int c SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureFromSurface,(SDL_Renderer *a, SDL_Surface *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindow,(const char *a, int b, int c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_CreateWindowAndRenderer,(int a, int b, Uint32 c, SDL_Window **d, SDL_Renderer **e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowFrom,(const void *a),(a),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowFrom,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowWithPosition,(const char *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(SDL_bool,SDL_CursorVisible,(void),(),return) SDL_DYNAPI_PROC(void,SDL_DelEventWatch,(SDL_EventFilter a, void *b),(a,b),) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index fe3e5fd52a4de..cc9597f663305 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -223,7 +223,7 @@ struct SDL_VideoDevice * Window functions */ int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window); - int (*CreateSDLWindowFrom)(SDL_VideoDevice *_this, SDL_Window *window, const void *data); + int (*CreateSDLWindowFrom)(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); void (*SetWindowTitle)(SDL_VideoDevice *_this, SDL_Window *window); int (*SetWindowIcon)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); int (*SetWindowPosition)(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 16010b810eb46..712b21e095f75 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2092,11 +2092,15 @@ SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y return SDL_CreateWindowInternal(NULL, offset_x, offset_y, w, h, parent, flags); } -SDL_Window *SDL_CreateWindowFrom(const void *data) +SDL_Window *SDL_CreateWindowFrom(SDL_PropertiesID props) { SDL_Window *window; Uint32 flags = SDL_WINDOW_FOREIGN; + if (!props) { + SDL_InvalidParamError("props"); + return NULL; + } if (!_this) { SDL_UninitializedVideo(); return NULL; @@ -2106,7 +2110,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) return NULL; } - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, SDL_FALSE)) { + if (SDL_GetBooleanProperty(props, "opengl", SDL_FALSE)) { if (!_this->GL_CreateContext) { SDL_ContextNotSupported("OpenGL"); return NULL; @@ -2117,7 +2121,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) flags |= SDL_WINDOW_OPENGL; } - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN, SDL_FALSE)) { + if (SDL_GetBooleanProperty(props, "vulkan", SDL_FALSE)) { if (!_this->Vulkan_CreateSurface) { SDL_ContextNotSupported("Vulkan"); return NULL; @@ -2149,7 +2153,7 @@ SDL_Window *SDL_CreateWindowFrom(const void *data) } _this->windows = window; - if (_this->CreateSDLWindowFrom(_this, window, data) < 0) { + if (_this->CreateSDLWindowFrom(_this, window, props) < 0) { SDL_DestroyWindow(window); return NULL; } diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 8e4158cf6724a..e03adb3504e89 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -142,8 +142,7 @@ typedef enum @end extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, - const void *data); +extern int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); extern void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int Cocoa_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); extern int Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index afbfb4352d211..ee99090591a16 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2007,22 +2007,35 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) +int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) { @autoreleasepool { - NSView *nsview = nil; + const void *data = SDL_GetProperty(props, "data", NULL); NSWindow *nswindow = nil; + NSView *nsview = nil; NSString *title; BOOL highdpi; - if ([(__bridge id)data isKindOfClass:[NSWindow class]]) { - nswindow = (__bridge NSWindow *)data; + if (data) { + if ([(__bridge id)data isKindOfClass:[NSWindow class]]) { + nswindow = (__bridge NSWindow *)data; + } else if ([(__bridge id)data isKindOfClass:[NSView class]]) { + nsview = (__bridge NSView *)data; + } else { + SDL_assert(false); + } + } else { + nswindow = (__bridge NSWindow *)SDL_GetProperty(props, "cocoa.window", NULL); + nsview = (__bridge NSView *)SDL_GetProperty(props, "cocoa.view", NULL); + } + if (nswindow && !nsview) { nsview = [nswindow contentView]; - } else if ([(__bridge id)data isKindOfClass:[NSView class]]) { - nsview = (__bridge NSView *)data; + } + if (nsview && !nswindow) { nswindow = [nsview window]; - } else { - SDL_assert(false); + } + if (!nswindow) { + return SDL_SetError("Couldn't find property cocoa.window"); } /* Query the title from the existing window */ diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index b97ee5a01c24a..21d1b864cb8d5 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -75,7 +75,6 @@ static SDL_VideoDevice * HAIKU_CreateDevice(void) device->PumpEvents = HAIKU_PumpEvents; device->CreateSDLWindow = HAIKU_CreateWindow; - device->CreateSDLWindowFrom = HAIKU_CreateWindowFrom; device->SetWindowTitle = HAIKU_SetWindowTitle; device->SetWindowPosition = HAIKU_SetWindowPosition; device->SetWindowSize = HAIKU_SetWindowSize; diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index bb99a0fb995ca..15c1d32fa220d 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -86,39 +86,6 @@ int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) { return 0; } -int HAIKU_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window * window, const void *data) { - - SDL_BWin *otherBWin = (SDL_BWin*)data; - if (!otherBWin->LockLooper()) { - return -1; - } - - /* Create the new window and initialize its members */ - window->x = (int)otherBWin->Frame().left; - window->y = (int)otherBWin->Frame().top; - window->w = (int)otherBWin->Frame().Width(); - window->h = (int)otherBWin->Frame().Height(); - - /* Set SDL flags */ - if (!(otherBWin->Flags() & B_NOT_RESIZABLE)) { - window->flags |= SDL_WINDOW_RESIZABLE; - } - - /* If we are out of memory, return the error code */ - if (_InitWindow(_this, window) < 0) { - return -1; - } - - /* TODO: Add any other SDL-supported window attributes here */ - _ToBeWin(window)->SetTitle(otherBWin->Title()); - - /* Start window loop and unlock the other window */ - _ToBeWin(window)->Show(); - - otherBWin->UnlockLooper(); - return 0; -} - void HAIKU_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window * window) { BMessage msg(BWIN_SET_TITLE); msg.AddString("window-title", window->title); diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index 400fa9467a5a4..b49ab92764266 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -25,7 +25,6 @@ #include "../SDL_sysvideo.h" extern int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int HAIKU_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); extern void HAIKU_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int HAIKU_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); extern void HAIKU_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index ca283c1fe8b37..07598ab26cb51 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -281,7 +281,6 @@ static SDL_VideoDevice *KMSDRM_CreateDevice(void) device->GetDisplayModes = KMSDRM_GetDisplayModes; device->SetDisplayMode = KMSDRM_SetDisplayMode; device->CreateSDLWindow = KMSDRM_CreateWindow; - device->CreateSDLWindowFrom = KMSDRM_CreateWindowFrom; device->SetWindowTitle = KMSDRM_SetWindowTitle; device->SetWindowPosition = KMSDRM_SetWindowPosition; device->SetWindowSize = KMSDRM_SetWindowSize; @@ -1584,11 +1583,6 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return ret; } -int KMSDRM_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) -{ - return -1; -} - void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { } diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index d488fc84aed89..9807cf4b3943e 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -122,7 +122,6 @@ void KMSDRM_VideoQuit(SDL_VideoDevice *_this); int KMSDRM_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -int KMSDRM_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 637d9c138570d..5a2091e3b82ae 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -89,7 +89,6 @@ static SDL_VideoDevice *PSP_Create() device->GetDisplayModes = PSP_GetDisplayModes; device->SetDisplayMode = PSP_SetDisplayMode; device->CreateSDLWindow = PSP_CreateWindow; - device->CreateSDLWindowFrom = PSP_CreateWindowFrom; device->SetWindowTitle = PSP_SetWindowTitle; device->SetWindowPosition = PSP_SetWindowPosition; device->SetWindowSize = PSP_SetWindowSize; @@ -205,11 +204,6 @@ int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return 0; } -int PSP_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) -{ - return SDL_Unsupported(); -} - void PSP_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { } diff --git a/src/video/psp/SDL_pspvideo.h b/src/video/psp/SDL_pspvideo.h index 429ad98d63bf0..6a680d9eb58f3 100644 --- a/src/video/psp/SDL_pspvideo.h +++ b/src/video/psp/SDL_pspvideo.h @@ -50,7 +50,6 @@ void PSP_VideoQuit(SDL_VideoDevice *_this); int PSP_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int PSP_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -int PSP_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); void PSP_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int PSP_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void PSP_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index e48bc1e68f3bf..e167265346162 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -101,7 +101,6 @@ static SDL_VideoDevice *RPI_Create() device->VideoInit = RPI_VideoInit; device->VideoQuit = RPI_VideoQuit; device->CreateSDLWindow = RPI_CreateWindow; - device->CreateSDLWindowFrom = RPI_CreateWindowFrom; device->SetWindowTitle = RPI_SetWindowTitle; device->SetWindowPosition = RPI_SetWindowPosition; device->SetWindowSize = RPI_SetWindowSize; @@ -339,11 +338,6 @@ void RPI_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -int RPI_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) -{ - return -1; -} - void RPI_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { } diff --git a/src/video/raspberry/SDL_rpivideo.h b/src/video/raspberry/SDL_rpivideo.h index b620d5d1305b9..f1d72b7ce05d6 100644 --- a/src/video/raspberry/SDL_rpivideo.h +++ b/src/video/raspberry/SDL_rpivideo.h @@ -64,7 +64,6 @@ void RPI_VideoQuit(SDL_VideoDevice *_this); int RPI_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int RPI_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -int RPI_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); void RPI_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int RPI_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void RPI_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index f3fd1f94bc1e2..884c95fe33da3 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -105,7 +105,6 @@ static SDL_VideoDevice *VITA_Create() device->VideoInit = VITA_VideoInit; device->VideoQuit = VITA_VideoQuit; device->CreateSDLWindow = VITA_CreateWindow; - device->CreateSDLWindowFrom = VITA_CreateWindowFrom; device->SetWindowTitle = VITA_SetWindowTitle; device->SetWindowPosition = VITA_SetWindowPosition; device->SetWindowSize = VITA_SetWindowSize; @@ -293,11 +292,6 @@ int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return 0; } -int VITA_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) -{ - return -1; -} - void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { } diff --git a/src/video/vita/SDL_vitavideo.h b/src/video/vita/SDL_vitavideo.h index aa4be1ba9ed17..a4cf79dafbff2 100644 --- a/src/video/vita/SDL_vitavideo.h +++ b/src/video/vita/SDL_vitavideo.h @@ -63,7 +63,6 @@ void VITA_VideoQuit(SDL_VideoDevice *_this); int VITA_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int VITA_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -int VITA_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int VITA_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void VITA_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 41103805e4f41..3b6c879e4efa2 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -893,21 +893,6 @@ int WIN_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context) return 0; } -SDL_bool WIN_GL_SetPixelFormatFrom(SDL_VideoDevice *_this, SDL_Window *fromWindow, SDL_Window *toWindow) -{ - HDC hfromdc = fromWindow->driverdata->hdc; - HDC htodc = toWindow->driverdata->hdc; - - /* get the pixel format of the fromWindow */ - int pixel_format = GetPixelFormat(hfromdc); - PIXELFORMATDESCRIPTOR pfd; - SDL_memset(&pfd, 0, sizeof(pfd)); - DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd); - - /* set the pixel format of the toWindow */ - return SetPixelFormat(htodc, pixel_format, &pfd); -} - #endif /* SDL_VIDEO_OPENGL_WGL */ #endif /* SDL_VIDEO_DRIVER_WINDOWS */ diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h index dc1d140de3df0..4597d8ee3af90 100644 --- a/src/video/windows/SDL_windowsopengl.h +++ b/src/video/windows/SDL_windowsopengl.h @@ -115,7 +115,6 @@ extern int WIN_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval); extern int WIN_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); extern int WIN_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context); extern void WIN_GL_InitExtensions(SDL_VideoDevice *_this); -extern SDL_bool WIN_GL_SetPixelFormatFrom(SDL_VideoDevice *_this, SDL_Window *fromWindow, SDL_Window *toWindow); #ifndef WGL_ARB_pixel_format #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index ebcabd24eac8b..66b5701498a8c 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -644,16 +644,20 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return 0; } -int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) +int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) { #if defined(__XBOXONE__) || defined(__XBOXSERIES__) return -1; #else - HWND hwnd = (HWND)data; + HWND hwnd = (HWND)SDL_GetProperty(props, "win32.hwnd", SDL_GetProperty(props, "data", NULL)); LPTSTR title; int titleLen; SDL_bool isstack; + if (!hwnd) { + return SDL_SetError("Couldn't find property win32.hwnd"); + } + /* Query the title from the existing window */ titleLen = GetWindowTextLength(hwnd); title = SDL_small_alloc(TCHAR, titleLen + 1, &isstack); @@ -675,23 +679,18 @@ int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void #ifdef SDL_VIDEO_OPENGL_WGL { - const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT); - if (hint) { - /* This hint is a pointer (in string form) of the address of - the window to share a pixel format with - */ - SDL_Window *otherWindow = NULL; - (void)SDL_sscanf(hint, "%p", (void **)&otherWindow); - - /* Do some error checking on the pointer */ - if (otherWindow && otherWindow->magic == &_this->window_magic) { - /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */ - if (otherWindow->flags & SDL_WINDOW_OPENGL) { - window->flags |= SDL_WINDOW_OPENGL; - if (!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) { - return -1; - } - } + HWND share_hwnd = (HWND)SDL_GetProperty(props, "win32.pixel_format_hwnd", NULL); + if (share_hwnd) { + HDC hdc = GetDC(share_hwnd); + int pixel_format = GetPixelFormat(hdc); + PIXELFORMATDESCRIPTOR pfd; + + SDL_zero(pfd); + DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); + ReleaseDC(share_hwnd, hdc); + + if (!SetPixelFormat(window->driverdata->hdc, pixel_format, &pfd)) { + return WIN_SetError("SetPixelFormat()"); } } else if (window->flags & SDL_WINDOW_OPENGL) { /* Try to set up the pixel format, if it hasn't been set by the application */ diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 5b2c0260c0ea0..a3e0c84561a14 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -76,7 +76,7 @@ struct SDL_WindowData }; extern int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); +extern int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); extern void WIN_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int WIN_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); extern int WIN_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 0997fc7532455..f8c7d5d8ba380 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -777,9 +777,12 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return 0; } -int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data) +int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) { - Window w = (Window)data; + Window w = (Window)SDL_GetNumberProperty(props, "x11.window", (Window)SDL_GetProperty(props, "data", NULL)); + if (!w) { + return SDL_SetError("Couldn't find property x11.window"); + } window->title = X11_GetWindowTitle(_this, w); diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 03b8b8cdee452..65afecc30d533 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -85,7 +85,7 @@ extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 fla extern Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwindow); extern int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data); +extern int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); extern char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow); extern void X11_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); diff --git a/test/testautomation_hints.c b/test/testautomation_hints.c index 0a5ec42583042..0e22b70747430 100644 --- a/test/testautomation_hints.c +++ b/test/testautomation_hints.c @@ -24,7 +24,6 @@ static const char *HintsEnum[] = { SDL_HINT_VIDEO_ALLOW_SCREENSAVER, SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, - SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_X11_XRANDR, SDL_HINT_XINPUT_ENABLED, @@ -47,7 +46,6 @@ static const char *HintsVerbose[] = { "SDL_VIDEO_ALLOW_SCREENSAVER", "SDL_VIDEO_MAC_FULLSCREEN_SPACES", "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", - "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT", "SDL_VIDEO_WIN_D3DCOMPILER", "SDL_VIDEO_X11_XRANDR", "SDL_XINPUT_ENABLED" diff --git a/test/testnative.c b/test/testnative.c index cc5b1b071ad98..212a6f7a18663 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -100,6 +100,7 @@ int main(int argc, char *argv[]) { int i, done; const char *driver; + SDL_PropertiesID props; SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *sprite; @@ -146,7 +147,10 @@ int main(int argc, char *argv[]) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create native window\n"); quit(3); } - window = SDL_CreateWindowFrom(native_window); + props = SDL_CreateProperties(); + SDL_SetProperty(props, "data", native_window); + window = SDL_CreateWindowFrom(props); + SDL_DestroyProperties(props); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window: %s\n", SDL_GetError()); quit(4); From e5ffd6d8ebb4a7eea3e88cfc9589167846de9d3a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 13 Nov 2023 13:01:25 -0500 Subject: [PATCH 340/725] include: Removed `\link` and `\endlink` Doxygen tags. --- include/SDL3/SDL_pen.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index 0f48da90abac4..e5e6731ee5a01 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -72,15 +72,15 @@ typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a sessio * Not all pens/backends support all axes: unsupported entries are always "0.0f". * * To convert angles for tilt and rotation into vector representation, use - * \link SDL_sinf \endlink on the XTILT, YTILT, or ROTATION component, e.g., "SDL_sinf(xtilt * SDL_PI_F / 180.0)". + * SDL_sinf on the XTILT, YTILT, or ROTATION component, e.g., "SDL_sinf(xtilt * SDL_PI_F / 180.0)". */ typedef enum { SDL_PEN_AXIS_PRESSURE = 0, /**< Pen pressure. Unidirectional: 0..1.0 */ SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0..90.0 (left-to-right). - The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */ + The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */ SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0..90.0 (top-to-down). - The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */ + The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */ SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0..1.0 */ SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180..179.9 (clockwise, 0 is facing up, -180.0 is facing down). */ SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0..1.0 */ @@ -256,7 +256,7 @@ typedef struct SDL_PenCapabilityInfo * \param instance_id The pen to query. * \param[out] capabilities Detail information about pen capabilities, such as the number of buttons * - * \returns a set of capability flags, cf. \link SDL_PEN_CAPABILITIES \endlink. Returns 0 on error + * \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES. Returns 0 on error * (cf. ::SDL_GetError()) * * \since This function is available since SDL 3.TBD From 8766aa39d6cd2969793f7fb94b48934732afc661 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 13 Nov 2023 13:03:42 -0500 Subject: [PATCH 341/725] Sync wiki -> headers. --- include/SDL3/SDL_pen.h | 76 ++++++++++++++++------------------- include/SDL3/SDL_properties.h | 31 +++++++++----- include/SDL3/SDL_render.h | 5 +++ include/SDL3/SDL_video.h | 21 ++++++++-- 4 files changed, 78 insertions(+), 55 deletions(-) diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index e5e6731ee5a01..9d73406cf2467 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -147,15 +147,13 @@ typedef enum /** * Retrieves all pens that are connected to the system. * - * Yields an array of ::SDL_PenID values. These identify and track pens throughout a session. - * To track pens across sessions (program restart), use ::SDL_GUID . + * Yields an array of ::SDL_PenID values. These identify and track pens + * throughout a session. To track pens across sessions (program restart), use + * ::SDL_GUID . * - * \param[out] count The number of pens in the array (number of array elements minus 1, i.e., not - * counting the terminator 0). - * - * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. - * The array must be freed with ::SDL_free(). - * On a NULL return, ::SDL_GetError() is set. + * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. The + * array must be freed with ::SDL_free(). On a NULL return, + * ::SDL_GetError() is set. * * \since This function is available since SDL 3.TBD */ @@ -168,15 +166,11 @@ extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); * default values. * * \param instance_id The pen to query. - * \param[out] x Out-mode parameter for pen x coordinate. May be NULL. - * \param[out] y Out-mode parameter for pen y coordinate. May be NULL. - * \param[out] axes Out-mode parameter for axis information. May be null. The axes are in the same order as for - * ::SDL_PenAxis . * \param num_axes Maximum number of axes to write to "axes". - * - * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK etc.), - * possibly ::SDL_PEN_DOWN_MASK, and exactly one of - * ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see ::SDL_GetError()). + * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK + * etc.), possibly ::SDL_PEN_DOWN_MASK, and exactly one of + * ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see + * ::SDL_GetError()). * * \since This function is available since SDL 3.TBD */ @@ -186,12 +180,12 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, * Retrieves an ::SDL_PenID for the given ::SDL_GUID. * * \param guid A pen GUID. - * - * \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching SDL_PenID. + * \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching + * SDL_PenID. * * \since This function is available since SDL 3.TBD * - * \sa SDL_GUID() + * \sa SDL_GUID */ extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); @@ -199,25 +193,24 @@ extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); * Retrieves the ::SDL_GUID for a given ::SDL_PenID. * * \param instance_id The pen to query. - * * \returns The corresponding pen GUID; persistent across multiple sessions. - * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. + * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. * * \since This function is available since SDL 3.TBD * - * \sa SDL_PenForID() + * \sa SDL_PenForID */ extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id); /** * Checks whether a pen is still attached. * - * If a pen is detached, it will not show up for ::SDL_GetPens(). - * Other operations will still be available but may return default values. + * If a pen is detached, it will not show up for ::SDL_GetPens(). Other + * operations will still be available but may return default values. * * \param instance_id A pen ID. - * \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is attached, or - * SDL_FALSE otherwise. + * \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is + * attached, or SDL_FALSE otherwise. * * \since This function is available since SDL 3.TBD */ @@ -227,14 +220,13 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); * Retrieves a human-readable description for a ::SDL_PenID. * * \param instance_id The pen to query. - * - * \returns A string that contains the name of the pen, intended for human consumption. - * The string might or might not be localised, depending on platform settings. - * It is not guaranteed to be unique; use ::SDL_GetPenGUID() for (best-effort) - * unique identifiers. - * The pointer is managed by the SDL pen subsystem and must not be deallocated. - * The pointer remains valid until SDL is shut down. - * Returns NULL on error (cf. ::SDL_GetError()) + * \returns A string that contains the name of the pen, intended for human + * consumption. The string might or might not be localised, depending + * on platform settings. It is not guaranteed to be unique; use + * ::SDL_GetPenGUID() for (best-effort) unique identifiers. The + * pointer is managed by the SDL pen subsystem and must not be + * deallocated. The pointer remains valid until SDL is shut down. + * Returns NULL on error (cf. ::SDL_GetError()) * * \since This function is available since SDL 3.TBD */ @@ -254,10 +246,7 @@ typedef struct SDL_PenCapabilityInfo * Retrieves capability flags for a given ::SDL_PenID. * * \param instance_id The pen to query. - * \param[out] capabilities Detail information about pen capabilities, such as the number of buttons - * - * \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES. Returns 0 on error - * (cf. ::SDL_GetError()) + * \returns a set of capability flags, cf. \link SDL_PEN_CAPABILITIES * * \since This function is available since SDL 3.TBD */ @@ -267,10 +256,13 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL * Retrieves the pen type for a given ::SDL_PenID. * * \param instance_id The pen to query. - * \returns The corresponding pen type (cf. ::SDL_PenSubtype) or 0 on error. Note that the pen type does not - * dictate whether the pen tip is ::SDL_PEN_TIP_INK or ::SDL_PEN_TIP_ERASER; to determine whether a pen - * is being used for drawing or in eraser mode, check either the pen tip on ::SDL_EVENT_PEN_DOWN, or the - * flag ::SDL_PEN_ERASER_MASK in the pen state. + * \returns The corresponding pen type (cf. ::SDL_PenSubtype) or 0 on error. + * Note that the pen type does not dictate whether the pen tip is + * ::SDL_PEN_TIP_INK or ::SDL_PEN_TIP_ERASER; to determine whether a + * pen is being used for drawing or in eraser mode, check either the + * pen tip on ::SDL_EVENT_PEN_DOWN, or the flag ::SDL_PEN_ERASER_MASK + * in the pen state. + * * \since This function is available since SDL 3.TBD */ extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id); diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index eedc178806f47..4e535aaacce7c 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -231,7 +231,8 @@ extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const * * \param props the properties to query * \param name the name of the property to query - * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is not set. + * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is + * not set. * * \threadsafety It is safe to call this function from any thread. * @@ -250,7 +251,8 @@ extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID pr * \param props the properties to query * \param name the name of the property to query * \param default_value the default value of the property - * \returns the value of the property, or `default_value` if it is not set or not a pointer property. + * \returns the value of the property, or `default_value` if it is not set or + * not a pointer property. * * \threadsafety It is safe to call this function from any thread, although * the data returned is not protected and could potentially be @@ -271,7 +273,8 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char * \param props the properties to query * \param name the name of the property to query * \param default_value the default value of the property - * \returns the value of the property, or `default_value` if it is not set or not a string property. + * \returns the value of the property, or `default_value` if it is not set or + * not a string property. * * \threadsafety It is safe to call this function from any thread. * @@ -285,12 +288,14 @@ extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props /** * Get a number property on a set of properties * - * You can use SDL_GetPropertyType() to query whether the property exists and is a number property. + * You can use SDL_GetPropertyType() to query whether the property exists and + * is a number property. * * \param props the properties to query * \param name the name of the property to query * \param default_value the default value of the property - * \returns the value of the property, or `default_value` if it is not set or not a number property. + * \returns the value of the property, or `default_value` if it is not set or + * not a number property. * * \threadsafety It is safe to call this function from any thread. * @@ -304,12 +309,14 @@ extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, con /** * Get a floating point property on a set of properties * - * You can use SDL_GetPropertyType() to query whether the property exists and is a floating point property. + * You can use SDL_GetPropertyType() to query whether the property exists and + * is a floating point property. * * \param props the properties to query * \param name the name of the property to query * \param default_value the default value of the property - * \returns the value of the property, or `default_value` if it is not set or not a float property. + * \returns the value of the property, or `default_value` if it is not set or + * not a float property. * * \threadsafety It is safe to call this function from any thread. * @@ -323,12 +330,14 @@ extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const /** * Get a boolean property on a set of properties * - * You can use SDL_GetPropertyType() to query whether the property exists and is a boolean property. + * You can use SDL_GetPropertyType() to query whether the property exists and + * is a boolean property. * * \param props the properties to query * \param name the name of the property to query * \param default_value the default value of the property - * \returns the value of the property, or `default_value` if it is not set or not a float property. + * \returns the value of the property, or `default_value` if it is not set or + * not a float property. * * \threadsafety It is safe to call this function from any thread. * @@ -356,10 +365,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); typedef void (SDLCALL *SDL_EnumeratePropertiesCallback)(void *userdata, SDL_PropertiesID props, const char *name); + /** * Enumerate the properties on a set of properties * - * The callback function is called for each property on the set of properties. The properties are locked during enumeration. + * The callback function is called for each property on the set of properties. + * The properties are locked during enumeration. * * \param props the properties to query * \param callback the function to call for each property diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 72cb5d263d815..86a2abb1a050e 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -310,6 +310,7 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * Get the properties associated with a renderer. * * The following properties are provided by SDL: + * * ``` * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer @@ -423,6 +424,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * The following properties are provided by SDL: * * With the direct3d11 renderer: + * * ``` * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture @@ -430,6 +432,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * ``` * * With the direct3d12 renderer: + * * ``` * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture @@ -437,6 +440,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * ``` * * With the opengl renderer: + * * ``` * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture @@ -446,6 +450,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * ``` * * With the opengles2 renderer: + * * ``` * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 262409f9e7c66..b75ffda4e1e39 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -868,28 +868,33 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *tit extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags); /** - * Create an SDL window from properties representing an existing native window. + * Create an SDL window from properties representing an existing native + * window. * * These are the supported properties: * * On macOS: + * * ``` * "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window * "cocoa.view" (pointer) - optional, the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] * ``` * * On Windows: + * * ``` * "win32.hwnd" (pointer) - the HWND associated with the window * "win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows * ``` * * On X11: + * * ``` * "x11.window" (number) - the X11 Window associated with the window * ``` * * On all platforms: + * * ``` * "opengl" (boolean) - optional, true if the window will be used with OpenGL rendering * "vulkan" (boolean) - optional, true if the window will be used with Vulkan rendering @@ -957,18 +962,21 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * The following properties are provided by SDL: * * On Android: + * * ``` * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window * ``` * * On iOS: + * * ``` * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window * ``` * * On KMS/DRM: + * * ``` * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX) * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window @@ -976,12 +984,14 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * ``` * * On macOS: + * * ``` * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window * ``` * * On Vivante: + * * ``` * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window @@ -989,11 +999,13 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * ``` * * On UWP: + * * ``` * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window * ``` * * On Windows: + * * ``` * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window @@ -1001,6 +1013,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * ``` * * On Wayland: + * * ``` * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window @@ -1012,10 +1025,12 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode * ``` * - * Note: The xdg_* window objects do not internally persist across window show/hide calls. - * They will be null if the window is hidden and must be queried each time it is shown. + * Note: The xdg_* window objects do not internally persist across window + * show/hide calls. They will be null if the window is hidden and must be + * queried each time it is shown. * * On X11: + * * ``` * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window * "SDL.window.x11.screen" (number) - the screen number associated with the window From 876c97454a954a70da8b8b3d8b09b52674534062 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Sat, 26 Nov 2022 18:37:10 +0200 Subject: [PATCH 342/725] Cleanup WIN_CreateCursor() code a bit Closes #6476 --- src/video/SDL_shape.c | 10 ++- src/video/SDL_shape_internals.h | 2 +- src/video/windows/SDL_windowsmouse.c | 94 +++++++++++++--------------- src/video/x11/SDL_x11shape.c | 2 +- 4 files changed, 52 insertions(+), 56 deletions(-) diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index 2362ed7f7f380..cb8d7c2f49ba1 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -55,14 +55,15 @@ SDL_bool SDL_IsShapedWindow(const SDL_Window *window) return (window->shaper != NULL); } -/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */ -void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb) +/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte and alignBytes scan line alignment. */ +void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8* bitmap, Uint8 ppb, Uint8 alignBytes) { int x = 0; int y = 0; Uint8 r = 0, g = 0, b = 0, alpha = 0; Uint32 mask_value = 0; - size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb; + int bytes_per_scanline; + Uint8 *bitmap_scanline; SDL_Color key; @@ -70,6 +71,9 @@ void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint SDL_LockSurface(shape); } + bytes_per_scanline = (shape->w + (ppb - 1)) / ppb; + bytes_per_scanline = (bytes_per_scanline + (alignBytes - 1)) & ~(alignBytes - 1); + SDL_memset(bitmap, 0, shape->h * bytes_per_scanline); for (y = 0; y < shape->h; y++) { diff --git a/src/video/SDL_shape_internals.h b/src/video/SDL_shape_internals.h index fa8e90adbf890..85e164c5b6d7a 100644 --- a/src/video/SDL_shape_internals.h +++ b/src/video/SDL_shape_internals.h @@ -51,7 +51,7 @@ typedef struct SDL_ShapeTree typedef void (*SDL_TraversalFunction)(SDL_ShapeTree *, void *); -extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb); +extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb, Uint8 alignBytes); extern SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape); extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure); extern void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 44491d37abcbb..b9d77af31f077 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -26,6 +26,8 @@ #include "../../events/SDL_mouse_c.h" +#include "../SDL_shape_internals.h" + DWORD SDL_last_warp_time = 0; HCURSOR SDL_cursor = NULL; static SDL_Cursor *SDL_blank_cursor = NULL; @@ -86,81 +88,71 @@ static SDL_Cursor *WIN_CreateDefaultCursor() static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) { - /* msdn says cursor mask has to be padded out to word alignment. Not sure - if that means machine word or WORD, but this handles either case. */ - const size_t pad = (sizeof(size_t) * 8); /* 32 or 64, or whatever. */ - SDL_Cursor *cursor; HICON hicon; - HICON hcursor; - HDC hdc; - BITMAPV4HEADER bmh; - LPVOID pixels; - LPVOID maskbits; - size_t maskbitslen; - SDL_bool isstack; + SDL_Cursor *cursor; + BITMAPV5HEADER bmh; ICONINFO ii; + HBITMAP colorBitmap = NULL, maskBitmap = NULL; + LPVOID colorBits, maskBits; + int maskPitch; SDL_zero(bmh); - bmh.bV4Size = sizeof(bmh); - bmh.bV4Width = surface->w; - bmh.bV4Height = -surface->h; /* Invert the image */ - bmh.bV4Planes = 1; - bmh.bV4BitCount = 32; - bmh.bV4V4Compression = BI_BITFIELDS; - bmh.bV4AlphaMask = 0xFF000000; - bmh.bV4RedMask = 0x00FF0000; - bmh.bV4GreenMask = 0x0000FF00; - bmh.bV4BlueMask = 0x000000FF; - - maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h; - maskbits = SDL_small_alloc(Uint8, maskbitslen, &isstack); - if (!maskbits) { - SDL_OutOfMemory(); + bmh.bV5Size = sizeof(bmh); + bmh.bV5Width = surface->w; + bmh.bV5Height = -surface->h; /* Invert the image to make it top-down. */ + bmh.bV5Planes = 1; + bmh.bV5BitCount = surface->format->BitsPerPixel; + bmh.bV5Compression = BI_BITFIELDS; + bmh.bV5RedMask = surface->format->Rmask; + bmh.bV5GreenMask = surface->format->Gmask; + bmh.bV5BlueMask = surface->format->Bmask; + bmh.bV5AlphaMask = surface->format->Amask; + + colorBitmap = CreateDIBSection(NULL, (BITMAPINFO *) &bmh, DIB_RGB_COLORS, &colorBits, NULL, 0); + + if (!colorBitmap || !colorBits) { + WIN_SetError("CreateDIBSection()"); return NULL; } - /* AND the cursor against full bits: no change. We already have alpha. */ - SDL_memset(maskbits, 0xFF, maskbitslen); + SDL_memcpy(colorBits, surface->pixels, surface->pitch * surface->h); + + /* Scan lines in 1 bpp mask should be aligned to WORD boundary. */ + maskPitch = (((surface->w + 15) & ~15) / 8); + if ((maskBits = SDL_stack_alloc(Uint8, maskPitch * surface->h))) { + SDL_WindowShapeMode mode = { ShapeModeDefault }; + SDL_CalculateShapeBitmap(mode, surface, maskBits, 8, sizeof(WORD)); + maskBitmap = CreateBitmap(surface->w, surface->h, 1, 1, maskBits); + SDL_stack_free(maskBits); + } - hdc = GetDC(NULL); SDL_zero(ii); ii.fIcon = FALSE; ii.xHotspot = (DWORD)hot_x; ii.yHotspot = (DWORD)hot_y; - ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0); - ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits); - ReleaseDC(NULL, hdc); - SDL_small_free(maskbits, isstack); - - SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); - SDL_assert(surface->pitch == surface->w * 4); - SDL_memcpy(pixels, surface->pixels, (size_t)surface->h * surface->pitch); + ii.hbmColor = colorBitmap; + ii.hbmMask = maskBitmap; hicon = CreateIconIndirect(&ii); - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask); - - if (!hicon) { - WIN_SetError("CreateIconIndirect()"); - return NULL; + if (colorBitmap) { + DeleteObject(colorBitmap); } - /* The cursor returned by CreateIconIndirect does not respect system cursor size - preference, use CopyImage to duplicate the cursor with desired sizes */ - hcursor = CopyImage(hicon, IMAGE_CURSOR, surface->w, surface->h, 0); - DestroyIcon(hicon); + if (maskBitmap) { + DeleteObject(maskBitmap); + } - if (!hcursor) { - WIN_SetError("CopyImage()"); + if (!hicon) { + WIN_SetError("CreateIconIndirect()"); return NULL; } cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { - cursor->driverdata = hcursor; + cursor->driverdata = hicon; } else { - DestroyIcon(hcursor); + DestroyIcon(hicon); SDL_OutOfMemory(); } diff --git a/src/video/x11/SDL_x11shape.c b/src/video/x11/SDL_x11shape.c index 373d6eba1ae4b..f1fd20e145a2e 100644 --- a/src/video/x11/SDL_x11shape.c +++ b/src/video/x11/SDL_x11shape.c @@ -81,7 +81,7 @@ int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowS data = shaper->driverdata; /* Assume that shaper->alphacutoff already has a value, because SDL_SetWindowShape() should have given it one. */ - SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8); + SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8, 1); windowdata = shaper->window->driverdata; shapemask = X11_XCreateBitmapFromData(windowdata->videodata->display, windowdata->xwindow, data->bitmap, shaper->window->w, shaper->window->h); From 91460fc13dec9bf5ad53ea26fdc00acc73abdda6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 13 Nov 2023 15:40:55 -0500 Subject: [PATCH 343/725] include: Fixed up documentation in SDL_pen.h --- include/SDL3/SDL_pen.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index 9d73406cf2467..63340a7cad919 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -151,11 +151,13 @@ typedef enum * throughout a session. To track pens across sessions (program restart), use * ::SDL_GUID . * + * \param count The number of pens in the array (number of array elements minus 1, i.e., not + * counting the terminator 0). * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. The * array must be freed with ::SDL_free(). On a NULL return, * ::SDL_GetError() is set. * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); @@ -166,13 +168,16 @@ extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); * default values. * * \param instance_id The pen to query. + * \param x Out-mode parameter for pen x coordinate. May be NULL. + * \param y Out-mode parameter for pen y coordinate. May be NULL. + * \param axes Out-mode parameter for axis information. May be null. The axes are in the same order as ::SDL_PenAxis. * \param num_axes Maximum number of axes to write to "axes". * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK * etc.), possibly ::SDL_PEN_DOWN_MASK, and exactly one of * ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see * ::SDL_GetError()). * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes); @@ -183,7 +188,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, * \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching * SDL_PenID. * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 * * \sa SDL_GUID */ @@ -196,7 +201,7 @@ extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); * \returns The corresponding pen GUID; persistent across multiple sessions. * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 * * \sa SDL_PenForID */ @@ -212,7 +217,7 @@ extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id); * \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is * attached, or SDL_FALSE otherwise. * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); @@ -228,7 +233,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); * deallocated. The pointer remains valid until SDL is shut down. * Returns NULL on error (cf. ::SDL_GetError()) * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC const char *SDLCALL SDL_GetPenName(SDL_PenID instance_id); @@ -246,9 +251,10 @@ typedef struct SDL_PenCapabilityInfo * Retrieves capability flags for a given ::SDL_PenID. * * \param instance_id The pen to query. - * \returns a set of capability flags, cf. \link SDL_PEN_CAPABILITIES + * \param capabilities Detail information about pen capabilities, such as the number of buttons + * \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *capabilities); @@ -263,7 +269,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL * pen tip on ::SDL_EVENT_PEN_DOWN, or the flag ::SDL_PEN_ERASER_MASK * in the pen state. * - * \since This function is available since SDL 3.TBD + * \since This function is available since SDL 3.0.0 */ extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id); From dd8ab67bd992de6000d89ad613a52a71dd41a9c2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 13 Nov 2023 15:46:29 -0500 Subject: [PATCH 344/725] Sync wiki -> headers. --- include/SDL3/SDL_pen.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index 63340a7cad919..0edd3512b1fa8 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -151,8 +151,8 @@ typedef enum * throughout a session. To track pens across sessions (program restart), use * ::SDL_GUID . * - * \param count The number of pens in the array (number of array elements minus 1, i.e., not - * counting the terminator 0). + * \param count The number of pens in the array (number of array elements + * minus 1, i.e., not counting the terminator 0). * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. The * array must be freed with ::SDL_free(). On a NULL return, * ::SDL_GetError() is set. @@ -168,9 +168,10 @@ extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); * default values. * * \param instance_id The pen to query. - * \param x Out-mode parameter for pen x coordinate. May be NULL. - * \param y Out-mode parameter for pen y coordinate. May be NULL. - * \param axes Out-mode parameter for axis information. May be null. The axes are in the same order as ::SDL_PenAxis. + * \param x Out-mode parameter for pen x coordinate. May be NULL. + * \param y Out-mode parameter for pen y coordinate. May be NULL. + * \param axes Out-mode parameter for axis information. May be null. The axes + * are in the same order as ::SDL_PenAxis. * \param num_axes Maximum number of axes to write to "axes". * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK * etc.), possibly ::SDL_PEN_DOWN_MASK, and exactly one of @@ -251,7 +252,8 @@ typedef struct SDL_PenCapabilityInfo * Retrieves capability flags for a given ::SDL_PenID. * * \param instance_id The pen to query. - * \param capabilities Detail information about pen capabilities, such as the number of buttons + * \param capabilities Detail information about pen capabilities, such as the + * number of buttons * \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES * * \since This function is available since SDL 3.0.0 From 861b1ebd12e2d515a307f1d0c92aac0ba97a0854 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 13 Nov 2023 18:06:45 -0500 Subject: [PATCH 345/725] properties: Use a mutex instead of an RWLock to guard the hash table The hash table can be recursively locked from the same thread, which can cause issues with RWLocks, as locking them recursively can result in undefined behavior or deadlocks. Use a mutex instead, as it can be safely recursively locked. --- src/SDL_properties.c | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index e447344940ba4..92c260fc14609 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -49,7 +49,7 @@ typedef struct } SDL_Properties; static SDL_HashTable *SDL_properties; -static SDL_RWLock *SDL_properties_lock; +static SDL_Mutex *SDL_properties_lock; static SDL_PropertiesID SDL_last_properties_id; static SDL_PropertiesID SDL_global_properties; @@ -97,7 +97,7 @@ static void SDL_FreeProperties(const void *key, const void *value, void *data) int SDL_InitProperties(void) { if (!SDL_properties_lock) { - SDL_properties_lock = SDL_CreateRWLock(); + SDL_properties_lock = SDL_CreateMutex(); if (!SDL_properties_lock) { return -1; } @@ -122,7 +122,7 @@ void SDL_QuitProperties(void) SDL_properties = NULL; } if (SDL_properties_lock) { - SDL_DestroyRWLock(SDL_properties_lock); + SDL_DestroyMutex(SDL_properties_lock); SDL_properties_lock = NULL; } } @@ -162,7 +162,7 @@ SDL_PropertiesID SDL_CreateProperties(void) goto error; } - SDL_LockRWLockForWriting(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); ++SDL_last_properties_id; if (SDL_last_properties_id == 0) { ++SDL_last_properties_id; @@ -171,7 +171,7 @@ SDL_PropertiesID SDL_CreateProperties(void) if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { inserted = SDL_TRUE; } - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (inserted) { /* All done! */ @@ -191,9 +191,9 @@ int SDL_LockProperties(SDL_PropertiesID props) return SDL_InvalidParamError("props"); } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { return SDL_InvalidParamError("props"); @@ -211,9 +211,9 @@ void SDL_UnlockProperties(SDL_PropertiesID props) return; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { return; @@ -236,9 +236,9 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ return SDL_InvalidParamError("name"); } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_FreeProperty(NULL, property, NULL); @@ -366,9 +366,9 @@ SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) return SDL_PROPERTY_TYPE_INVALID; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -403,9 +403,9 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_va return value; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -448,9 +448,9 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons return value; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -525,9 +525,9 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de return value; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -578,9 +578,9 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau return value; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -631,9 +631,9 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo return value; } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { SDL_InvalidParamError("props"); @@ -686,9 +686,9 @@ int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallb return SDL_InvalidParamError("callback"); } - SDL_LockRWLockForReading(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); if (!properties) { return SDL_InvalidParamError("props"); @@ -715,7 +715,7 @@ void SDL_DestroyProperties(SDL_PropertiesID props) return; } - SDL_LockRWLockForWriting(SDL_properties_lock); + SDL_LockMutex(SDL_properties_lock); SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props); - SDL_UnlockRWLock(SDL_properties_lock); + SDL_UnlockMutex(SDL_properties_lock); } From edd044e90187528656327584b6e2337bbceacd57 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 21:30:57 -0800 Subject: [PATCH 346/725] Fixed the ROG PUGIO II showing up as a game controller This mouse actually enumerates as a gamepad with 2 axes, 8 buttons and a hat. We'll ignore it like the other ROG mice, unless someone specifically wants to use it as a gamepad. --- src/joystick/SDL_joystick.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 8ac7f6d8b7564..664f05e7e9b88 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2995,6 +2995,7 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid) }; static Uint32 rog_chakram_list[] = { + MAKE_VIDPID(0x0b05, 0x1906), /* ROG Pugio II */ MAKE_VIDPID(0x0b05, 0x1958), /* ROG Chakram Core Mouse */ MAKE_VIDPID(0x0b05, 0x18e3), /* ROG Chakram (wired) Mouse */ MAKE_VIDPID(0x0b05, 0x18e5), /* ROG Chakram (wireless) Mouse */ From 2c1fbe1967457c6b95323a5ea4136849c66bc307 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 21:33:09 -0800 Subject: [PATCH 347/725] Revert "Check to make sure the Windows joystick device has buttons and axes" This reverts commit ad0af488837e44cbea0f0eab3b2f73b50a74bff4. It turns out the ROG PUGIO II actually enumerates as a gamepad, so this change didn't have any effect anyway. We're getting lots of reports of people's racing pedals and similar devices no longer showing up, so we'll revert this again. Fixes https://github.com/libsdl-org/SDL/issues/8227 Fixes https://github.com/libsdl-org/SDL/issues/8484 --- src/joystick/windows/SDL_dinputjoystick.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index ef57755b576a7..56f844f22ef34 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -451,7 +451,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta char *hidPath = NULL; char *name = NULL; LPDIRECTINPUTDEVICE8 device = NULL; - DIDEVCAPS caps; /* We are only supporting HID devices. */ CHECK(pDeviceInstance->dwDevType & DIDEVTYPE_HID); @@ -461,13 +460,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta CHECK(QueryDevicePath(device, &hidPath)); CHECK(QueryDeviceInfo(device, &vendor, &product)); - /* Check to make sure the device has buttons and axes. - * This fixes incorrectly detecting the ROG CHAKRAM X mouse as a game controller on Windows 10 - */ - caps.dwSize = sizeof(caps); - CHECK(SUCCEEDED(IDirectInputDevice8_GetCapabilities(device, &caps))); - CHECK(caps.dwAxes > 0 && caps.dwButtons > 0); - CHECK(!SDL_IsXInputDevice(vendor, product, hidPath)); pNewJoystick = *(JoyStick_DeviceData **)pContext; From 229b7b9d50fecd74690321ab7f7fe719565414e3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 11:29:30 -0800 Subject: [PATCH 348/725] SDL_CreateWindowWithPosition() and SDL_CreateWindowFrom() have been replaced with SDL_CreateWindowWithProperties() This is a more general interface that can be extended in the future as needed. --- docs/README-migration.md | 11 +- include/SDL3/SDL_video.h | 206 +++++++----------- src/dynapi/SDL_dynapi.sym | 3 +- src/dynapi/SDL_dynapi_overrides.h | 3 +- src/dynapi/SDL_dynapi_procs.h | 3 +- src/test/SDL_test_common.c | 11 +- src/video/SDL_sysvideo.h | 3 +- src/video/SDL_video.c | 204 ++++++++---------- src/video/android/SDL_androidwindow.c | 2 +- src/video/android/SDL_androidwindow.h | 2 +- src/video/cocoa/SDL_cocoavideo.m | 1 - src/video/cocoa/SDL_cocoawindow.h | 3 +- src/video/cocoa/SDL_cocoawindow.m | 210 +++++++++---------- src/video/emscripten/SDL_emscriptenvideo.c | 4 +- src/video/haiku/SDL_bwindow.cc | 2 +- src/video/haiku/SDL_bwindow.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.h | 2 +- src/video/n3ds/SDL_n3dsvideo.c | 4 +- src/video/ngage/SDL_ngagewindow.cpp | 2 +- src/video/ngage/SDL_ngagewindow.h | 2 +- src/video/offscreen/SDL_offscreenwindow.c | 2 +- src/video/offscreen/SDL_offscreenwindow.h | 2 +- src/video/ps2/SDL_ps2video.c | 2 +- src/video/psp/SDL_pspvideo.c | 2 +- src/video/psp/SDL_pspvideo.h | 2 +- src/video/raspberry/SDL_rpivideo.c | 2 +- src/video/raspberry/SDL_rpivideo.h | 2 +- src/video/riscos/SDL_riscoswindow.c | 2 +- src/video/riscos/SDL_riscoswindow.h | 2 +- src/video/uikit/SDL_uikitwindow.h | 2 +- src/video/uikit/SDL_uikitwindow.m | 2 +- src/video/vita/SDL_vitavideo.c | 2 +- src/video/vita/SDL_vitavideo.h | 2 +- src/video/vivante/SDL_vivantevideo.c | 2 +- src/video/vivante/SDL_vivantevideo.h | 2 +- src/video/wayland/SDL_waylandwindow.c | 2 +- src/video/wayland/SDL_waylandwindow.h | 2 +- src/video/windows/SDL_windowsvideo.c | 1 - src/video/windows/SDL_windowswindow.c | 233 ++++++++++----------- src/video/windows/SDL_windowswindow.h | 4 +- src/video/winrt/SDL_winrtvideo.cpp | 4 +- src/video/x11/SDL_x11video.c | 1 - src/video/x11/SDL_x11window.c | 43 ++-- src/video/x11/SDL_x11window.h | 3 +- test/testautomation_video.c | 10 +- test/testnative.c | 4 +- 47 files changed, 458 insertions(+), 561 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index d0eda28d593bf..eeda40d173bb8 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -559,10 +559,10 @@ The following hints have been removed: * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer * SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() -* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowFrom() -* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowFrom() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled -* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowFrom() +* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "native.win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend @@ -1261,9 +1261,7 @@ Rather than iterating over displays using display index, there is a new function } ``` -SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithPosition() if you need to set the window position when creating it. - -SDL_CreateWindowFrom() now takes a set of properties that describe the native window and options. +SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it. The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. @@ -1332,6 +1330,7 @@ The following functions have been removed: * SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() * SDL_GetWindowData() - use SDL_GetWindowProperties() instead * SDL_SetWindowData() - use SDL_GetWindowProperties() instead +* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with "native.*" properties instead SDL_Window id type is named SDL_WindowID diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index b75ffda4e1e39..3a80cf9633d2b 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -89,42 +89,41 @@ typedef enum /** * The type used to identify a window * - * \sa SDL_CreateWindow() - * \sa SDL_CreateWindowFrom() - * \sa SDL_CreateWindowWithPosition() - * \sa SDL_DestroyWindow() - * \sa SDL_FlashWindow() - * \sa SDL_GetWindowFlags() - * \sa SDL_GetWindowGrab() - * \sa SDL_GetWindowKeyboardGrab() - * \sa SDL_GetWindowMouseGrab() - * \sa SDL_GetWindowPosition() - * \sa SDL_GetWindowSize() - * \sa SDL_GetWindowTitle() - * \sa SDL_HideWindow() - * \sa SDL_MaximizeWindow() - * \sa SDL_MinimizeWindow() - * \sa SDL_RaiseWindow() - * \sa SDL_RestoreWindow() - * \sa SDL_SetWindowFullscreen() - * \sa SDL_SetWindowGrab() - * \sa SDL_SetWindowKeyboardGrab() - * \sa SDL_SetWindowMouseGrab() - * \sa SDL_SetWindowIcon() - * \sa SDL_SetWindowPosition() - * \sa SDL_SetWindowSize() - * \sa SDL_SetWindowBordered() - * \sa SDL_SetWindowResizable() - * \sa SDL_SetWindowTitle() - * \sa SDL_ShowWindow() - * \sa SDL_ShowWindowSystemMenu() + * \sa SDL_CreateWindow + * \sa SDL_CreateWindowWithProperties + * \sa SDL_DestroyWindow + * \sa SDL_FlashWindow + * \sa SDL_GetWindowFlags + * \sa SDL_GetWindowGrab + * \sa SDL_GetWindowKeyboardGrab + * \sa SDL_GetWindowMouseGrab + * \sa SDL_GetWindowPosition + * \sa SDL_GetWindowSize + * \sa SDL_GetWindowTitle + * \sa SDL_HideWindow + * \sa SDL_MaximizeWindow + * \sa SDL_MinimizeWindow + * \sa SDL_RaiseWindow + * \sa SDL_RestoreWindow + * \sa SDL_SetWindowFullscreen + * \sa SDL_SetWindowGrab + * \sa SDL_SetWindowKeyboardGrab + * \sa SDL_SetWindowMouseGrab + * \sa SDL_SetWindowIcon + * \sa SDL_SetWindowPosition + * \sa SDL_SetWindowSize + * \sa SDL_SetWindowBordered + * \sa SDL_SetWindowResizable + * \sa SDL_SetWindowTitle + * \sa SDL_ShowWindow + * \sa SDL_ShowWindowSystemMenu */ typedef struct SDL_Window SDL_Window; /** * The flags on a window * - * \sa SDL_GetWindowFlags() + * \sa SDL_GetWindowFlags */ typedef enum { @@ -144,8 +143,8 @@ typedef enum SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */ SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window, not showing in the task bar and window list */ - SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip and must be created using SDL_CreatePopupWindow() */ - SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu and must be created using SDL_CreatePopupWindow() */ + SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */ + SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */ SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */ SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */ SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */ @@ -713,11 +712,6 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * window is created and should be queried again if you get an * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. * - * If the window is set fullscreen, the width and height parameters `w` and - * `h` will not be used. However, invalid size parameters (e.g. too large) may - * still fail. Window size is actually limited to 16384 x 16384 for all - * platforms at window creation. - * * If the window is created with any of the SDL_WINDOW_OPENGL or * SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function * (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the @@ -743,79 +737,11 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * \since This function is available since SDL 3.0.0. * * \sa SDL_CreatePopupWindow - * \sa SDL_CreateWindowFrom - * \sa SDL_CreateWindowWithPosition + * \sa SDL_CreateWindowWithProperties * \sa SDL_DestroyWindow */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, int h, Uint32 flags); -/** - * Create a window with the specified position, dimensions, and flags. - * - * `flags` may be any of the following OR'd together: - * - * - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution - * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context - * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance - * - `SDL_WINDOW_METAL`: window usable with a Metal instance - * - `SDL_WINDOW_HIDDEN`: window is not visible - * - `SDL_WINDOW_BORDERLESS`: no window decoration - * - `SDL_WINDOW_RESIZABLE`: window can be resized - * - `SDL_WINDOW_MINIMIZED`: window is minimized - * - `SDL_WINDOW_MAXIMIZED`: window is maximized - * - `SDL_WINDOW_MOUSE_GRABBED`: window has grabbed mouse focus - * - * The SDL_Window is implicitly shown if SDL_WINDOW_HIDDEN is not set. - * - * On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist - * property to YES, otherwise you will not receive a High-DPI OpenGL canvas. - * - * The window pixel size may differ from its window coordinate size if the - * window is on a high pixel density display. Use SDL_GetWindowSize() to query - * the client area's size in window coordinates, and - * SDL_GetWindowSizeInPixels() or SDL_GetRenderOutputSize() to query the - * drawable size in pixels. Note that the drawable size can vary after the - * window is created and should be queried again if you get an - * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. - * - * If the window is set fullscreen, the width and height parameters `w` and - * `h` will not be used. However, invalid size parameters (e.g. too large) may - * still fail. Window size is actually limited to 16384 x 16384 for all - * platforms at window creation. - * - * If the window is created with any of the SDL_WINDOW_OPENGL or - * SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function - * (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the - * corresponding UnloadLibrary function is called by SDL_DestroyWindow(). - * - * If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver, - * SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail. - * - * If SDL_WINDOW_METAL is specified on an OS that does not support Metal, - * SDL_CreateWindow() will fail. - * - * On non-Apple devices, SDL requires you to either not link to the Vulkan - * loader or link to a dynamic library version. This limitation may be removed - * in a future version of SDL. - * - * \param title the title of the window, in UTF-8 encoding - * \param x the x position of the window, or `SDL_WINDOWPOS_CENTERED` - * \param y the y position of the window, or `SDL_WINDOWPOS_CENTERED` - * \param w the width of the window - * \param h the height of the window - * \param flags 0, or one or more SDL_WindowFlags OR'd together - * \returns the window that was created or NULL on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreatePopupWindow - * \sa SDL_CreateWindow - * \sa SDL_CreateWindowFrom - * \sa SDL_DestroyWindow - */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *title, int x, int y, int w, int h, Uint32 flags); - /** * Create a child popup window of the specified parent window. * @@ -824,10 +750,12 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *tit * input events. - 'SDL_WINDOW_POPUP_MENU': The popup window is a popup menu. * The topmost popup menu will implicitly gain the keyboard focus. * - * The following flags are not relevant to popup window creation and will be - * ignored: - 'SDL_WINDOW_MINIMIZED' - 'SDL_WINDOW_MAXIMIZED' - - * 'SDL_WINDOW_FULLSCREEN' - 'SDL_WINDOW_BORDERLESS' - - * 'SDL_WINDOW_SKIP_TASKBAR' + * The following flags are not relevant to popup window creation and will be ignored: + * + * - 'SDL_WINDOW_MINIMIZED' + * - 'SDL_WINDOW_MAXIMIZED' + * - 'SDL_WINDOW_FULLSCREEN' + * - 'SDL_WINDOW_BORDERLESS' * * The parent parameter **must** be non-null and a valid window. The parent of * a popup window can be either a regular, toplevel window, or another popup @@ -862,45 +790,60 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *tit * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateWindow + * \sa SDL_CreateWindowWithProperties * \sa SDL_DestroyWindow * \sa SDL_GetWindowParent */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags); /** - * Create an SDL window from properties representing an existing native - * window. + * Create a window with the specified properties. * * These are the supported properties: * + * - "always-on-top" (boolean) - true if the window should be always on top + * - "borderless" (boolean) - true if the window has no window decoration + * - "focusable" (boolean) - true if the window should accept keyboard input (defaults true) + * - "fullscreen" (boolean) - true if the window should start in fullscreen mode at desktop resolution + * - "height" (number) - the height of the window + * - "hidden" (boolean) - true if the window should start hidden + * - "high-pixel-density" (boolean) - true if the window uses a high pixel density buffer if possible + * - "maximized" (boolean) - true if the window should start maximized + * - "menu" (boolean) - true if the window is a popup menu + * - "metal" (string) - true if the window will be used with Metal rendering + * - "minimized" (boolean) - true if the window should start minimized + * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse focus + * - "opengl" (boolean) - true if the window will be used with OpenGL rendering + * - "parent" (pointer) - an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties + * - "resizable" (boolean) - true if the window should be resizable + * - "title" (string) - the title of the window, in UTF-8 encoding + * - "transparent" (string) - true if the window show transparent in the areas with alpha of 0 + * - "tooltip" (boolean) - true if the window is a tooltip + * - "utility" (boolean) - true if the window is a utility window, not showing in the task bar and window list + * - "vulkan" (string) - true if the window will be used with Vulkan rendering + * - "width" (number) - the width of the window + * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. + * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. + * * On macOS: * - * ``` - * "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window - * "cocoa.view" (pointer) - optional, the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] - * ``` + * - "native.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. + * - "native.cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] * * On Windows: * - * ``` - * "win32.hwnd" (pointer) - the HWND associated with the window - * "win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows - * ``` + * - "native.win32.hwnd" (pointer) - the HWND associated with the window, if you want to wrap an existing window. + * - "native.win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows * * On X11: * - * ``` - * "x11.window" (number) - the X11 Window associated with the window - * ``` + * - "native.x11.window" (number) - the X11 Window associated with the window, if you want to wrap an existing window. * - * On all platforms: + * The SDL_Window is implicitly shown if the "hidden" property is not set. * - * ``` - * "opengl" (boolean) - optional, true if the window will be used with OpenGL rendering - * "vulkan" (boolean) - optional, true if the window will be used with Vulkan rendering - * ``` + * Windows with the "tooltip" and "menu" properties are popup windows and have the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. * - * \param props a set of properties describing the native window and options + * \param props the properties to use * \returns the window that was created or NULL on failure; call * SDL_GetError() for more information. * @@ -909,7 +852,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * \sa SDL_CreateWindow * \sa SDL_DestroyWindow */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowFrom(SDL_PropertiesID props); +extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); /** * Get the numeric ID of a window. @@ -1912,8 +1855,9 @@ extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperati * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreatePopupWindow * \sa SDL_CreateWindow - * \sa SDL_CreateWindowFrom + * \sa SDL_CreateWindowWithProperties */ extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window *window); diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 46c1278c6b655..bb55f404c9a4c 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -69,8 +69,7 @@ SDL3_0.0.0 { SDL_CreateThreadWithStackSize; SDL_CreateWindow; SDL_CreateWindowAndRenderer; - SDL_CreateWindowFrom; - SDL_CreateWindowWithPosition; + SDL_CreateWindowWithProperties; SDL_CursorVisible; SDL_DXGIGetOutputInfo; SDL_DelEventWatch; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index a476b53fc07d9..57e1affe2342f 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -93,8 +93,7 @@ #define SDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize_REAL #define SDL_CreateWindow SDL_CreateWindow_REAL #define SDL_CreateWindowAndRenderer SDL_CreateWindowAndRenderer_REAL -#define SDL_CreateWindowFrom SDL_CreateWindowFrom_REAL -#define SDL_CreateWindowWithPosition SDL_CreateWindowWithPosition_REAL +#define SDL_CreateWindowWithProperties SDL_CreateWindowWithProperties_REAL #define SDL_CursorVisible SDL_CursorVisible_REAL #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL #define SDL_DelEventWatch SDL_DelEventWatch_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 309249d97f9d5..3d8049d023a52 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -157,8 +157,7 @@ SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTexture,(SDL_Renderer *a, Uint32 b, int c SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureFromSurface,(SDL_Renderer *a, SDL_Surface *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindow,(const char *a, int b, int c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_CreateWindowAndRenderer,(int a, int b, Uint32 c, SDL_Window **d, SDL_Renderer **e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowFrom,(SDL_PropertiesID a),(a),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowWithPosition,(const char *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowWithProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_CursorVisible,(void),(),return) SDL_DYNAPI_PROC(void,SDL_DelEventWatch,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_DelHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index ad14ba4ee80a5..aa56394955107 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1347,6 +1347,7 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state) for (i = 0; i < state->num_windows; ++i) { char title[1024]; SDL_Rect r; + SDL_PropertiesID props; r.x = state->window_x; r.y = state->window_y; @@ -1369,7 +1370,15 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state) } else { SDL_strlcpy(title, state->window_title, SDL_arraysize(title)); } - state->windows[i] = SDL_CreateWindowWithPosition(title, r.x, r.y, r.w, r.h, state->window_flags); + props = SDL_CreateProperties(); + SDL_SetStringProperty(props, "title", title); + SDL_SetNumberProperty(props, "x", r.x); + SDL_SetNumberProperty(props, "y", r.y); + SDL_SetNumberProperty(props, "width", r.w); + SDL_SetNumberProperty(props, "height", r.h); + SDL_SetNumberProperty(props, "flags", state->window_flags); + state->windows[i] = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); if (!state->windows[i]) { SDL_Log("Couldn't create window: %s\n", SDL_GetError()); diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index cc9597f663305..2dccb30d2b797 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -222,8 +222,7 @@ struct SDL_VideoDevice /* * Window functions */ - int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window); - int (*CreateSDLWindowFrom)(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); + int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void (*SetWindowTitle)(SDL_VideoDevice *_this, SDL_Window *window); int (*SetWindowIcon)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); int (*SetWindowPosition)(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 712b21e095f75..1e325794a3691 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1844,9 +1844,59 @@ static int SDL_DllNotSupported(const char *name) return SDL_SetError("No dynamic %s support in current SDL video driver (%s)", name, _this->name); } -static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int w, int h, SDL_Window *parent, Uint32 flags) +static struct { + const char *property_name; + Uint32 flag; + SDL_bool invert_value; +} SDL_WindowFlagProperties[] = { + { "always-on-top", SDL_WINDOW_ALWAYS_ON_TOP, SDL_FALSE }, + { "borderless", SDL_WINDOW_BORDERLESS, SDL_FALSE }, + { "focusable", SDL_WINDOW_NOT_FOCUSABLE, SDL_TRUE }, + { "fullscreen", SDL_WINDOW_FULLSCREEN, SDL_FALSE }, + { "hidden", SDL_WINDOW_HIDDEN, SDL_FALSE }, + { "high-pixel-density", SDL_WINDOW_HIGH_PIXEL_DENSITY, SDL_FALSE }, + { "maximized", SDL_WINDOW_MAXIMIZED, SDL_FALSE }, + { "menu", SDL_WINDOW_POPUP_MENU, SDL_FALSE }, + { "metal", SDL_WINDOW_METAL, SDL_FALSE }, + { "minimized", SDL_WINDOW_MINIMIZED, SDL_FALSE }, + { "mouse-grabbed", SDL_WINDOW_MOUSE_GRABBED, SDL_FALSE }, + { "opengl", SDL_WINDOW_OPENGL, SDL_FALSE }, + { "resizable", SDL_WINDOW_RESIZABLE, SDL_FALSE }, + { "transparent", SDL_WINDOW_TRANSPARENT, SDL_FALSE }, + { "tooltip", SDL_WINDOW_TOOLTIP, SDL_FALSE }, + { "utility", SDL_WINDOW_UTILITY, SDL_FALSE }, + { "vulkan", SDL_WINDOW_VULKAN, SDL_FALSE } +}; + +static Uint32 SDL_GetWindowFlagProperties(SDL_PropertiesID props) +{ + unsigned i; + Uint32 flags = (Uint32)SDL_GetNumberProperty(props, "flags", 0); + + for (i = 0; i < SDL_arraysize(SDL_WindowFlagProperties); ++i) { + if (SDL_WindowFlagProperties[i].invert_value) { + if (!SDL_GetBooleanProperty(props, SDL_WindowFlagProperties[i].property_name, SDL_TRUE)) { + flags |= SDL_WindowFlagProperties[i].flag; + } + } else { + if (SDL_GetBooleanProperty(props, SDL_WindowFlagProperties[i].property_name, SDL_FALSE)) { + flags |= SDL_WindowFlagProperties[i].flag; + } + } + } + return flags; +} + +SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) { SDL_Window *window; + const char *title = SDL_GetStringProperty(props, "title", NULL); + int x = (int)SDL_GetNumberProperty(props, "x", SDL_WINDOWPOS_UNDEFINED); + int y = (int)SDL_GetNumberProperty(props, "y", SDL_WINDOWPOS_UNDEFINED); + int w = (int)SDL_GetNumberProperty(props, "width", 0); + int h = (int)SDL_GetNumberProperty(props, "height", 0); + SDL_Window *parent = SDL_GetProperty(props, "parent", NULL); + Uint32 flags = SDL_GetWindowFlagProperties(props); Uint32 type_flags, graphics_flags; SDL_bool undefined_x = SDL_FALSE; SDL_bool undefined_y = SDL_FALSE; @@ -1863,22 +1913,32 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int } } - /* Make sure the display list is up to date for window placement */ - if (_this->RefreshDisplays) { - _this->RefreshDisplays(_this); + if ((flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)) != 0) { + if (!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT)) { + SDL_Unsupported(); + return NULL; + } + + /* Tooltip and popup menu window must specify a parent window */ + if (!parent || parent->magic != &_this->window_magic) { + SDL_SetError("Tooltip and popup menu windows must specify a parent window"); + return NULL; + } + + /* Remove invalid flags */ + flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS); } - /* ensure no more than one of these flags is set */ + /* Ensure no more than one of these flags is set */ type_flags = flags & (SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU); if (type_flags & (type_flags - 1)) { SDL_SetError("Conflicting window type flags specified: 0x%.8x", (unsigned int)type_flags); return NULL; } - /* Tooltip and popup menu window must specify a parent window */ - if (!parent && ((type_flags & SDL_WINDOW_TOOLTIP) || (type_flags & SDL_WINDOW_POPUP_MENU))) { - SDL_SetError("Tooltip and popup menu windows must specify a parent window"); - return NULL; + /* Make sure the display list is up to date for window placement */ + if (_this->RefreshDisplays) { + _this->RefreshDisplays(_this); } /* Some platforms can't create zero-sized windows */ @@ -1889,14 +1949,6 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int h = 1; } - /* Some platforms blow up if the windows are too large. Raise it later? */ - if (w > 16384) { - w = 16384; - } - if (h > 16384) { - h = 16384; - } - if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) { SDL_DisplayID displayID = 0; @@ -2013,7 +2065,7 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int parent->first_child = window; } - if (_this->CreateSDLWindow && _this->CreateSDLWindow(_this, window) < 0) { + if (_this->CreateSDLWindow && _this->CreateSDLWindow(_this, window, props) < 0) { SDL_DestroyWindow(window); return NULL; } @@ -2057,28 +2109,23 @@ static SDL_Window *SDL_CreateWindowInternal(const char *title, int x, int y, int SDL_Window *SDL_CreateWindow(const char *title, int w, int h, Uint32 flags) { - return SDL_CreateWindowInternal(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w , h, NULL, flags); -} - -SDL_Window *SDL_CreateWindowWithPosition(const char *title, int x, int y, int w, int h, Uint32 flags) -{ - return SDL_CreateWindowInternal(title, x, y, w , h, NULL, flags); + SDL_Window *window; + SDL_PropertiesID props = SDL_CreateProperties(); + if (title && *title) { + SDL_SetStringProperty(props, "title", title); + } + SDL_SetNumberProperty(props, "width", w); + SDL_SetNumberProperty(props, "height", h); + SDL_SetNumberProperty(props, "flags", flags); + window = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); + return window; } SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags) { - if (!_this) { - SDL_UninitializedVideo(); - return NULL; - } - - if (!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT)) { - SDL_Unsupported(); - return NULL; - } - - /* Parent must be a valid window */ - CHECK_WINDOW_MAGIC(parent, NULL); + SDL_Window *window; + SDL_PropertiesID props = SDL_CreateProperties(); /* Popups must specify either the tooltip or popup menu window flags */ if (!(flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU))) { @@ -2086,81 +2133,14 @@ SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y return NULL; } - /* Remove invalid flags */ - flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS); - - return SDL_CreateWindowInternal(NULL, offset_x, offset_y, w, h, parent, flags); -} - -SDL_Window *SDL_CreateWindowFrom(SDL_PropertiesID props) -{ - SDL_Window *window; - Uint32 flags = SDL_WINDOW_FOREIGN; - - if (!props) { - SDL_InvalidParamError("props"); - return NULL; - } - if (!_this) { - SDL_UninitializedVideo(); - return NULL; - } - if (!_this->CreateSDLWindowFrom) { - SDL_Unsupported(); - return NULL; - } - - if (SDL_GetBooleanProperty(props, "opengl", SDL_FALSE)) { - if (!_this->GL_CreateContext) { - SDL_ContextNotSupported("OpenGL"); - return NULL; - } - if (SDL_GL_LoadLibrary(NULL) < 0) { - return NULL; - } - flags |= SDL_WINDOW_OPENGL; - } - - if (SDL_GetBooleanProperty(props, "vulkan", SDL_FALSE)) { - if (!_this->Vulkan_CreateSurface) { - SDL_ContextNotSupported("Vulkan"); - return NULL; - } - if (flags & SDL_WINDOW_OPENGL) { - SDL_SetError("Vulkan and OpenGL not supported on same window"); - return NULL; - } - if (SDL_Vulkan_LoadLibrary(NULL) < 0) { - return NULL; - } - flags |= SDL_WINDOW_VULKAN; - } - - window = (SDL_Window *)SDL_calloc(1, sizeof(*window)); - if (!window) { - SDL_OutOfMemory(); - return NULL; - } - window->magic = &_this->window_magic; - window->id = SDL_GetNextObjectID(); - window->flags = flags; - window->is_destroying = SDL_FALSE; - window->display_scale = 1.0f; - window->opacity = 1.0f; - window->next = _this->windows; - if (_this->windows) { - _this->windows->prev = window; - } - _this->windows = window; - - if (_this->CreateSDLWindowFrom(_this, window, props) < 0) { - SDL_DestroyWindow(window); - return NULL; - } - - window->last_displayID = SDL_GetDisplayForWindow(window); - PrepareDragAndDropSupport(window); - + SDL_SetProperty(props, "parent", parent); + SDL_SetNumberProperty(props, "x", offset_x); + SDL_SetNumberProperty(props, "y", offset_y); + SDL_SetNumberProperty(props, "width", w); + SDL_SetNumberProperty(props, "height", h); + SDL_SetNumberProperty(props, "flags", flags); + window = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); return window; } @@ -2265,7 +2245,7 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) window->is_destroying = SDL_FALSE; if (_this->CreateSDLWindow && !(flags & SDL_WINDOW_FOREIGN)) { - if (_this->CreateSDLWindow(_this, window) < 0) { + if (_this->CreateSDLWindow(_this, window, 0) < 0) { if (loaded_opengl) { SDL_GL_UnloadLibrary(); window->flags &= ~SDL_WINDOW_OPENGL; diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 3f640fdaac09a..911345d22549b 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -35,7 +35,7 @@ /* Currently only one window */ SDL_Window *Android_Window = NULL; -int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *data; int retval = 0; diff --git a/src/video/android/SDL_androidwindow.h b/src/video/android/SDL_androidwindow.h index ea81d3bc802d9..bbe2e4f1da249 100644 --- a/src/video/android/SDL_androidwindow.h +++ b/src/video/android/SDL_androidwindow.h @@ -26,7 +26,7 @@ #include "../../core/android/SDL_android.h" #include "../SDL_egl_c.h" -extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index bd2fdf8148bb8..1153b26350d2e 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -90,7 +90,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) device->SuspendScreenSaver = Cocoa_SuspendScreenSaver; device->CreateSDLWindow = Cocoa_CreateWindow; - device->CreateSDLWindowFrom = Cocoa_CreateWindowFrom; device->SetWindowTitle = Cocoa_SetWindowTitle; device->SetWindowIcon = Cocoa_SetWindowIcon; device->SetWindowPosition = Cocoa_SetWindowPosition; diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index e03adb3504e89..d422f52c3de74 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -141,8 +141,7 @@ typedef enum #endif @end -extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); +extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int Cocoa_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); extern int Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index ee99090591a16..64b541b21ef54 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1752,7 +1752,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent @end -static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow *nswindow, NSView *nsview, SDL_bool created) +static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow *nswindow, NSView *nsview) { @autoreleasepool { SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)_this->driverdata; @@ -1765,7 +1765,6 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow } data.window = window; data.nswindow = nswindow; - data.created = created; data.videodata = videodata; data.window_number = nswindow.windowNumber; data.nscontexts = [[NSMutableArray alloc] init]; @@ -1862,6 +1861,14 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow */ [nswindow setOneShot:NO]; + if (window->flags & SDL_WINDOW_FOREIGN) { + /* Query the title from the existing window */ + NSString *title = [nswindow title]; + if (title) { + window->title = SDL_strdup([title UTF8String]); + } + } + SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, "SDL.window.cocoa.window", (__bridge void *)data.nswindow); SDL_SetNumberProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG); @@ -1872,69 +1879,99 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow } } -int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { @autoreleasepool { SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)_this->driverdata; - NSWindow *nswindow; - int x, y; - NSScreen *screen; - NSRect rect, screenRect; - BOOL fullscreen; - NSUInteger style; - SDLView *contentView; - BOOL highdpi; + const void *data = SDL_GetProperty(create_props, "native.data", NULL); + NSWindow *nswindow = nil; + NSView *nsview = nil; - SDL_RelativeToGlobalForWindow(window, window->x, window->y, &x, &y); - rect.origin.x = x; - rect.origin.y = y; - rect.size.width = window->w; - rect.size.height = window->h; - fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN) ? YES : NO; - ConvertNSRect(fullscreen, &rect); + if (data) { + if ([(__bridge id)data isKindOfClass:[NSWindow class]]) { + nswindow = (__bridge NSWindow *)data; + } else if ([(__bridge id)data isKindOfClass:[NSView class]]) { + nsview = (__bridge NSView *)data; + } else { + SDL_assert(false); + } + } else { + nswindow = (__bridge NSWindow *)SDL_GetProperty(create_props, "native.cocoa.window", NULL); + nsview = (__bridge NSView *)SDL_GetProperty(create_props, "native.cocoa.view", NULL); + } + if (nswindow && !nsview) { + nsview = [nswindow contentView]; + } + if (nsview && !nswindow) { + nswindow = [nsview window]; + } + if (nswindow) { + window->flags |= SDL_WINDOW_FOREIGN; + } else { + int x, y; + NSScreen *screen; + NSRect rect, screenRect; + BOOL fullscreen; + NSUInteger style; + SDLView *contentView; - style = GetWindowStyle(window); + SDL_RelativeToGlobalForWindow(window, window->x, window->y, &x, &y); + rect.origin.x = x; + rect.origin.y = y; + rect.size.width = window->w; + rect.size.height = window->h; + fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN) ? YES : NO; + ConvertNSRect(fullscreen, &rect); - /* Figure out which screen to place this window */ - screen = ScreenForRect(&rect); - screenRect = [screen frame]; - rect.origin.x -= screenRect.origin.x; - rect.origin.y -= screenRect.origin.y; + style = GetWindowStyle(window); - /* Constrain the popup */ - if (SDL_WINDOW_IS_POPUP(window)) { - if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) { - rect.origin.x -= (rect.origin.x + rect.size.width) - (screenRect.origin.x + screenRect.size.width); - } - if (rect.origin.y + rect.size.height > screenRect.origin.y + screenRect.size.height) { - rect.origin.y -= (rect.origin.y + rect.size.height) - (screenRect.origin.y + screenRect.size.height); + /* Figure out which screen to place this window */ + screen = ScreenForRect(&rect); + screenRect = [screen frame]; + rect.origin.x -= screenRect.origin.x; + rect.origin.y -= screenRect.origin.y; + + /* Constrain the popup */ + if (SDL_WINDOW_IS_POPUP(window)) { + if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) { + rect.origin.x -= (rect.origin.x + rect.size.width) - (screenRect.origin.x + screenRect.size.width); + } + if (rect.origin.y + rect.size.height > screenRect.origin.y + screenRect.size.height) { + rect.origin.y -= (rect.origin.y + rect.size.height) - (screenRect.origin.y + screenRect.size.height); + } + rect.origin.x = SDL_max(rect.origin.x, screenRect.origin.x); + rect.origin.y = SDL_max(rect.origin.y, screenRect.origin.y); } - rect.origin.x = SDL_max(rect.origin.x, screenRect.origin.x); - rect.origin.y = SDL_max(rect.origin.y, screenRect.origin.y); - } - @try { - nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen]; - } - @catch (NSException *e) { - return SDL_SetError("%s", [[e reason] UTF8String]); - } + @try { + nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen]; + } + @catch (NSException *e) { + return SDL_SetError("%s", [[e reason] UTF8String]); + } - [nswindow setColorSpace:[NSColorSpace sRGBColorSpace]]; + [nswindow setColorSpace:[NSColorSpace sRGBColorSpace]]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 /* Added in the 10.12.0 SDK. */ - /* By default, don't allow users to make our window tabbed in 10.12 or later */ - if ([nswindow respondsToSelector:@selector(setTabbingMode:)]) { - [nswindow setTabbingMode:NSWindowTabbingModeDisallowed]; - } + /* By default, don't allow users to make our window tabbed in 10.12 or later */ + if ([nswindow respondsToSelector:@selector(setTabbingMode:)]) { + [nswindow setTabbingMode:NSWindowTabbingModeDisallowed]; + } #endif - if (videodata.allow_spaces) { - /* we put fullscreen desktop windows in their own Space, without a toggle button or menubar, later */ - if (window->flags & SDL_WINDOW_RESIZABLE) { - /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */ - [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + if (videodata.allow_spaces) { + /* we put fullscreen desktop windows in their own Space, without a toggle button or menubar, later */ + if (window->flags & SDL_WINDOW_RESIZABLE) { + /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */ + [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + } } + + /* Create a default view for this window */ + rect = [nswindow contentRectForFrameRect:[nswindow frame]]; + contentView = [[SDLView alloc] initWithFrame:rect]; + [contentView setSDLWindow:window]; + nsview = contentView; } if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) { @@ -1947,11 +1984,6 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) nswindow.backgroundColor = [NSColor clearColor]; } - /* Create a default view for this window */ - rect = [nswindow contentRectForFrameRect:[nswindow frame]]; - contentView = [[SDLView alloc] initWithFrame:rect]; - [contentView setSDLWindow:window]; - /* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */ #ifdef __clang__ #pragma clang diagnostic push @@ -1959,8 +1991,8 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) #endif /* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when * the NSHighResolutionCapable boolean is set in Info.plist. */ - highdpi = (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) ? YES : NO; - [contentView setWantsBestResolutionOpenGLSurface:highdpi]; + BOOL highdpi = (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) ? YES : NO; + [nsview setWantsBestResolutionOpenGLSurface:highdpi]; #ifdef __clang__ #pragma clang diagnostic pop #endif @@ -1969,19 +2001,19 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) #ifdef SDL_VIDEO_OPENGL_EGL if ((window->flags & SDL_WINDOW_OPENGL) && _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { - [contentView setWantsLayer:TRUE]; + [nsview setWantsLayer:TRUE]; if ((window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) && [nswindow.screen respondsToSelector:@selector(backingScaleFactor)]) { - contentView.layer.contentsScale = nswindow.screen.backingScaleFactor; + nsview.layer.contentsScale = nswindow.screen.backingScaleFactor; } else { - contentView.layer.contentsScale = 1; + nsview.layer.contentsScale = 1; } } #endif /* SDL_VIDEO_OPENGL_EGL */ #endif /* SDL_VIDEO_OPENGL_ES2 */ - [nswindow setContentView:contentView]; + [nswindow setContentView:nsview]; - if (SetupWindowData(_this, window, nswindow, contentView, SDL_TRUE) < 0) { + if (SetupWindowData(_this, window, nswindow, nsview) < 0) { return -1; } @@ -2007,60 +2039,6 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ - @autoreleasepool { - const void *data = SDL_GetProperty(props, "data", NULL); - NSWindow *nswindow = nil; - NSView *nsview = nil; - NSString *title; - BOOL highdpi; - - if (data) { - if ([(__bridge id)data isKindOfClass:[NSWindow class]]) { - nswindow = (__bridge NSWindow *)data; - } else if ([(__bridge id)data isKindOfClass:[NSView class]]) { - nsview = (__bridge NSView *)data; - } else { - SDL_assert(false); - } - } else { - nswindow = (__bridge NSWindow *)SDL_GetProperty(props, "cocoa.window", NULL); - nsview = (__bridge NSView *)SDL_GetProperty(props, "cocoa.view", NULL); - } - if (nswindow && !nsview) { - nsview = [nswindow contentView]; - } - if (nsview && !nswindow) { - nswindow = [nsview window]; - } - if (!nswindow) { - return SDL_SetError("Couldn't find property cocoa.window"); - } - - /* Query the title from the existing window */ - title = [nswindow title]; - if (title) { - window->title = SDL_strdup([title UTF8String]); - } - -/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */ -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - /* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when - * the NSHighResolutionCapable boolean is set in Info.plist. */ - highdpi = (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) ? YES : NO; - [nsview setWantsBestResolutionOpenGLSurface:highdpi]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - return SetupWindowData(_this, window, nswindow, nsview, SDL_FALSE); - } -} - void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { @autoreleasepool { diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index 0c2209dd07544..43e74764c2cfc 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -40,7 +40,7 @@ static int Emscripten_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *d static void Emscripten_VideoQuit(SDL_VideoDevice *_this); static int Emscripten_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect); -static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); static void Emscripten_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); static void Emscripten_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h); static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); @@ -171,7 +171,7 @@ static void Emscripten_PumpEvents(SDL_VideoDevice *_this) /* do nothing. */ } -static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) { SDL_WindowData *wdata; double scaled_w, scaled_h; diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index 15c1d32fa220d..c5eb22995b710 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -76,7 +76,7 @@ static int _InitWindow(SDL_VideoDevice *_this, SDL_Window *window) { return 0; } -int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) { +int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { if (_InitWindow(_this, window) < 0) { return -1; } diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index b49ab92764266..0f4fc48640eb0 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -24,7 +24,7 @@ #include "../SDL_sysvideo.h" -extern int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int HAIKU_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void HAIKU_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int HAIKU_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); extern void HAIKU_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 07598ab26cb51..f603707131ef9 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1443,7 +1443,7 @@ void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) /* reflect it: if it's fullscreen, KMSDRM_SetWindwoFullscreen() will */ /* be called by SDL later, and we can manage it there. */ /**********************************************************************/ -int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *windata = NULL; SDL_VideoData *viddata = _this->driverdata; diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index 9807cf4b3943e..ee11dd5941312 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -121,7 +121,7 @@ int KMSDRM_VideoInit(SDL_VideoDevice *_this); void KMSDRM_VideoQuit(SDL_VideoDevice *_this); int KMSDRM_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c index 409713e77c99d..6eb88ec3d7e01 100644 --- a/src/video/n3ds/SDL_n3dsvideo.c +++ b/src/video/n3ds/SDL_n3dsvideo.c @@ -36,7 +36,7 @@ static int AddN3DSDisplay(gfxScreen_t screen); static int N3DS_VideoInit(SDL_VideoDevice *_this); static void N3DS_VideoQuit(SDL_VideoDevice *_this); static int N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect); -static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); struct SDL_DisplayData @@ -150,7 +150,7 @@ static int N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *displ return 0; } -static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_DisplayData *display_data; SDL_WindowData *window_data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); diff --git a/src/video/ngage/SDL_ngagewindow.cpp b/src/video/ngage/SDL_ngagewindow.cpp index d8ee898ae2550..7a305ec3368d2 100644 --- a/src/video/ngage/SDL_ngagewindow.cpp +++ b/src/video/ngage/SDL_ngagewindow.cpp @@ -32,7 +32,7 @@ const TUint32 WindowClientHandle = 9210; void DisableKeyBlocking(SDL_VideoDevice *_this); void ConstructWindowL(SDL_VideoDevice *_this); -int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { NGAGE_Window *ngage_window = (NGAGE_Window *)SDL_calloc(1, sizeof(NGAGE_Window)); diff --git a/src/video/ngage/SDL_ngagewindow.h b/src/video/ngage/SDL_ngagewindow.h index 811142dd7e632..58d4d97d49868 100644 --- a/src/video/ngage/SDL_ngagewindow.h +++ b/src/video/ngage/SDL_ngagewindow.h @@ -32,7 +32,7 @@ typedef struct } NGAGE_Window; -extern int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void NGAGE_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_ngagewindow */ diff --git a/src/video/offscreen/SDL_offscreenwindow.c b/src/video/offscreen/SDL_offscreenwindow.c index 7a8ce759ff638..f90bba6822959 100644 --- a/src/video/offscreen/SDL_offscreenwindow.c +++ b/src/video/offscreen/SDL_offscreenwindow.c @@ -27,7 +27,7 @@ #include "SDL_offscreenwindow.h" -int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *offscreen_window = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); diff --git a/src/video/offscreen/SDL_offscreenwindow.h b/src/video/offscreen/SDL_offscreenwindow.h index 4f502560ffa5d..2e360d418ae03 100644 --- a/src/video/offscreen/SDL_offscreenwindow.h +++ b/src/video/offscreen/SDL_offscreenwindow.h @@ -33,7 +33,7 @@ struct SDL_WindowData #endif }; -extern int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void OFFSCREEN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_offscreenwindow_h */ diff --git a/src/video/ps2/SDL_ps2video.c b/src/video/ps2/SDL_ps2video.c index 5d003834c556a..ea12f7cbde133 100644 --- a/src/video/ps2/SDL_ps2video.c +++ b/src/video/ps2/SDL_ps2video.c @@ -55,7 +55,7 @@ static void PS2_DeleteDevice(SDL_VideoDevice *device) SDL_free(device); } -static int PS2_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +static int PS2_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_SetKeyboardFocus(window); diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 5a2091e3b82ae..44269db934a9d 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -185,7 +185,7 @@ int PSP_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Di } \ } while (0) -int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *wdata; diff --git a/src/video/psp/SDL_pspvideo.h b/src/video/psp/SDL_pspvideo.h index 6a680d9eb58f3..28fd92127be94 100644 --- a/src/video/psp/SDL_pspvideo.h +++ b/src/video/psp/SDL_pspvideo.h @@ -49,7 +49,7 @@ int PSP_VideoInit(SDL_VideoDevice *_this); void PSP_VideoQuit(SDL_VideoDevice *_this); int PSP_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int PSP_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void PSP_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int PSP_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void PSP_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index e167265346162..5b1c45ad07700 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -216,7 +216,7 @@ static void RPI_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data) SDL_UnlockMutex(wdata->vsync_cond_mutex); } -int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *wdata; SDL_VideoDisplay *display; diff --git a/src/video/raspberry/SDL_rpivideo.h b/src/video/raspberry/SDL_rpivideo.h index f1d72b7ce05d6..d2904508cdd26 100644 --- a/src/video/raspberry/SDL_rpivideo.h +++ b/src/video/raspberry/SDL_rpivideo.h @@ -63,7 +63,7 @@ int RPI_VideoInit(SDL_VideoDevice *_this); void RPI_VideoQuit(SDL_VideoDevice *_this); int RPI_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int RPI_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void RPI_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int RPI_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void RPI_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c index bd192c3ceaa10..2b27bf7f79a49 100644 --- a/src/video/riscos/SDL_riscoswindow.c +++ b/src/video/riscos/SDL_riscoswindow.c @@ -28,7 +28,7 @@ #include "SDL_riscosvideo.h" #include "SDL_riscoswindow.h" -int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *driverdata; diff --git a/src/video/riscos/SDL_riscoswindow.h b/src/video/riscos/SDL_riscoswindow.h index 6899a3d2a8016..46adc3a97d271 100644 --- a/src/video/riscos/SDL_riscoswindow.h +++ b/src/video/riscos/SDL_riscoswindow.h @@ -32,7 +32,7 @@ struct SDL_WindowData sprite_header *fb_sprite; }; -extern int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void RISCOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_riscoswindow_h_ */ diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index 64ba38c13d2ed..8635bef4ca849 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -26,7 +26,7 @@ #import "SDL_uikitview.h" #import "SDL_uikitviewcontroller.h" -extern int UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void UIKit_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 54ba279bd2bb8..dd7a36dd239ae 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -160,7 +160,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow return 0; } -int UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int UIKit_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { @autoreleasepool { SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window); diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 884c95fe33da3..efaa6209a15b4 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -218,7 +218,7 @@ void VITA_VideoQuit(SDL_VideoDevice *_this) VITA_QuitTouch(); } -int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *wdata; #ifdef SDL_VIDEO_VITA_PVR diff --git a/src/video/vita/SDL_vitavideo.h b/src/video/vita/SDL_vitavideo.h index a4cf79dafbff2..fc62aec2f73a5 100644 --- a/src/video/vita/SDL_vitavideo.h +++ b/src/video/vita/SDL_vitavideo.h @@ -62,7 +62,7 @@ int VITA_VideoInit(SDL_VideoDevice *_this); void VITA_VideoQuit(SDL_VideoDevice *_this); int VITA_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int VITA_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int VITA_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void VITA_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index fa507571c8a3f..f9d2daa2e5557 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -238,7 +238,7 @@ void VIVANTE_VideoQuit(SDL_VideoDevice *_this) #endif } -int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_VideoData *videodata = _this->driverdata; SDL_DisplayData *displaydata; diff --git a/src/video/vivante/SDL_vivantevideo.h b/src/video/vivante/SDL_vivantevideo.h index ca9a62ed6ca57..6bb9985dd9113 100644 --- a/src/video/vivante/SDL_vivantevideo.h +++ b/src/video/vivante/SDL_vivantevideo.h @@ -72,7 +72,7 @@ int VIVANTE_VideoInit(SDL_VideoDevice *_this); void VIVANTE_VideoQuit(SDL_VideoDevice *_this); int VIVANTE_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); int VIVANTE_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); void VIVANTE_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int VIVANTE_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void VIVANTE_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index d7acd64bac0a7..043571aaceb67 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1981,7 +1981,7 @@ void Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, S } } -int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { SDL_WindowData *data; SDL_VideoData *c; diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index d2105706d7626..e53fe31680669 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -137,7 +137,7 @@ extern void Wayland_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *wi extern void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); extern void Wayland_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); -extern int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern int Wayland_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); extern void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); extern void Wayland_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 78bf4236816b9..15ef5a8fee05d 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -176,7 +176,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) #endif device->CreateSDLWindow = WIN_CreateWindow; - device->CreateSDLWindowFrom = WIN_CreateWindowFrom; device->SetWindowTitle = WIN_SetWindowTitle; device->SetWindowIcon = WIN_SetWindowIcon; device->SetWindowPosition = WIN_SetWindowPosition; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 66b5701498a8c..8a3b6cc2d0cf5 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -276,7 +276,7 @@ static void SDLCALL WIN_MouseRelativeModeCenterChanged(void *userdata, const cha data->mouse_relative_mode_center = SDL_GetStringBoolean(hint, SDL_TRUE); } -static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd, HWND parent, SDL_bool created) +static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd, HWND parent) { SDL_VideoData *videodata = _this->driverdata; SDL_WindowData *data; @@ -295,8 +295,6 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd data->hdc = GetDC(hwnd); #endif data->hinstance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); - data->created = created; - data->high_surrogate = 0; data->mouse_button_flags = (WPARAM)-1; data->last_pointer_update = (LPARAM)-1; data->videodata = videodata; @@ -349,7 +347,10 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd int w = rect.right; int h = rect.bottom; - if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) { + if (window->flags & SDL_WINDOW_FOREIGN) { + window->windowed.w = window->w = w; + window->windowed.h = window->h = h; + } else if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) { /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */ int x, y; /* Figure out what the window area will be */ @@ -369,6 +370,10 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd point.x = 0; point.y = 0; if (ClientToScreen(hwnd, &point)) { + if (window->flags & SDL_WINDOW_FOREIGN) { + window->windowed.x = point.x; + window->windowed.y = point.y; + } window->x = point.x; window->y = point.y; } @@ -438,6 +443,27 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd data->initializing = SDL_FALSE; + if (window->flags & SDL_WINDOW_FOREIGN) { + /* Query the title from the existing window */ + LPTSTR title; + int titleLen; + SDL_bool isstack; + + titleLen = GetWindowTextLength(hwnd); + title = SDL_small_alloc(TCHAR, titleLen + 1, &isstack); + if (title) { + titleLen = GetWindowText(hwnd, title, titleLen + 1); + } else { + titleLen = 0; + } + if (titleLen > 0) { + window->title = WIN_StringToUTF8(title); + } + if (title) { + SDL_small_free(title, isstack); + } + } + SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, "SDL.window.win32.hwnd", data->hwnd); SDL_SetProperty(props, "SDL.window.win32.hdc", data->hdc); @@ -464,7 +490,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window) ReleaseDC(data->hwnd, data->hdc); RemoveProp(data->hwnd, TEXT("SDL_WindowData")); #endif - if (data->created) { + if (!(window->flags & SDL_WINDOW_FOREIGN)) { DestroyWindow(data->hwnd); if (data->destroy_parent_with_window && data->parent) { DestroyWindow(data->parent); @@ -538,55 +564,64 @@ static void WIN_SetKeyboardFocus(SDL_Window *window) SDL_SetKeyboardFocus(window); } -int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { - HWND hwnd, parent = NULL; - DWORD style = STYLE_BASIC; - DWORD styleEx = 0; - int x, y; - int w, h; + HWND hwnd = (HWND)SDL_GetProperty(create_props, "native.win32.hwnd", SDL_GetProperty(create_props, "native.data", NULL)); + HWND parent = NULL; + if (hwnd) { + window->flags |= SDL_WINDOW_FOREIGN; - if (SDL_WINDOW_IS_POPUP(window)) { - parent = window->parent->driverdata->hwnd; - } else if (window->flags & SDL_WINDOW_UTILITY) { - parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL); - } + if (SetupWindowData(_this, window, hwnd, parent) < 0) { + return -1; + } + } else { + DWORD style = STYLE_BASIC; + DWORD styleEx = 0; + int x, y; + int w, h; + + if (SDL_WINDOW_IS_POPUP(window)) { + parent = window->parent->driverdata->hwnd; + } else if (window->flags & SDL_WINDOW_UTILITY) { + parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL); + } - style |= GetWindowStyle(window); - styleEx |= GetWindowStyleEx(window); + style |= GetWindowStyle(window); + styleEx |= GetWindowStyleEx(window); - /* Figure out what the window area will be */ - WIN_ConstrainPopup(window); - WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE); + /* Figure out what the window area will be */ + WIN_ConstrainPopup(window); + WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE); - hwnd = CreateWindowEx(styleEx, SDL_Appname, TEXT(""), style, - x, y, w, h, parent, NULL, SDL_Instance, NULL); - if (!hwnd) { - return WIN_SetError("Couldn't create window"); - } + hwnd = CreateWindowEx(styleEx, SDL_Appname, TEXT(""), style, + x, y, w, h, parent, NULL, SDL_Instance, NULL); + if (!hwnd) { + return WIN_SetError("Couldn't create window"); + } - WIN_UpdateDarkModeForHWND(hwnd); + WIN_UpdateDarkModeForHWND(hwnd); - WIN_PumpEvents(_this); + WIN_PumpEvents(_this); - if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) { - DestroyWindow(hwnd); - if (parent) { - DestroyWindow(parent); + if (SetupWindowData(_this, window, hwnd, parent) < 0) { + DestroyWindow(hwnd); + if (parent) { + DestroyWindow(parent); + } + return -1; } - return -1; - } - /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */ - SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); + /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */ + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); - if (window->flags & SDL_WINDOW_MINIMIZED) { - /* TODO: We have to clear SDL_WINDOW_HIDDEN here to ensure the window flags match the window state. The - window is already shown after this and windows with WS_MINIMIZE do not generate a WM_SHOWWINDOW. This - means you can't currently create a window that is initially hidden and is minimized when shown. - */ - window->flags &= ~SDL_WINDOW_HIDDEN; - ShowWindow(hwnd, SW_SHOWMINNOACTIVE); + if (window->flags & SDL_WINDOW_MINIMIZED) { + /* TODO: We have to clear SDL_WINDOW_HIDDEN here to ensure the window flags match the window state. The + window is already shown after this and windows with WS_MINIMIZE do not generate a WM_SHOWWINDOW. This + means you can't currently create a window that is initially hidden and is minimized when shown. + */ + window->flags &= ~SDL_WINDOW_HIDDEN; + ShowWindow(hwnd, SW_SHOWMINNOACTIVE); + } } /* FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs) */ @@ -608,98 +643,56 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - if (!(window->flags & SDL_WINDOW_OPENGL)) { - return 0; - } + HWND share_hwnd = (HWND)SDL_GetProperty(create_props, "native.win32.pixel_format_hwnd", NULL); + if (share_hwnd) { + HDC hdc = GetDC(share_hwnd); + int pixel_format = GetPixelFormat(hdc); + PIXELFORMATDESCRIPTOR pfd; + + SDL_zero(pfd); + DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); + ReleaseDC(share_hwnd, hdc); + + if (!SetPixelFormat(window->driverdata->hdc, pixel_format, &pfd)) { + WIN_DestroyWindow(_this, window); + return WIN_SetError("SetPixelFormat()"); + } + } else { + if (!(window->flags & SDL_WINDOW_OPENGL)) { + return 0; + } - /* The rest of this macro mess is for OpenGL or OpenGL ES windows */ + /* The rest of this macro mess is for OpenGL or OpenGL ES windows */ #ifdef SDL_VIDEO_OPENGL_ES2 - if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES || - SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) && + if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES || + SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) && #ifdef SDL_VIDEO_OPENGL_WGL - (!_this->gl_data || WIN_GL_UseEGL(_this)) + (!_this->gl_data || WIN_GL_UseEGL(_this)) #endif /* SDL_VIDEO_OPENGL_WGL */ - ) { + ) { #ifdef SDL_VIDEO_OPENGL_EGL - if (WIN_GLES_SetupWindow(_this, window) < 0) { - WIN_DestroyWindow(_this, window); - return -1; - } - return 0; + if (WIN_GLES_SetupWindow(_this, window) < 0) { + WIN_DestroyWindow(_this, window); + return -1; + } + return 0; #else - return SDL_SetError("Could not create GLES window surface (EGL support not configured)"); + return SDL_SetError("Could not create GLES window surface (EGL support not configured)"); #endif /* SDL_VIDEO_OPENGL_EGL */ - } + } #endif /* SDL_VIDEO_OPENGL_ES2 */ #ifdef SDL_VIDEO_OPENGL_WGL - if (WIN_GL_SetupWindow(_this, window) < 0) { - WIN_DestroyWindow(_this, window); - return -1; - } + if (WIN_GL_SetupWindow(_this, window) < 0) { + WIN_DestroyWindow(_this, window); + return -1; + } #else - return SDL_SetError("Could not create GL window (WGL support not configured)"); + return SDL_SetError("Could not create GL window (WGL support not configured)"); #endif - - return 0; -} - -int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) - return -1; -#else - HWND hwnd = (HWND)SDL_GetProperty(props, "win32.hwnd", SDL_GetProperty(props, "data", NULL)); - LPTSTR title; - int titleLen; - SDL_bool isstack; - - if (!hwnd) { - return SDL_SetError("Couldn't find property win32.hwnd"); } - /* Query the title from the existing window */ - titleLen = GetWindowTextLength(hwnd); - title = SDL_small_alloc(TCHAR, titleLen + 1, &isstack); - if (title) { - titleLen = GetWindowText(hwnd, title, titleLen + 1); - } else { - titleLen = 0; - } - if (titleLen > 0) { - window->title = WIN_StringToUTF8(title); - } - if (title) { - SDL_small_free(title, isstack); - } - - if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) { - return -1; - } - -#ifdef SDL_VIDEO_OPENGL_WGL - { - HWND share_hwnd = (HWND)SDL_GetProperty(props, "win32.pixel_format_hwnd", NULL); - if (share_hwnd) { - HDC hdc = GetDC(share_hwnd); - int pixel_format = GetPixelFormat(hdc); - PIXELFORMATDESCRIPTOR pfd; - - SDL_zero(pfd); - DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); - ReleaseDC(share_hwnd, hdc); - - if (!SetPixelFormat(window->driverdata->hdc, pixel_format, &pfd)) { - return WIN_SetError("SetPixelFormat()"); - } - } else if (window->flags & SDL_WINDOW_OPENGL) { - /* Try to set up the pixel format, if it hasn't been set by the application */ - WIN_GL_SetupWindow(_this, window); - } - } -#endif return 0; -#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ } void WIN_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index a3e0c84561a14..65e1c03d1060e 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -45,7 +45,6 @@ struct SDL_WindowData HBITMAP hbm; WNDPROC wndproc; HHOOK keyboard_hook; - SDL_bool created; WPARAM mouse_button_flags; LPARAM last_pointer_update; WCHAR high_surrogate; @@ -75,8 +74,7 @@ struct SDL_WindowData UINT copybits_flag; }; -extern int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int WIN_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); +extern int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void WIN_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int WIN_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); extern int WIN_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index f9877a9ced78b..1399738c7e2b0 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -74,7 +74,7 @@ static int WINRT_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *displa static void WINRT_VideoQuit(SDL_VideoDevice *_this); /* Window functions */ -static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); +static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); static void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); static void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); static void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); @@ -581,7 +581,7 @@ static bool WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow) return true; } -int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { // Make sure that only one window gets created, at least until multimonitor // support is added. diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 1def27f26c7d3..8e9b91d2a963d 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -181,7 +181,6 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->SendWakeupEvent = X11_SendWakeupEvent; device->CreateSDLWindow = X11_CreateWindow; - device->CreateSDLWindowFrom = X11_CreateWindowFrom; device->SetWindowTitle = X11_SetWindowTitle; device->SetWindowIcon = X11_SetWindowIcon; device->SetWindowPosition = X11_SetWindowPosition; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index f8c7d5d8ba380..99238f105cfa5 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -295,7 +295,7 @@ Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwin return flags; } -static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, BOOL created) +static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) { SDL_VideoData *videodata = _this->driverdata; SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); @@ -320,7 +320,6 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, NULL); } #endif - data->created = created; data->videodata = videodata; /* Associate the data with the window */ @@ -380,8 +379,10 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, } } - /* All done! */ - window->driverdata = data; + if (window->flags & SDL_WINDOW_FOREIGN) { + /* Query the title from the existing window */ + window->title = X11_GetWindowTitle(_this, w); + } SDL_PropertiesID props = SDL_GetWindowProperties(window); int screen = (displaydata ? displaydata->screen : 0); @@ -389,6 +390,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w, SDL_SetNumberProperty(props, "SDL.window.x11.screen", screen); SDL_SetNumberProperty(props, "SDL.window.x11.window", data->xwindow); + /* All done! */ + window->driverdata = data; return 0; } @@ -422,8 +425,18 @@ static void SetWindowBordered(Display *display, int screen, Window window, SDL_b } } -int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) +int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { + Window w = (Window)SDL_GetNumberProperty(create_props, "native.x11.window", (Window)SDL_GetProperty(create_props, "native.data", NULL)); + if (w) { + window->flags |= SDL_WINDOW_FOREIGN; + + if (SetupWindowData(_this, window, w) < 0) { + return -1; + } + return 0; + } + SDL_VideoData *data = _this->driverdata; SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); const SDL_bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, SDL_FALSE); @@ -433,7 +446,6 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) Visual *visual; int depth; XSetWindowAttributes xattr; - Window w; XSizeHints *sizehints; XWMHints *wmhints; XClassHint *classhints; @@ -706,7 +718,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_XSetWMProtocols(display, w, protocols, proto_count); } - if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) { + if (SetupWindowData(_this, window, w) < 0) { X11_XDestroyWindow(display, w); return -1; } @@ -777,21 +789,6 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window) return 0; } -int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ - Window w = (Window)SDL_GetNumberProperty(props, "x11.window", (Window)SDL_GetProperty(props, "data", NULL)); - if (!w) { - return SDL_SetError("Couldn't find property x11.window"); - } - - window->title = X11_GetWindowTitle(_this, w); - - if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) { - return -1; - } - return 0; -} - char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow) { SDL_VideoData *data = _this->driverdata; @@ -1848,7 +1845,7 @@ void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_XDestroyIC(data->ic); } #endif - if (data->created) { + if (!(window->flags & SDL_WINDOW_FOREIGN)) { X11_XDestroyWindow(display, data->xwindow); X11_XFlush(display); } diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 65afecc30d533..56bc6193b63de 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -84,8 +84,7 @@ struct SDL_WindowData extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags); extern Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwindow); -extern int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); +extern int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow); extern void X11_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 14caeee49a7e5..e7c3de32be931 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1676,6 +1676,7 @@ static int video_setWindowCenteredOnDisplay(void *arg) int currentDisplay; int expectedDisplay; SDL_Rect expectedDisplayRect; + SDL_PropertiesID props; /* xVariation is the display we start on */ expectedDisplay = displays[xVariation % displayNum]; @@ -1687,7 +1688,14 @@ static int video_setWindowCenteredOnDisplay(void *arg) expectedX = (expectedDisplayRect.x + ((expectedDisplayRect.w - w) / 2)); expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2)); - window = SDL_CreateWindowWithPosition(title, x, y, w, h, 0); + props = SDL_CreateProperties(); + SDL_SetStringProperty(props, "title", title); + SDL_SetNumberProperty(props, "x", x); + SDL_SetNumberProperty(props, "w", y); + SDL_SetNumberProperty(props, "width", w); + SDL_SetNumberProperty(props, "height", h); + window = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); diff --git a/test/testnative.c b/test/testnative.c index 212a6f7a18663..ab306ee1a199c 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -148,8 +148,8 @@ int main(int argc, char *argv[]) quit(3); } props = SDL_CreateProperties(); - SDL_SetProperty(props, "data", native_window); - window = SDL_CreateWindowFrom(props); + SDL_SetProperty(props, "native.data", native_window); + window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window: %s\n", SDL_GetError()); From e0c45c6c98bc74b49a01ed7320eed284ca0ec085 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 12:21:23 -0800 Subject: [PATCH 349/725] Renamed SDL_WINDOW_FOREIGN to SDL_WINDOW_EXTERNAL --- docs/README-migration.md | 4 ++-- include/SDL3/SDL_video.h | 12 ++++++------ src/test/SDL_test_common.c | 6 +++--- src/video/SDL_video.c | 20 ++++++++++---------- src/video/cocoa/SDL_cocoavulkan.m | 2 +- src/video/cocoa/SDL_cocoawindow.m | 10 +++++----- src/video/windows/SDL_windowswindow.c | 14 +++++++------- src/video/x11/SDL_x11window.c | 13 +++++++------ test/testautomation_video.c | 2 +- test/testnative.c | 2 +- 10 files changed, 43 insertions(+), 42 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index eeda40d173bb8..a93074cd67c65 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -562,7 +562,7 @@ The following hints have been removed: * SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled -* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "native.win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend @@ -1330,7 +1330,7 @@ The following functions have been removed: * SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() * SDL_GetWindowData() - use SDL_GetWindowProperties() instead * SDL_SetWindowData() - use SDL_GetWindowProperties() instead -* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with "native.*" properties instead +* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window SDL_Window id type is named SDL_WindowID diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 3a80cf9633d2b..b0cb063b81870 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -138,7 +138,7 @@ typedef enum SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */ SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */ - SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */ + SDL_WINDOW_EXTERNAL = 0x00000800, /**< window not created by SDL */ SDL_WINDOW_HIGH_PIXEL_DENSITY = 0x00002000, /**< window uses high pixel density back buffer if possible */ SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */ @@ -827,17 +827,17 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * On macOS: * - * - "native.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. - * - "native.cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] + * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. + * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] * * On Windows: * - * - "native.win32.hwnd" (pointer) - the HWND associated with the window, if you want to wrap an existing window. - * - "native.win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows + * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want to wrap an existing window. + * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows * * On X11: * - * - "native.x11.window" (number) - the X11 Window associated with the window, if you want to wrap an existing window. + * - "x11.window" (number) - the X11 Window associated with the window, if you want to wrap an existing window. * * The SDL_Window is implicitly shown if the "hidden" property is not set. * diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index aa56394955107..12b7fee5e3b0b 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -783,8 +783,8 @@ static void SDLTest_PrintWindowFlag(char *text, size_t maxlen, Uint32 flag) case SDL_WINDOW_MOUSE_FOCUS: SDL_snprintfcat(text, maxlen, "MOUSE_FOCUS"); break; - case SDL_WINDOW_FOREIGN: - SDL_snprintfcat(text, maxlen, "FOREIGN"); + case SDL_WINDOW_EXTERNAL: + SDL_snprintfcat(text, maxlen, "EXTERNAL"); break; case SDL_WINDOW_HIGH_PIXEL_DENSITY: SDL_snprintfcat(text, maxlen, "HIGH_PIXEL_DENSITY"); @@ -835,7 +835,7 @@ static void SDLTest_PrintWindowFlags(char *text, size_t maxlen, Uint32 flags) SDL_WINDOW_MOUSE_GRABBED, SDL_WINDOW_INPUT_FOCUS, SDL_WINDOW_MOUSE_FOCUS, - SDL_WINDOW_FOREIGN, + SDL_WINDOW_EXTERNAL, SDL_WINDOW_HIGH_PIXEL_DENSITY, SDL_WINDOW_MOUSE_CAPTURE, SDL_WINDOW_ALWAYS_ON_TOP, diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 1e325794a3691..ee69721939807 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2170,15 +2170,15 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) return SDL_ContextNotSupported("Metal"); } - if (window->flags & SDL_WINDOW_FOREIGN) { - /* Can't destroy and re-create foreign windows, hrm */ - flags |= SDL_WINDOW_FOREIGN; + if (window->flags & SDL_WINDOW_EXTERNAL) { + /* Can't destroy and re-create external windows, hrm */ + flags |= SDL_WINDOW_EXTERNAL; } else { - flags &= ~SDL_WINDOW_FOREIGN; + flags &= ~SDL_WINDOW_EXTERNAL; } /* Restore video mode, etc. */ - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { const SDL_bool restore_on_show = window->restore_on_show; SDL_HideWindow(window); window->restore_on_show = restore_on_show; @@ -2223,7 +2223,7 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) SDL_Vulkan_UnloadLibrary(); } - if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) { + if (_this->DestroyWindow && !(flags & SDL_WINDOW_EXTERNAL)) { _this->DestroyWindow(_this, window); } @@ -2244,7 +2244,7 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN); window->is_destroying = SDL_FALSE; - if (_this->CreateSDLWindow && !(flags & SDL_WINDOW_FOREIGN)) { + if (_this->CreateSDLWindow && !(flags & SDL_WINDOW_EXTERNAL)) { if (_this->CreateSDLWindow(_this, window, 0) < 0) { if (loaded_opengl) { SDL_GL_UnloadLibrary(); @@ -2258,8 +2258,8 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) } } - if (flags & SDL_WINDOW_FOREIGN) { - window->flags |= SDL_WINDOW_FOREIGN; + if (flags & SDL_WINDOW_EXTERNAL) { + window->flags |= SDL_WINDOW_EXTERNAL; } if (_this->SetWindowTitle && window->title) { @@ -3556,7 +3556,7 @@ void SDL_DestroyWindow(SDL_Window *window) /* Restore video mode, etc. */ SDL_UpdateFullscreenMode(window, SDL_FALSE); - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { SDL_HideWindow(window); } diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index a018db5a82805..3586e8f64bd09 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -256,7 +256,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this, return SDL_FALSE; } - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { @autoreleasepool { SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; if (![data.sdlContentView.layer isKindOfClass:[CAMetalLayer class]]) { diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 64b541b21ef54..b4c0bf7d2a898 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1861,7 +1861,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow */ [nswindow setOneShot:NO]; - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { /* Query the title from the existing window */ NSString *title = [nswindow title]; if (title) { @@ -1883,7 +1883,7 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie { @autoreleasepool { SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)_this->driverdata; - const void *data = SDL_GetProperty(create_props, "native.data", NULL); + const void *data = SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL); NSWindow *nswindow = nil; NSView *nsview = nil; @@ -1896,8 +1896,8 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie SDL_assert(false); } } else { - nswindow = (__bridge NSWindow *)SDL_GetProperty(create_props, "native.cocoa.window", NULL); - nsview = (__bridge NSView *)SDL_GetProperty(create_props, "native.cocoa.view", NULL); + nswindow = (__bridge NSWindow *)SDL_GetProperty(create_props, "cocoa.window", NULL); + nsview = (__bridge NSView *)SDL_GetProperty(create_props, "cocoa.view", NULL); } if (nswindow && !nsview) { nsview = [nswindow contentView]; @@ -1906,7 +1906,7 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie nswindow = [nsview window]; } if (nswindow) { - window->flags |= SDL_WINDOW_FOREIGN; + window->flags |= SDL_WINDOW_EXTERNAL; } else { int x, y; NSScreen *screen; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 8a3b6cc2d0cf5..2665a21ae91a3 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -347,7 +347,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd int w = rect.right; int h = rect.bottom; - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { window->windowed.w = window->w = w; window->windowed.h = window->h = h; } else if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) { @@ -370,7 +370,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd point.x = 0; point.y = 0; if (ClientToScreen(hwnd, &point)) { - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { window->windowed.x = point.x; window->windowed.y = point.y; } @@ -443,7 +443,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd data->initializing = SDL_FALSE; - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { /* Query the title from the existing window */ LPTSTR title; int titleLen; @@ -490,7 +490,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window) ReleaseDC(data->hwnd, data->hdc); RemoveProp(data->hwnd, TEXT("SDL_WindowData")); #endif - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { DestroyWindow(data->hwnd); if (data->destroy_parent_with_window && data->parent) { DestroyWindow(data->parent); @@ -566,10 +566,10 @@ static void WIN_SetKeyboardFocus(SDL_Window *window) int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { - HWND hwnd = (HWND)SDL_GetProperty(create_props, "native.win32.hwnd", SDL_GetProperty(create_props, "native.data", NULL)); + HWND hwnd = (HWND)SDL_GetProperty(create_props, "win32.hwnd", SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL)); HWND parent = NULL; if (hwnd) { - window->flags |= SDL_WINDOW_FOREIGN; + window->flags |= SDL_WINDOW_EXTERNAL; if (SetupWindowData(_this, window, hwnd, parent) < 0) { return -1; @@ -643,7 +643,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI } } - HWND share_hwnd = (HWND)SDL_GetProperty(create_props, "native.win32.pixel_format_hwnd", NULL); + HWND share_hwnd = (HWND)SDL_GetProperty(create_props, "win32.pixel_format_hwnd", NULL); if (share_hwnd) { HDC hdc = GetDC(share_hwnd); int pixel_format = GetPixelFormat(hdc); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 99238f105cfa5..373590ec2cf74 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -379,7 +379,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) } } - if (window->flags & SDL_WINDOW_FOREIGN) { + if (window->flags & SDL_WINDOW_EXTERNAL) { /* Query the title from the existing window */ window->title = X11_GetWindowTitle(_this, w); } @@ -427,9 +427,10 @@ static void SetWindowBordered(Display *display, int screen, Window window, SDL_b int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { - Window w = (Window)SDL_GetNumberProperty(create_props, "native.x11.window", (Window)SDL_GetProperty(create_props, "native.data", NULL)); + Window w = (Window)SDL_GetNumberProperty(create_props, "x11.window", + (Window)SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL)); if (w) { - window->flags |= SDL_WINDOW_FOREIGN; + window->flags |= SDL_WINDOW_EXTERNAL; if (SetupWindowData(_this, window, w) < 0) { return -1; @@ -1335,7 +1336,7 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Blocking wait for "MapNotify" event. * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type, * and XCheckTypedWindowEvent doesn't block */ - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); } X11_XFlush(display); @@ -1371,7 +1372,7 @@ void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) if (X11_IsWindowMapped(_this, window)) { X11_XWithdrawWindow(display, data->xwindow, displaydata->screen); /* Blocking wait for "UnmapNotify" event */ - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); } X11_XFlush(display); @@ -1845,7 +1846,7 @@ void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_XDestroyIC(data->ic); } #endif - if (!(window->flags & SDL_WINDOW_FOREIGN)) { + if (!(window->flags & SDL_WINDOW_EXTERNAL)) { X11_XDestroyWindow(display, data->xwindow); X11_XFlush(display); } diff --git a/test/testautomation_video.c b/test/testautomation_video.c index e7c3de32be931..50b88cdceed86 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -233,7 +233,7 @@ static int video_createWindowVariousFlags(void *arg) flags = SDL_WINDOW_MOUSE_FOCUS; break; case 12: - flags = SDL_WINDOW_FOREIGN; + flags = SDL_WINDOW_EXTERNAL; break; case 13: flags = SDL_WINDOW_KEYBOARD_GRABBED; diff --git a/test/testnative.c b/test/testnative.c index ab306ee1a199c..e18195301f077 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) quit(3); } props = SDL_CreateProperties(); - SDL_SetProperty(props, "native.data", native_window); + SDL_SetProperty(props, "sdl2-compat.external_window", native_window); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); if (!window) { From 72036415978ed1de5cc034781e70cdc73f09227c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 13:58:33 -0800 Subject: [PATCH 350/725] Note that the SDL window properties are read-only --- include/SDL3/SDL_video.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index b0cb063b81870..c12c1115b32e3 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -902,7 +902,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); /** * Get the properties associated with a window. * - * The following properties are provided by SDL: + * The following read-only properties are provided by SDL: * * On Android: * From 1c64366b8097ff9e9361e878f6aff793dcde3bf1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 12:13:20 -0800 Subject: [PATCH 351/725] Added SDL_CreateRendererWithProperties() and SDL_CreateTextureWithProperties() --- include/SDL3/SDL_render.h | 127 +++++++++++++++++------ src/dynapi/SDL_dynapi.sym | 2 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/render/SDL_render.c | 71 ++++++++++--- src/render/SDL_sysrender.h | 4 +- src/render/direct3d/SDL_render_d3d.c | 8 +- src/render/direct3d11/SDL_render_d3d11.c | 75 ++++++++----- src/render/direct3d12/SDL_render_d3d12.c | 103 +++++++++++------- src/render/metal/SDL_render_metal.m | 6 +- src/render/opengl/SDL_render_gl.c | 65 +++++++++--- src/render/opengles2/SDL_render_gles2.c | 63 +++++++---- src/render/ps2/SDL_render_ps2.c | 12 ++- src/render/psp/SDL_render_psp.c | 10 +- src/render/software/SDL_render_sw.c | 10 +- src/render/vitagxm/SDL_render_vita_gxm.c | 11 +- 16 files changed, 404 insertions(+), 167 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 86a2abb1a050e..b7313d9d09d2e 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -195,7 +195,6 @@ extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); */ extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); - /** * Create a window and default renderer. * @@ -215,14 +214,13 @@ extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); */ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags, SDL_Window **window, SDL_Renderer **renderer); - /** * Create a 2D rendering context for a window. * * If you want a specific renderer, you can specify its name here. A list of * available renderers can be obtained by calling SDL_GetRenderDriver multiple * times, with indices from 0 to SDL_GetNumRenderDrivers()-1. If you don't - * need a specific renderer, specify NULL and SDL will attempt to chooes the + * need a specific renderer, specify NULL and SDL will attempt to choose the * best option for you, based on what is available on the user's system. * * By default the rendering size matches the window size in pixels, but you @@ -238,13 +236,37 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, U * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateRendererWithProperties * \sa SDL_CreateSoftwareRenderer * \sa SDL_DestroyRenderer * \sa SDL_GetNumRenderDrivers * \sa SDL_GetRenderDriver * \sa SDL_GetRendererInfo */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags); +extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags); + +/** + * Create a 2D rendering context for a window, with the specified properties. + * + * These are the supported properties: + * + * - "window" (pointer) - the window where rendering is displayed + * - "surface" (pointer) - the surface where rendering is displayed, if you want a software renderer without a window + * - "name" (string) - the name of the rendering driver to use, if a specific one is desired + * - "present_vsync" (boolean) - true if you want present synchronized with the refresh rate + * + * \param props the properties to use + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_CreateSoftwareRenderer + * \sa SDL_DestroyRenderer + * \sa SDL_GetRendererInfo + */ +extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); /** * Create a 2D software rendering context for a surface. @@ -309,7 +331,7 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: + * The following read-only properties are provided by SDL: * * ``` * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer @@ -386,6 +408,7 @@ extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *rendere * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture * \sa SDL_QueryTexture * \sa SDL_UpdateTexture @@ -413,50 +436,96 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTexture + * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture * \sa SDL_QueryTexture */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); +/** + * Create a texture for a rendering context with the specified properties. + * + * These are the supported properties: + * + * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer + * - "access" (number) - one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC + * - "width" (number) - the width of the texture in pixels, required + * - "height" (number) - the height of the texture in pixels, required + * + * With the direct3d11 renderer: + * + * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. + * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * + * With the direct3d12 renderer: + * + * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the texture, if you want to wrap an existing texture. + * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * + * With the opengl renderer: + * + * - "opengl.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * + * With the opengles2 renderer: + * + * - "opengles2.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - "opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * + * \param renderer the rendering context + * \param props the properties to use + * \returns a pointer to the created texture or NULL if no rendering context + * was active, the format was unsupported, or the width or height + * were out of range; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTexture + * \sa SDL_DestroyTexture + * \sa SDL_QueryTexture + * \sa SDL_UpdateTexture + */ +extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); + /** * Get the properties associated with a texture. * - * The following properties are provided by SDL: + * The following read-only properties are provided by SDL: * * With the direct3d11 renderer: * - * ``` - * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture - * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture - * "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture - * ``` + * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture + * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture + * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture * * With the direct3d12 renderer: * - * ``` - * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture - * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture - * "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture - * ``` + * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture + * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture + * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture * * With the opengl renderer: * - * ``` - * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture - * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture - * "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) - * "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) - * ``` + * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture + * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture + * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture + * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) + * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * ``` - * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture - * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture - * "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture - * ``` + * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture + * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture + * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index bb55f404c9a4c..14bc32ae91eac 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -965,6 +965,8 @@ SDL3_0.0.0 { SDL_EnumerateProperties; SDL_SetBooleanProperty; SDL_GetBooleanProperty; + SDL_CreateTextureWithProperties; + SDL_CreateRendererWithProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 57e1affe2342f..83ec2ca332f7d 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -990,3 +990,5 @@ #define SDL_EnumerateProperties SDL_EnumerateProperties_REAL #define SDL_SetBooleanProperty SDL_SetBooleanProperty_REAL #define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL +#define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL +#define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 3d8049d023a52..7ddba0e8c8c2a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1015,3 +1015,5 @@ SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, f SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 8f987e84d0f77..aedde6af332c8 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -804,15 +804,23 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind #endif /* !SDL_RENDER_DISABLED */ -SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) + +SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) { #ifndef SDL_RENDER_DISABLED + SDL_Window *window = SDL_GetProperty(props, "window", NULL); + SDL_Surface *surface = SDL_GetProperty(props, "surface", NULL); + const char *name = SDL_GetStringProperty(props, "name", NULL); SDL_Renderer *renderer = NULL; const int n = SDL_GetNumRenderDrivers(); SDL_bool batching = SDL_TRUE; const char *hint; int i; + if (!window && surface) { + return SDL_CreateSoftwareRenderer(surface); + } + #ifdef __ANDROID__ Android_ActivityMutex_Lock_Running(); #endif @@ -834,11 +842,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); if (hint && *hint) { - if (SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)) { - flags |= SDL_RENDERER_PRESENTVSYNC; - } else { - flags &= ~SDL_RENDERER_PRESENTVSYNC; - } + SDL_SetBooleanProperty(props, "present_vsync", SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); } if (!name) { @@ -850,7 +854,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl const SDL_RenderDriver *driver = render_drivers[i]; if (SDL_strcasecmp(name, driver->info.name) == 0) { /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, flags); + renderer = driver->CreateRenderer(window, props); if (renderer) { batching = SDL_FALSE; } @@ -860,13 +864,11 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl } else { for (i = 0; i < n; i++) { const SDL_RenderDriver *driver = render_drivers[i]; - if ((driver->info.flags & flags) == flags) { - /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, flags); - if (renderer) { - /* Yay, we got one! */ - break; - } + /* Create a new renderer instance */ + renderer = driver->CreateRenderer(window, props); + if (renderer) { + /* Yay, we got one! */ + break; } } } @@ -876,7 +878,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl goto error; } - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(props, "present_vsync", SDL_FALSE)) { renderer->wanted_vsync = SDL_TRUE; if (!(renderer->info.flags & SDL_RENDERER_PRESENTVSYNC)) { @@ -956,6 +958,24 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl #endif } +SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) +{ + SDL_Renderer *renderer; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetProperty(props, "window", window); + if (flags & SDL_RENDERER_SOFTWARE) { + SDL_SetStringProperty(props, "name", "software"); + } else { + SDL_SetStringProperty(props, "name", name); + } + if (flags & SDL_RENDERER_PRESENTVSYNC) { + SDL_SetBooleanProperty(props, "present_vsync", SDL_TRUE); + } + renderer = SDL_CreateRendererWithProperties(props); + SDL_DestroyProperties(props); + return renderer; +} + SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) { #if !defined(SDL_RENDER_DISABLED) && SDL_VIDEO_RENDER_SW @@ -1116,9 +1136,13 @@ static SDL_ScaleMode SDL_GetScaleMode(void) } } -SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props) { SDL_Texture *texture; + Uint32 format = (Uint32)SDL_GetNumberProperty(props, "format", SDL_PIXELFORMAT_UNKNOWN); + int access = (int)SDL_GetNumberProperty(props, "access", SDL_TEXTUREACCESS_STATIC); + int w = (int)SDL_GetNumberProperty(props, "width", 0); + int h = (int)SDL_GetNumberProperty(props, "height", 0); SDL_bool texture_is_fourcc_and_target; CHECK_RENDERER_MAGIC(renderer, NULL); @@ -1177,7 +1201,7 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(texture->format)); if (texture_is_fourcc_and_target == SDL_FALSE && IsSupportedFormat(renderer, format)) { - if (renderer->CreateTexture(renderer, texture) < 0) { + if (renderer->CreateTexture(renderer, texture, props) < 0) { SDL_DestroyTexture(texture); return NULL; } @@ -1232,6 +1256,19 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access return texture; } +SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +{ + SDL_Texture *texture; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetNumberProperty(props, "format", format); + SDL_SetNumberProperty(props, "access", access); + SDL_SetNumberProperty(props, "width", w); + SDL_SetNumberProperty(props, "height", h); + texture = SDL_CreateTextureWithProperties(renderer, props); + SDL_DestroyProperties(props); + return texture; +} + SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface) { const SDL_PixelFormat *fmt; diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index edba7e18e0c88..187073de13097 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -160,7 +160,7 @@ struct SDL_Renderer void (*WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event); int (*GetOutputSize)(SDL_Renderer *renderer, int *w, int *h); SDL_bool (*SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode); - int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture); + int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); int (*QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd); int (*QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd); int (*QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, @@ -280,7 +280,7 @@ struct SDL_Renderer /* Define the SDL render driver structure */ struct SDL_RenderDriver { - SDL_Renderer *(*CreateRenderer)(SDL_Window *window, Uint32 flags); + SDL_Renderer *(*CreateRenderer)(SDL_Window *window, SDL_PropertiesID props); /* Info about the renderer capabilities */ SDL_RendererInfo info; diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 7d6428932b3cf..6a882ce0f101e 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -517,7 +517,7 @@ static void D3D_DestroyTextureRep(D3D_TextureRep *texture) } } -static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata; @@ -1493,7 +1493,7 @@ static int D3D_Reset(SDL_Renderer *renderer) /* Allocate application render targets */ for (texture = renderer->textures; texture; texture = texture->next) { if (texture->access == SDL_TEXTUREACCESS_TARGET) { - D3D_CreateTexture(renderer, texture); + D3D_CreateTexture(renderer, texture, 0); } } @@ -1536,7 +1536,7 @@ static int D3D_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D_RenderData *data; @@ -1617,7 +1617,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) pparams.BackBufferFormat = D3DFMT_UNKNOWN; pparams.FullScreen_RefreshRateInHz = 0; } - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 4561dfe300d5e..5e4eba0f40d05 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1062,7 +1062,19 @@ static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl return SDL_TRUE; } -static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D11Texture2D **texture) +{ + IUnknown *unknown = SDL_GetProperty(props, name, NULL); + if (unknown) { + HRESULT result = IUnknown_QueryInterface(unknown, &SDL_IID_ID3D11Texture2D, (void **)texture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(name, result); + } + } + return 0; +} + +static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData; @@ -1109,13 +1121,18 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; } - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTexture); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture", &textureData->mainTexture) < 0) { + return -1; + } + if (!textureData->mainTexture) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTexture); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture", textureData->mainTexture); #if SDL_HAVE_YUV @@ -1126,23 +1143,33 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) textureDesc.Width = (textureDesc.Width + 1) / 2; textureDesc.Height = (textureDesc.Height + 1) / 2; - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTextureU); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture_u", &textureData->mainTextureU) < 0) { + return -1; + } + if (!textureData->mainTextureU) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTextureU); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_u", textureData->mainTextureU); - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTextureV); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture_v", &textureData->mainTextureV) < 0) { + return -1; + } + if (!textureData->mainTextureV) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTextureV); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_v", textureData->mainTextureV); } @@ -2384,7 +2411,7 @@ static int D3D11_SetVSync(SDL_Renderer *renderer, const int vsync) } #endif -SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D11_RenderData *data; @@ -2445,7 +2472,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) */ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; #else - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D11_SetVSync; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 1442be58ee13a..c241c3bc9cbcf 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1432,7 +1432,19 @@ static void D3D12_FreeSRVIndex(SDL_Renderer *renderer, SIZE_T index) rendererData->srvPoolHead = &rendererData->srvPoolNodes[index]; } -static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D12Resource **texture) +{ + IUnknown *unknown = SDL_GetProperty(props, name, NULL); + if (unknown) { + HRESULT result = D3D_CALL(unknown, QueryInterface, D3D_GUID(SDL_IID_ID3D12Resource), (void **)texture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(name, result); + } + } + return 0; +} + +static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData; @@ -1476,28 +1488,10 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) heapProps.CreationNodeMask = 1; heapProps.VisibleNodeMask = 1; - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &textureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTexture); - textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + if (GetTextureProperty(create_props, "d3d12.texture", &textureData->mainTexture) < 0) { + return -1; } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture", textureData->mainTexture); -#if SDL_HAVE_YUV - if (texture->format == SDL_PIXELFORMAT_YV12 || - texture->format == SDL_PIXELFORMAT_IYUV) { - textureData->yuv = SDL_TRUE; - - textureDesc.Width = (textureDesc.Width + 1) / 2; - textureDesc.Height = (textureDesc.Height + 1) / 2; - + if (!textureData->mainTexture) { result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, &heapProps, D3D12_HEAP_FLAG_NONE, @@ -1505,27 +1499,60 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_RESOURCE_STATE_COPY_DEST, NULL, D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureU); - textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST; + (void **)&textureData->mainTexture); if (FAILED(result)) { D3D12_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); } + } + textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST; + SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture", textureData->mainTexture); +#if SDL_HAVE_YUV + if (texture->format == SDL_PIXELFORMAT_YV12 || + texture->format == SDL_PIXELFORMAT_IYUV) { + textureData->yuv = SDL_TRUE; + + textureDesc.Width = (textureDesc.Width + 1) / 2; + textureDesc.Height = (textureDesc.Height + 1) / 2; + + if (GetTextureProperty(create_props, "d3d12.texture_u", &textureData->mainTextureU) < 0) { + return -1; + } + if (!textureData->mainTextureU) { + result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + NULL, + D3D_GUID(SDL_IID_ID3D12Resource), + (void **)&textureData->mainTextureU); + if (FAILED(result)) { + D3D12_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + } + } + textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST; SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_u", textureData->mainTextureU); - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &textureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureV); - textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + if (GetTextureProperty(create_props, "d3d12.texture_v", &textureData->mainTextureV) < 0) { + return -1; } + if (!textureData->mainTextureV) { + result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + NULL, + D3D_GUID(SDL_IID_ID3D12Resource), + (void **)&textureData->mainTextureV); + if (FAILED(result)) { + D3D12_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + } + } + textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST; SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_v", textureData->mainTextureV); } @@ -2943,7 +2970,7 @@ static int D3D12_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D12_RenderData *data; @@ -2990,7 +3017,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D12_SetVSync; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index a215ff5c6298a..285d42018ec12 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -544,7 +544,7 @@ static SDL_bool METAL_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl return SDL_TRUE; } -static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { @autoreleasepool { METAL_RenderData *data = (__bridge METAL_RenderData *)renderer->driverdata; @@ -1653,7 +1653,7 @@ static SDL_MetalView GetWindowView(SDL_Window *window) return nil; } -static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { @autoreleasepool { SDL_Renderer *renderer = NULL; @@ -1921,7 +1921,7 @@ in case we want to use it later (recreating the renderer) #if (defined(__MACOS__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST if (@available(macOS 10.13, *)) { - data.mtllayer.displaySyncEnabled = (flags & SDL_RENDERER_PRESENTVSYNC) != 0; + data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE); if (data.mtllayer.displaySyncEnabled) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 523e8ac7eec67..d63eef782123d 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -125,6 +125,7 @@ typedef struct typedef struct { GLuint texture; + SDL_bool texture_external; GLfloat texw; GLfloat texh; GLenum format; @@ -139,7 +140,9 @@ typedef struct SDL_bool yuv; SDL_bool nv12; GLuint utexture; + SDL_bool utexture_external; GLuint vtexture; + SDL_bool vtexture_external; #endif GL_FBOList *fbo; @@ -434,7 +437,7 @@ static SDL_bool convert_format(GL_RenderData *renderdata, Uint32 pixel_format, return SDL_TRUE; } -static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GL_RenderData *renderdata = (GL_RenderData *)renderer->driverdata; const GLenum textype = renderdata->textype; @@ -491,14 +494,19 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) data->fbo = NULL; } - GL_CheckError("", renderer); - renderdata->glGenTextures(1, &data->texture); - if (GL_CheckError("glGenTextures()", renderer) < 0) { - if (data->pixels) { - SDL_free(data->pixels); + data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture", 0); + if (data->texture) { + data->texture_external = SDL_TRUE; + } else { + GL_CheckError("", renderer); + renderdata->glGenTextures(1, &data->texture); + if (GL_CheckError("glGenTextures()", renderer) < 0) { + if (data->pixels) { + SDL_free(data->pixels); + } + SDL_free(data); + return -1; } - SDL_free(data); - return -1; } texture->driverdata = data; @@ -580,8 +588,18 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) texture->format == SDL_PIXELFORMAT_IYUV) { data->yuv = SDL_TRUE; - renderdata->glGenTextures(1, &data->utexture); - renderdata->glGenTextures(1, &data->vtexture); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_u", 0); + if (data->utexture) { + data->utexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->utexture); + } + data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_v", 0); + if (data->vtexture) { + data->vtexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->vtexture); + } renderdata->glBindTexture(textype, data->utexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, @@ -614,7 +632,12 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) texture->format == SDL_PIXELFORMAT_NV21) { data->nv12 = SDL_TRUE; - renderdata->glGenTextures(1, &data->utexture); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_uv", 0); + if (data->utexture) { + data->utexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->utexture); + } renderdata->glBindTexture(textype, data->utexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode); @@ -626,6 +649,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); 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.texture.opengl.texture_uv", data->utexture); } #endif @@ -1500,13 +1524,22 @@ static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (!data) { return; } - if (data->texture) { + if (data->texture && !data->texture_external) { renderdata->glDeleteTextures(1, &data->texture); } #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glDeleteTextures(1, &data->utexture); - renderdata->glDeleteTextures(1, &data->vtexture); + if (!data->utexture_external) { + renderdata->glDeleteTextures(1, &data->utexture); + } + if (!data->vtexture_external) { + renderdata->glDeleteTextures(1, &data->vtexture); + } + } + if (data->nv12) { + if (!data->utexture_external) { + renderdata->glDeleteTextures(1, &data->utexture); + } } #endif SDL_free(data->pixels); @@ -1702,7 +1735,7 @@ static SDL_bool GL_IsProbablyAccelerated(const GL_RenderData *data) return SDL_TRUE; } -static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; GL_RenderData *data; @@ -1807,7 +1840,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) */ #endif - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index cb03179ef8258..d56568877095f 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -61,6 +61,7 @@ struct GLES2_FBOList typedef struct GLES2_TextureData { GLuint texture; + SDL_bool texture_external; GLenum texture_type; GLenum pixel_format; GLenum pixel_type; @@ -71,7 +72,9 @@ typedef struct GLES2_TextureData SDL_bool yuv; SDL_bool nv12; GLuint texture_v; + GLuint texture_v_external; GLuint texture_u; + GLuint texture_u_external; #endif GLES2_FBOList *fbo; } GLES2_TextureData; @@ -1396,7 +1399,7 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer); } -static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata; GLES2_TextureData *data; @@ -1488,9 +1491,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glGenTextures(1, &data->texture_v); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_v", 0); + if (data->texture_v) { + data->texture_v_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_v); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE2); renderdata->glBindTexture(data->texture_type, data->texture_v); @@ -1501,9 +1509,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) 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.texture.opengles2.texture_v", data->texture_v); - renderdata->glGenTextures(1, &data->texture_u); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_u", 0); + if (data->texture_u) { + data->texture_u_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_u); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); @@ -1518,9 +1531,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", data->texture_u); } else if (data->nv12) { - renderdata->glGenTextures(1, &data->texture_u); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_uv", 0); + if (data->texture_u) { + data->texture_u_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_u); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); @@ -1536,9 +1554,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) } #endif - renderdata->glGenTextures(1, &data->texture); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture", 0); + if (data->texture) { + data->texture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } texture->driverdata = data; renderdata->glActiveTexture(GL_TEXTURE0); @@ -1893,12 +1916,14 @@ static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) /* Destroy the texture */ if (tdata) { - data->glDeleteTextures(1, &tdata->texture); + if (tdata->texture && !tdata->texture_external) { + data->glDeleteTextures(1, &tdata->texture); + } #if SDL_HAVE_YUV - if (tdata->texture_v) { + if (tdata->texture_v && !tdata->texture_v_external) { data->glDeleteTextures(1, &tdata->texture_v); } - if (tdata->texture_u) { + if (tdata->texture_u && !tdata->texture_u_external) { data->glDeleteTextures(1, &tdata->texture_u); } #endif @@ -2052,7 +2077,7 @@ static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture) * Renderer instantiation * *************************************************************************************************/ -static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; GLES2_RenderData *data; @@ -2139,10 +2164,10 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) * is turned on. Not doing so will freeze the screen's contents to that * of the first drawn frame. */ - flags |= SDL_RENDERER_PRESENTVSYNC; + SDL_SetBooleanProperty(create_props, "present_vsync", SDL_TRUE); #endif - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index febf7031a95a7..467d2745c048a 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -100,7 +100,7 @@ static void PS2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event { } -static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GSTEXTURE *ps2_tex = (GSTEXTURE *)SDL_calloc(1, sizeof(GSTEXTURE)); @@ -574,7 +574,7 @@ static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; PS2_RenderData *data; @@ -634,7 +634,9 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) data->gsGlobal = gsGlobal; dynamicVsync = SDL_GetHintBoolean(SDL_HINT_PS2_DYNAMIC_VSYNC, SDL_FALSE); - data->vsync = flags & SDL_RENDERER_PRESENTVSYNC ? (dynamicVsync ? 2 : 1) : 0; + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + data->vsync = (dynamicVsync ? 2 : 1); + } renderer->WindowEvent = PS2_WindowEvent; renderer->CreateTexture = PS2_CreateTexture; @@ -655,9 +657,13 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyRenderer = PS2_DestroyRenderer; renderer->SetVSync = PS2_SetVSync; renderer->info = PS2_RenderDriver.info; + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; + if (data->vsync) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; + } return renderer; } diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 1f5a28385a1db..3fe45e2af0bce 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -478,7 +478,7 @@ static void PSP_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event { } -static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { PSP_RenderData *data = renderer->driverdata; PSP_TextureData *psp_texture = (PSP_TextureData *)SDL_calloc(1, sizeof(*psp_texture)); @@ -1290,9 +1290,8 @@ static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { - SDL_Renderer *renderer; PSP_RenderData *data; int pixelformat; @@ -1341,7 +1340,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) data->most_recent_target = NULL; data->least_recent_target = NULL; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { data->vsync = SDL_TRUE; } else { data->vsync = SDL_FALSE; @@ -1400,6 +1399,9 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) sceKernelRegisterSubIntrHandler(PSP_VBLANK_INT, 0, psp_on_vblank, data); sceKernelEnableSubIntr(PSP_VBLANK_INT, 0); + if (data->vsync) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; + } return renderer; } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index ed428d3fc4266..8f10ef7f0f769 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -97,7 +97,7 @@ static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) return SDL_SetError("Software renderer doesn't have an output surface"); } -static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format); @@ -1147,7 +1147,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) return renderer; } -static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { const char *hint; SDL_Surface *surface; @@ -1162,7 +1162,11 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) } if (no_hint_set) { - SDL_SetHint(SDL_HINT_RENDER_VSYNC, (flags & SDL_RENDERER_PRESENTVSYNC) ? "1" : "0"); + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); + } else { + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0"); + } } surface = SDL_GetWindowSurface(window); diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 289ab06f8f4be..ec0fe146a507f 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -42,13 +42,13 @@ #include #endif -static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags); +static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props); static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); -static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture); +static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); static int VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); @@ -209,7 +209,7 @@ static int VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; VITA_GXM_RenderData *data; @@ -258,8 +258,9 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) data->initialized = SDL_TRUE; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { data->displayData.wait_vblank = SDL_TRUE; + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } else { data->displayData.wait_vblank = SDL_FALSE; } @@ -288,7 +289,7 @@ static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode return SDL_FALSE; } -static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData)); From 924de4df4865c325f905fca926490c7d4bf784e0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 21:11:51 -0800 Subject: [PATCH 352/725] Enable transparent windows when using the D3D11 renderer Note that this will not work with D3D12, as DXGI_SWAP_EFFECT_DISCARD is not available there. --- src/render/direct3d11/SDL_render_d3d11.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 5e4eba0f40d05..2263f883276c0 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -786,7 +786,12 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) swapChainDesc.Scaling = DXGI_SCALING_STRETCH; } } - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */ + if (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_TRANSPARENT) { + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + } else { + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */ + } #endif swapChainDesc.Flags = 0; From f5600fd9f4f0f0bcde3ee1e54574fa6ab0a4f585 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 14 Nov 2023 06:28:27 -0800 Subject: [PATCH 353/725] Fall back to using the physical profile for Apple controllers if they don't match a standard profile We may want to flip this to be the default, but it needs more testing. --- src/joystick/apple/SDL_mfijoystick.m | 299 +++++++++++++++---------- src/joystick/apple/SDL_mfijoystick_c.h | 7 + 2 files changed, 183 insertions(+), 123 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 1d45799e16505..e53ddd01fa2b7 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -271,32 +271,116 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } #endif + BOOL is_xbox = IsControllerXbox(controller); + BOOL is_ps4 = IsControllerPS4(controller); + BOOL is_ps5 = IsControllerPS5(controller); + BOOL is_switch_pro = IsControllerSwitchPro(controller); + BOOL is_switch_joycon_pair = IsControllerSwitchJoyConPair(controller); + BOOL is_stadia = IsControllerStadia(controller); + BOOL is_backbone_one = IsControllerBackboneOne(controller); + BOOL is_switch_joyconL = IsControllerSwitchJoyConL(controller); + BOOL is_switch_joyconR = IsControllerSwitchJoyConR(controller); +#ifdef SDL_JOYSTICK_HIDAPI + if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE)) || + (is_ps4 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS4)) || + (is_ps5 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS5)) || + (is_switch_pro && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO)) || + (is_switch_joycon_pair && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR, 0, "")) || + (is_stadia && HIDAPI_IsDevicePresent(USB_VENDOR_GOOGLE, USB_PRODUCT_GOOGLE_STADIA_CONTROLLER, 0, "")) || + (is_switch_joyconL && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT, 0, "")) || + (is_switch_joyconR && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT, 0, ""))) { + /* The HIDAPI driver is taking care of this device */ + return FALSE; + } +#else + (void)is_stadia; + (void)is_switch_joyconL; + (void)is_switch_joyconR; +#endif + + if (is_backbone_one) { + vendor = USB_VENDOR_BACKBONE; + if (is_ps5) { + product = USB_PRODUCT_BACKBONE_ONE_IOS_PS5; + } else { + product = USB_PRODUCT_BACKBONE_ONE_IOS; + } + subtype = 0; + } else if (is_xbox) { + vendor = USB_VENDOR_MICROSOFT; + if (device->has_xbox_paddles) { + /* Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID */ + product = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH; + subtype = 1; + } else if (device->has_xbox_share_button) { + /* Assume Xbox Series X Controller unless/until GCController flows VID/PID */ + product = USB_PRODUCT_XBOX_SERIES_X_BLE; + subtype = 1; + } else { + /* Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID */ + product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; + subtype = 0; + } + } else if (is_ps4) { + /* Assume DS4 Slim unless/until GCController flows VID/PID */ + vendor = USB_VENDOR_SONY; + product = USB_PRODUCT_SONY_DS4_SLIM; + if (device->has_dualshock_touchpad) { + subtype = 1; + } else { + subtype = 0; + } + } else if (is_ps5) { + vendor = USB_VENDOR_SONY; + product = USB_PRODUCT_SONY_DS5; + subtype = 0; + } else if (is_switch_pro) { + vendor = USB_VENDOR_NINTENDO; + product = USB_PRODUCT_NINTENDO_SWITCH_PRO; + subtype = 0; + } else if (is_switch_joycon_pair) { + vendor = USB_VENDOR_NINTENDO; + product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; + subtype = 0; + } else if (is_switch_joyconL) { + vendor = USB_VENDOR_NINTENDO; + product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT; + subtype = 0; + } else if (is_switch_joyconR) { + vendor = USB_VENDOR_NINTENDO; + product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT; + subtype = 0; + } else if (controller.extendedGamepad) { + vendor = USB_VENDOR_APPLE; + product = 1; + subtype = 1; + } else if (controller.gamepad) { + vendor = USB_VENDOR_APPLE; + product = 2; + subtype = 2; +#if TARGET_OS_TV + } else if (controller.microGamepad) { + vendor = USB_VENDOR_APPLE; + product = 3; + subtype = 3; +#endif +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + } else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + vendor = USB_VENDOR_APPLE; + product = 4; + subtype = 4; +#endif + } else { + vendor = USB_VENDOR_APPLE; + product = 5; + subtype = 5; + } + if (controller.extendedGamepad) { GCExtendedGamepad *gamepad = controller.extendedGamepad; - BOOL is_xbox = IsControllerXbox(controller); - BOOL is_ps4 = IsControllerPS4(controller); - BOOL is_ps5 = IsControllerPS5(controller); - BOOL is_switch_pro = IsControllerSwitchPro(controller); - BOOL is_switch_joycon_pair = IsControllerSwitchJoyConPair(controller); - BOOL is_stadia = IsControllerStadia(controller); - BOOL is_backbone_one = IsControllerBackboneOne(controller); int nbuttons = 0; BOOL has_direct_menu; -#ifdef SDL_JOYSTICK_HIDAPI - if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE)) || - (is_ps4 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS4)) || - (is_ps5 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS5)) || - (is_switch_pro && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO)) || - (is_switch_joycon_pair && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR, 0, "")) || - (is_stadia && HIDAPI_IsDevicePresent(USB_VENDOR_GOOGLE, USB_PRODUCT_GOOGLE_STADIA_CONTROLLER, 0, ""))) { - /* The HIDAPI driver is taking care of this device */ - return FALSE; - } -#else - (void)is_stadia; -#endif - /* These buttons are part of the original MFi spec */ device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); @@ -378,56 +462,6 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle #endif #pragma clang diagnostic pop - if (is_backbone_one) { - vendor = USB_VENDOR_BACKBONE; - if (is_ps5) { - product = USB_PRODUCT_BACKBONE_ONE_IOS_PS5; - } else { - product = USB_PRODUCT_BACKBONE_ONE_IOS; - } - subtype = 0; - } else if (is_xbox) { - vendor = USB_VENDOR_MICROSOFT; - if (device->has_xbox_paddles) { - /* Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID */ - product = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH; - subtype = 1; - } else if (device->has_xbox_share_button) { - /* Assume Xbox Series X Controller unless/until GCController flows VID/PID */ - product = USB_PRODUCT_XBOX_SERIES_X_BLE; - subtype = 1; - } else { - /* Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID */ - product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; - subtype = 0; - } - } else if (is_ps4) { - /* Assume DS4 Slim unless/until GCController flows VID/PID */ - vendor = USB_VENDOR_SONY; - product = USB_PRODUCT_SONY_DS4_SLIM; - if (device->has_dualshock_touchpad) { - subtype = 1; - } else { - subtype = 0; - } - } else if (is_ps5) { - vendor = USB_VENDOR_SONY; - product = USB_PRODUCT_SONY_DS5; - subtype = 0; - } else if (is_switch_pro) { - vendor = USB_VENDOR_NINTENDO; - product = USB_PRODUCT_NINTENDO_SWITCH_PRO; - subtype = 0; - } else if (is_switch_joycon_pair) { - vendor = USB_VENDOR_NINTENDO; - product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; - subtype = 0; - } else { - vendor = USB_VENDOR_APPLE; - product = 1; - subtype = 1; - } - if (is_backbone_one) { /* The Backbone app uses share button */ if ((device->button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC1)) != 0) { @@ -442,35 +476,8 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->nbuttons = nbuttons; } else if (controller.gamepad) { - BOOL is_switch_joyconL = IsControllerSwitchJoyConL(controller); - BOOL is_switch_joyconR = IsControllerSwitchJoyConR(controller); int nbuttons = 0; -#ifdef SDL_JOYSTICK_HIDAPI - if ((is_switch_joyconL && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT, 0, "")) || - (is_switch_joyconR && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT, 0, ""))) { - /* The HIDAPI driver is taking care of this device */ - return FALSE; - } -#else - (void)is_switch_joyconL; - (void)is_switch_joyconR; -#endif - - if (is_switch_joyconL) { - vendor = USB_VENDOR_NINTENDO; - product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT; - subtype = 0; - } else if (is_switch_joyconR) { - vendor = USB_VENDOR_NINTENDO; - product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT; - subtype = 0; - } else { - vendor = USB_VENDOR_APPLE; - product = 2; - subtype = 2; - } - /* These buttons are part of the original MFi spec */ device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); @@ -503,16 +510,29 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle ++nbuttons; device->uses_pause_handler = SDL_TRUE; - vendor = USB_VENDOR_APPLE; - product = 3; - subtype = 3; device->naxes = 2; /* treat the touch surface as two axes */ device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */ device->nbuttons = nbuttons; controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE); } -#endif /* TARGET_OS_TV */ +#endif +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + device->use_physical_profile = SDL_TRUE; + device->axes = [controller.physicalInputProfile.axes allKeys]; + device->naxes = controller.physicalInputProfile.axes.count; + device->dpads = [controller.physicalInputProfile.dpads allKeys]; + device->nhats = controller.physicalInputProfile.dpads.count; + device->buttons = [controller.physicalInputProfile.buttons allKeys]; + device->nbuttons = controller.physicalInputProfile.buttons.count; + subtype = 4; + } +#endif + else { + /* We can't detect any inputs on this */ + return SDL_FALSE; + } if (vendor == USB_VENDOR_APPLE) { /* Note that this is an MFI controller and what subtype it is */ @@ -957,7 +977,8 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_MFI @autoreleasepool { - GCController *controller = joystick->hwdata->controller; + SDL_JoystickDeviceItem *device = joystick->hwdata; + GCController *controller = device->controller; Uint8 hatstate = SDL_HAT_CENTERED; int i; int pause_button_index = 0; @@ -976,11 +997,39 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) if (axis.value != 0.0f) NSLog(@"Axis %@ = %g\n", key, axis.value); } + for (id key in controller.physicalInputProfile.dpads) { + GCControllerDirectionPad *dpad = controller.physicalInputProfile.dpads[key]; + if (dpad.up.isPressed || dpad.down.isPressed || dpad.left.isPressed || dpad.right.isPressed) { + NSLog(@"Hat %@ =%s%s%s%s\n", key, + dpad.up.isPressed ? " UP" : "", + dpad.down.isPressed ? " DOWN" : "", + dpad.left.isPressed ? " LEFT" : "", + dpad.right.isPressed ? " RIGHT" : ""); + } + } } } #endif - if (controller.extendedGamepad) { + if (device->use_physical_profile) { + int axis = 0; + for (id key in device->axes) { + Sint16 value = (Sint16)(controller.physicalInputProfile.axes[key].value * 32767); + SDL_SendJoystickAxis(timestamp, joystick, axis++, value); + } + + int button = 0; + for (id key in device->buttons) { + Uint8 value = controller.physicalInputProfile.buttons[key].isPressed; + SDL_SendJoystickButton(timestamp, joystick, button++, value); + } + + int hat = 0; + for (id key in device->dpads) { + hatstate = IOS_MFIJoystickHatStateForDPad(controller.physicalInputProfile.dpads[key]); + SDL_SendJoystickHat(timestamp, joystick, hat++, hatstate); + } + } else if (controller.extendedGamepad) { SDL_bool isstack; GCExtendedGamepad *gamepad = controller.extendedGamepad; @@ -1014,21 +1063,21 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) /* These buttons are available on some newer controllers */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability-new" - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) { buttons[button_count++] = gamepad.leftThumbstickButton.isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) { buttons[button_count++] = gamepad.rightThumbstickButton.isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { buttons[button_count++] = gamepad.buttonOptions.isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) { buttons[button_count++] = gamepad.buttonHome.isPressed; } /* This must be the last button, so we can optionally handle it with pause_button_index below */ - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { - if (joystick->hwdata->uses_pause_handler) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { + if (device->uses_pause_handler) { pause_button_index = button_count; buttons[button_count++] = joystick->delayed_guide_button; } else { @@ -1037,7 +1086,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if (joystick->hwdata->has_dualshock_touchpad) { + if (device->has_dualshock_touchpad) { GCControllerDirectionPad *dpad; buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed; @@ -1056,17 +1105,17 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } } - if (joystick->hwdata->has_xbox_paddles) { - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1)) { + if (device->has_xbox_paddles) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed; } - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed; } @@ -1079,7 +1128,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) */ } - if (joystick->hwdata->has_xbox_share_button) { + if (device->has_xbox_share_button) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxShareButton].isPressed; } #endif @@ -1170,8 +1219,8 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability-new" /* This must be the last button, so we can optionally handle it with pause_button_index below */ - if (joystick->hwdata->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { - if (joystick->hwdata->uses_pause_handler) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { + if (device->uses_pause_handler) { pause_button_index = button_count; buttons[button_count++] = joystick->delayed_guide_button; } else { @@ -1186,16 +1235,16 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #endif /* TARGET_OS_TV */ - if (joystick->nhats > 0) { + if (joystick->nhats > 0 && !device->use_physical_profile) { SDL_SendJoystickHat(timestamp, joystick, 0, hatstate); } - if (joystick->hwdata->uses_pause_handler) { - for (i = 0; i < joystick->hwdata->num_pause_presses; i++) { + if (device->uses_pause_handler) { + for (i = 0; i < device->num_pause_presses; i++) { SDL_SendJoystickButton(timestamp, joystick, pause_button_index, SDL_PRESSED); SDL_SendJoystickButton(timestamp, joystick, pause_button_index, SDL_RELEASED); } - joystick->hwdata->num_pause_presses = 0; + device->num_pause_presses = 0; } #ifdef ENABLE_MFI_BATTERY @@ -1732,6 +1781,10 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * return controller.microGamepad.dpad; } + if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + return controller.physicalInputProfile.dpads[GCInputDirectionPad]; + } + return nil; } #endif /* SDL_JOYSTICK_MFI && ENABLE_PHYSICAL_INPUT_PROFILE */ diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index 553a6307c8d89..06a9cd8f2b968 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -25,6 +25,8 @@ #include "../SDL_sysjoystick.h" +#include + @class GCController; typedef struct joystick_hwdata @@ -51,6 +53,11 @@ typedef struct joystick_hwdata SDL_bool has_xbox_paddles; SDL_bool has_xbox_share_button; + SDL_bool use_physical_profile; + NSArray *axes; + NSArray *dpads; + NSArray *buttons; + struct joystick_hwdata *next; } joystick_hwdata; From 15504da0b830aacdb8f8301e22ba5eb6ea9eb1b0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 14 Nov 2023 09:10:56 -0800 Subject: [PATCH 354/725] Fixed mouse wheel scrolling direction on iOS --- src/video/uikit/SDL_uikitevents.m | 40 ++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/video/uikit/SDL_uikitevents.m b/src/video/uikit/SDL_uikitevents.m index 8913c3dab2f4a..be3384833b910 100644 --- a/src/video/uikit/SDL_uikitevents.m +++ b/src/video/uikit/SDL_uikitevents.m @@ -273,6 +273,31 @@ void SDL_QuitGCKeyboard(void) static id mouse_connect_observer = nil; static id mouse_disconnect_observer = nil; static bool mouse_relative_mode = SDL_FALSE; +static SDL_MouseWheelDirection mouse_scroll_direction = SDL_MOUSEWHEEL_NORMAL; + +static void UpdateScrollDirection(void) +{ +#if 0 /* This code doesn't work for some reason */ + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + if ([userDefaults boolForKey:@"com.apple.swipescrolldirection"]) { + mouse_scroll_direction = SDL_MOUSEWHEEL_FLIPPED; + } else { + mouse_scroll_direction = SDL_MOUSEWHEEL_NORMAL; + } +#else + Boolean keyExistsAndHasValidFormat = NO; + Boolean naturalScrollDirection = CFPreferencesGetAppBooleanValue(CFSTR("com.apple.swipescrolldirection"), kCFPreferencesAnyApplication, &keyExistsAndHasValidFormat); + if (!keyExistsAndHasValidFormat) { + /* Couldn't read the preference, assume natural scrolling direction */ + naturalScrollDirection = YES; + } + if (naturalScrollDirection) { + mouse_scroll_direction = SDL_MOUSEWHEEL_FLIPPED; + } else { + mouse_scroll_direction = SDL_MOUSEWHEEL_NORMAL; + } +#endif +} static void UpdatePointerLock(void) { @@ -325,8 +350,21 @@ static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14 }; mouse.mouseInput.scroll.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { - SDL_SendMouseWheel(0, SDL_GetMouseFocus(), 0, xValue, yValue, SDL_MOUSEWHEEL_NORMAL); + /* Raw scroll values come in here, vertical values in the first axis, horizontal values in the second axis. + * The vertical values are negative moving the mouse wheel up and positive moving it down. + * The horizontal values are negative moving the mouse wheel left and positive moving it right. + * The vertical values are inverted compared to SDL, and the horizontal values are as expected. + */ + float vertical = -xValue; + float horizontal = yValue; + if (mouse_scroll_direction == SDL_MOUSEWHEEL_FLIPPED) { + /* Since these are raw values, we need to flip them ourselves */ + vertical = -vertical; + horizontal = -horizontal; + } + SDL_SendMouseWheel(0, SDL_GetMouseFocus(), mouseID, horizontal, vertical, mouse_scroll_direction); }; + UpdateScrollDirection(); dispatch_queue_t queue = dispatch_queue_create("org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL); dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); From bd4966999b9f3f148424aa97cf81aaac604626e0 Mon Sep 17 00:00:00 2001 From: Louis M Date: Mon, 13 Nov 2023 13:06:07 -0500 Subject: [PATCH 355/725] Replacing SDL_SCANCODE_AUDIOMUTE by SDL_SCANCODE_MUTE on Windows (cherry picked from commit 925362a2fcf0a7065ade5e9e55572c377d716edd) --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 7a797561af73f..ef6b3d655c3b9 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -228,7 +228,7 @@ static SDL_Scancode VKeytoScancode(WPARAM vkey) case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME; case VK_VOLUME_MUTE: - return SDL_SCANCODE_AUDIOMUTE; + return SDL_SCANCODE_MUTE; case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN; case VK_VOLUME_UP: From 708f18d49ef6975769865d247e2ce4da6ce8da76 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 14 Nov 2023 10:28:19 -0800 Subject: [PATCH 356/725] Added SDL_HINT_JOYSTICK_IOKIT and SDL_HINT_JOYSTICK_MFI to control whether the IOKit and GCController drivers should be used for joystick support. This can be used to work around issues where the Apple GCController driver doesn't work for some controllers but there's no way to know which GCController maps to which IOKit device. --- include/SDL3/SDL_hints.h | 18 ++++++++++++++++++ src/joystick/apple/SDL_mfijoystick.m | 8 ++++++++ src/joystick/darwin/SDL_iokitjoystick.c | 14 ++++++++------ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index bac7e5086682b..d2c2b0d8a73a9 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -965,6 +965,24 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" +/** + * A variable controlling whether IOKit should be used for controller handling. + * + * This variable can be set to the following values: + * "0" - IOKit is not used + * "1" - IOKit is used (the default) + */ +#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" + +/** + * A variable controlling whether GCController should be used for controller handling. + * + * This variable can be set to the following values: + * "0" - GCController is not used + * "1" - GCController is used (the default) + */ +#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI" + /** * A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. * diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index e53ddd01fa2b7..ebe5c7bcadc80 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -694,6 +694,10 @@ static void SDLCALL SDL_AppleTVRemoteRotationHintChanged(void *udata, const char static int IOS_JoystickInit(void) { + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_MFI, SDL_TRUE)) { + return 0; + } + #ifdef __MACOS__ #if SDL_HAS_BUILTIN(__builtin_available) if (@available(macOS 10.16, *)) { @@ -1741,6 +1745,10 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi #if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device) { + if (!connectObserver) { + return SDL_FALSE; + } + if (@available(macOS 10.16, *)) { const int MAX_ATTEMPTS = 3; for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) { diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 288909504779a..50cb2e107b3b1 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -655,8 +655,8 @@ static SDL_bool CreateHIDManager(void) static int DARWIN_JoystickInit(void) { - if (gpDeviceList) { - return SDL_SetError("Joystick: Device list already inited."); + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_IOKIT, SDL_TRUE)) { + return 0; } if (!CreateHIDManager()) { @@ -692,10 +692,12 @@ static void DARWIN_JoystickDetect(void) } } - /* run this after the checks above so we don't set device->removed and delete the device before - DARWIN_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device */ - while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) { - /* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */ + if (hidman) { + /* run this after the checks above so we don't set device->removed and delete the device before + DARWIN_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device */ + while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) { + /* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */ + } } } From 34392db9c38ef71b57825e8e5a7428a577e9870d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 14 Nov 2023 10:57:47 -0800 Subject: [PATCH 357/725] Fixed IOS_SupportedHIDDevice() returning SDL_FALSE before initialization --- src/joystick/apple/SDL_mfijoystick.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index ebe5c7bcadc80..624a8a0fe96dd 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1745,7 +1745,7 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi #if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device) { - if (!connectObserver) { + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_MFI, SDL_TRUE)) { return SDL_FALSE; } From a58af6d0d1773cbfbb5b32c0543343aab36185c5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 14 Nov 2023 16:18:38 -0500 Subject: [PATCH 358/725] wasapi: Reference devices when proxying to management thread. Otherwise, a disconnect/default change on another thread may cause the device pointer to become invalid by the time the management thread runs the task. --- src/audio/wasapi/SDL_wasapi_win32.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index db8397c416675..6c95e9ee655a6 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -50,26 +50,36 @@ static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x static int mgmtthrtask_AudioDeviceDisconnected(void *userdata) { - SDL_AudioDeviceDisconnected((SDL_AudioDevice *)userdata); + SDL_AudioDevice *device = (SDL_AudioDevice *) userdata; + SDL_AudioDeviceDisconnected(device); + UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes. return 0; } static void WASAPI_AudioDeviceDisconnected(SDL_AudioDevice *device) { // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. - WASAPI_ProxyToManagementThread(mgmtthrtask_AudioDeviceDisconnected, device, NULL); + if (device) { + RefPhysicalAudioDevice(device); // make sure this lives until the task completes. + WASAPI_ProxyToManagementThread(mgmtthrtask_AudioDeviceDisconnected, device, NULL); + } } static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) { - SDL_DefaultAudioDeviceChanged((SDL_AudioDevice *) userdata); + SDL_AudioDevice *device = (SDL_AudioDevice *) userdata; + SDL_DefaultAudioDeviceChanged(device); + UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes. return 0; } static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) { // don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. - WASAPI_ProxyToManagementThread(mgmtthrtask_DefaultAudioDeviceChanged, new_default_device, NULL); + if (new_default_device) { + RefPhysicalAudioDevice(new_default_device); // make sure this lives until the task completes. + WASAPI_ProxyToManagementThread(mgmtthrtask_DefaultAudioDeviceChanged, new_default_device, NULL); + } } int WASAPI_PlatformInit(void) From 078995bbe079e97251c7f75d45d797f5103c2377 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 5 Nov 2023 16:17:36 -0500 Subject: [PATCH 359/725] x11: Set the skip taskbar and skip pager atoms on utility windows Some compositors apparently still need these set to keep the window out of the taskbar and pager, even with the utility window atom being set. --- src/video/x11/SDL_x11window.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 373590ec2cf74..e17113cf25b57 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -121,6 +121,8 @@ void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags) Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ; Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN; Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE; + Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR; + Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER; Atom atoms[16]; int count = 0; @@ -136,6 +138,10 @@ void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags) if (flags & SDL_WINDOW_ALWAYS_ON_TOP) { atoms[count++] = _NET_WM_STATE_ABOVE; } + if (flags & SDL_WINDOW_UTILITY) { + atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR; + atoms[count++] = _NET_WM_STATE_SKIP_PAGER; + } if (flags & SDL_WINDOW_INPUT_FOCUS) { atoms[count++] = _NET_WM_STATE_FOCUSED; } From 8fa0746d4af9a354160f724f8d3ca1c439528e30 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 15 Nov 2023 14:10:29 -0500 Subject: [PATCH 360/725] audio: Fix postmix state when migrating to new default devices. Otherwise buffers might not be allocated, etc. --- src/audio/SDL_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 6bbd666c7604d..4f13b54a8a336 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -2065,6 +2065,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) RefPhysicalAudioDevice(new_default_device); UnrefPhysicalAudioDevice(current_default_device); + SDL_SetAudioPostmixCallback(logdev->instance_id, logdev->postmix, logdev->postmix_userdata); + SDL_PendingAudioDeviceEvent *p; // Queue an event for each logical device we moved. From e923a458eacba3e8436b133d8ce0f6d1e0c21567 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 15 Nov 2023 14:12:31 -0500 Subject: [PATCH 361/725] audio: Protect against race conditions when closing a physical device. This specifically deals with two threads closing the same device at the same time, and a thread trying to reopen the device as it's still in process of being closed. This can happen in normal usage if a device is disconnected: the OS might send a disconnect event, while the device thread also attempts to manage a disconnect as system calls start to report failure. This effort is necessary because we have to release the device lock during close to allow the device thread to unblock and cleanly shutdown. But the good news is that all the places that call ClosePhysicalAudioDevice can now safely hold the device lock on entry, and that one function will manage the lock tapdancing. --- src/audio/SDL_audio.c | 69 +++++++++++++++++++++++++++------------- src/audio/SDL_sysaudio.h | 3 ++ 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 4f13b54a8a336..168a909fa78b4 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -466,14 +466,15 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) while (device->logical_devices) { DestroyLogicalAudioDevice(device->logical_devices); } - SDL_UnlockMutex(device->lock); // don't use ReleaseAudioDevice because we don't want to change refcounts while destroying. - // it's safe to not hold the lock for this (we can't anyhow, or the audio thread won't quit), because we shouldn't be in the device list at this point. ClosePhysicalAudioDevice(device); current_audio.impl.FreeDeviceHandle(device); + SDL_UnlockMutex(device->lock); // don't use ReleaseAudioDevice because we don't want to change refcounts while destroying. + SDL_DestroyMutex(device->lock); + SDL_DestroyCondition(device->close_cond); SDL_free(device->work_buffer); SDL_free(device->name); SDL_free(device); @@ -529,6 +530,14 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc return NULL; } + device->close_cond = SDL_CreateCondition(); + if (!device->close_cond) { + SDL_DestroyMutex(device->lock); + SDL_free(device->name); + SDL_free(device); + return NULL; + } + SDL_AtomicSet(&device->shutdown, 0); SDL_AtomicSet(&device->zombie, 0); device->iscapture = iscapture; @@ -1380,10 +1389,29 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * return retval; } -// this expects the device lock to be held. !!! FIXME: no it doesn't...? +// this is awkward, but this makes sure we can release the device lock +// so the device thread can terminate but also not have two things +// race to close or open the device while the lock is unprotected. +// you hold the lock when calling this, it will release the lock and +// wait while the shutdown flag is set. +// BE CAREFUL WITH THIS. +static void SerializePhysicalDeviceClose(SDL_AudioDevice *device) +{ + while (SDL_AtomicGet(&device->shutdown)) { + SDL_WaitCondition(device->close_cond, device->lock); + } +} + +// this expects the device lock to be held. static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { + SerializePhysicalDeviceClose(device); + SDL_AtomicSet(&device->shutdown, 1); + + // YOU MUST PROTECT KEY POINTS WITH SerializePhysicalDeviceClose() WHILE THE THREAD JOINS + SDL_UnlockMutex(device->lock); + if (device->thread) { SDL_WaitThread(device->thread, NULL); device->thread = NULL; @@ -1395,6 +1423,10 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) device->hidden = NULL; // just in case. } + SDL_LockMutex(device->lock); + SDL_AtomicSet(&device->shutdown, 0); // ready to go again. + SDL_BroadcastCondition(device->close_cond); // release anyone waiting in SerializePhysicalDeviceClose; they'll still block until we release device->lock, though. + SDL_aligned_free(device->work_buffer); device->work_buffer = NULL; @@ -1407,28 +1439,24 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) SDL_copyp(&device->spec, &device->default_spec); device->sample_frames = 0; device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); - SDL_AtomicSet(&device->shutdown, 0); // ready to go again. } void SDL_CloseAudioDevice(SDL_AudioDeviceID devid) { - SDL_bool close_physical = SDL_FALSE; SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); if (logdev) { DestroyLogicalAudioDevice(logdev); - close_physical = (!device->logical_devices); // no more logical devices? Close the physical device, too. } - // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. - ReleaseAudioDevice(device); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. - if (device) { - if (close_physical) { + if (!device->logical_devices) { // no more logical devices? Close the physical device, too. ClosePhysicalAudioDevice(device); } UnrefPhysicalAudioDevice(device); // one reference for each logical device. } + + ReleaseAudioDevice(device); } @@ -1501,8 +1529,11 @@ char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen) // this expects the device lock to be held. static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec *inspec) { - SDL_assert(!device->currently_opened); - SDL_assert(!device->logical_devices); + SerializePhysicalDeviceClose(device); // make sure another thread that's closing didn't release the lock to let the device thread join... + + if (device->currently_opened) { + return 0; // we're already good. + } // Just pretend to open a zombie device. It can still collect logical devices on a default device under the assumption they will all migrate when the default device is officially changed. if (SDL_AtomicGet(&device->zombie)) { @@ -1600,7 +1631,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp SDL_SetError("Device was already lost and can't accept new opens"); } else if ((logdev = (SDL_LogicalAudioDevice *) SDL_calloc(1, sizeof (SDL_LogicalAudioDevice))) == NULL) { SDL_OutOfMemory(); - } else if (!device->currently_opened && OpenPhysicalAudioDevice(device, spec) == -1) { // first thing using this physical device? Open at the OS level... + } else if (OpenPhysicalAudioDevice(device, spec) == -1) { // if this is the first thing using this physical device, open at the OS level if necessary... SDL_free(logdev); } else { RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice @@ -2026,10 +2057,9 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) } if (needs_migration) { - if (!new_default_device->currently_opened) { // New default physical device not been opened yet? Open at the OS level... - if (OpenPhysicalAudioDevice(new_default_device, &spec) == -1) { - needs_migration = SDL_FALSE; // uhoh, just leave everything on the old default, nothing to be done. - } + // New default physical device not been opened yet? Open at the OS level... + if (OpenPhysicalAudioDevice(new_default_device, &spec) == -1) { + needs_migration = SDL_FALSE; // uhoh, just leave everything on the old default, nothing to be done. } } @@ -2086,12 +2116,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) UpdateAudioStreamFormatsPhysical(new_default_device); if (!current_default_device->logical_devices) { // nothing left on the current physical device, close it. - // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. - RefPhysicalAudioDevice(current_default_device); // hold a temp ref for a moment while we release... - ReleaseAudioDevice(current_default_device); // can't hold the lock or the audio thread will deadlock while we WaitThread it. ClosePhysicalAudioDevice(current_default_device); - ObtainPhysicalAudioDeviceObj(current_default_device); // we're about to unlock this again, so make sure the locks match. - UnrefPhysicalAudioDevice(current_default_device); // drop temp ref. } } diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 7969207692e32..649e50651c3aa 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -257,6 +257,9 @@ struct SDL_AudioDevice // A mutex for locking access to this struct SDL_Mutex *lock; + // A condition variable to protect device close, where we can't hold the device lock forever. + SDL_Condition *close_cond; + // Reference count of the device; logical devices, device threads, etc, add to this. SDL_AtomicInt refcount; From aaf54b09a12d631fec3b87c3100a8687cbf949b1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 11:30:30 -0800 Subject: [PATCH 362/725] Revert "Cleanup WIN_CreateCursor() code a bit" This reverts commit 876c97454a954a70da8b8b3d8b09b52674534062. This caused the blank cursor to be entirely black --- src/video/SDL_shape.c | 10 +-- src/video/SDL_shape_internals.h | 2 +- src/video/windows/SDL_windowsmouse.c | 94 +++++++++++++++------------- src/video/x11/SDL_x11shape.c | 2 +- 4 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index cb8d7c2f49ba1..2362ed7f7f380 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -55,15 +55,14 @@ SDL_bool SDL_IsShapedWindow(const SDL_Window *window) return (window->shaper != NULL); } -/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte and alignBytes scan line alignment. */ -void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8* bitmap, Uint8 ppb, Uint8 alignBytes) +/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */ +void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb) { int x = 0; int y = 0; Uint8 r = 0, g = 0, b = 0, alpha = 0; Uint32 mask_value = 0; - int bytes_per_scanline; - + size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb; Uint8 *bitmap_scanline; SDL_Color key; @@ -71,9 +70,6 @@ void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint SDL_LockSurface(shape); } - bytes_per_scanline = (shape->w + (ppb - 1)) / ppb; - bytes_per_scanline = (bytes_per_scanline + (alignBytes - 1)) & ~(alignBytes - 1); - SDL_memset(bitmap, 0, shape->h * bytes_per_scanline); for (y = 0; y < shape->h; y++) { diff --git a/src/video/SDL_shape_internals.h b/src/video/SDL_shape_internals.h index 85e164c5b6d7a..fa8e90adbf890 100644 --- a/src/video/SDL_shape_internals.h +++ b/src/video/SDL_shape_internals.h @@ -51,7 +51,7 @@ typedef struct SDL_ShapeTree typedef void (*SDL_TraversalFunction)(SDL_ShapeTree *, void *); -extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb, Uint8 alignBytes); +extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb); extern SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape); extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure); extern void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index b9d77af31f077..44491d37abcbb 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -26,8 +26,6 @@ #include "../../events/SDL_mouse_c.h" -#include "../SDL_shape_internals.h" - DWORD SDL_last_warp_time = 0; HCURSOR SDL_cursor = NULL; static SDL_Cursor *SDL_blank_cursor = NULL; @@ -88,71 +86,81 @@ static SDL_Cursor *WIN_CreateDefaultCursor() static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) { - HICON hicon; + /* msdn says cursor mask has to be padded out to word alignment. Not sure + if that means machine word or WORD, but this handles either case. */ + const size_t pad = (sizeof(size_t) * 8); /* 32 or 64, or whatever. */ SDL_Cursor *cursor; - BITMAPV5HEADER bmh; + HICON hicon; + HICON hcursor; + HDC hdc; + BITMAPV4HEADER bmh; + LPVOID pixels; + LPVOID maskbits; + size_t maskbitslen; + SDL_bool isstack; ICONINFO ii; - HBITMAP colorBitmap = NULL, maskBitmap = NULL; - LPVOID colorBits, maskBits; - int maskPitch; SDL_zero(bmh); - bmh.bV5Size = sizeof(bmh); - bmh.bV5Width = surface->w; - bmh.bV5Height = -surface->h; /* Invert the image to make it top-down. */ - bmh.bV5Planes = 1; - bmh.bV5BitCount = surface->format->BitsPerPixel; - bmh.bV5Compression = BI_BITFIELDS; - bmh.bV5RedMask = surface->format->Rmask; - bmh.bV5GreenMask = surface->format->Gmask; - bmh.bV5BlueMask = surface->format->Bmask; - bmh.bV5AlphaMask = surface->format->Amask; - - colorBitmap = CreateDIBSection(NULL, (BITMAPINFO *) &bmh, DIB_RGB_COLORS, &colorBits, NULL, 0); - - if (!colorBitmap || !colorBits) { - WIN_SetError("CreateDIBSection()"); + bmh.bV4Size = sizeof(bmh); + bmh.bV4Width = surface->w; + bmh.bV4Height = -surface->h; /* Invert the image */ + bmh.bV4Planes = 1; + bmh.bV4BitCount = 32; + bmh.bV4V4Compression = BI_BITFIELDS; + bmh.bV4AlphaMask = 0xFF000000; + bmh.bV4RedMask = 0x00FF0000; + bmh.bV4GreenMask = 0x0000FF00; + bmh.bV4BlueMask = 0x000000FF; + + maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h; + maskbits = SDL_small_alloc(Uint8, maskbitslen, &isstack); + if (!maskbits) { + SDL_OutOfMemory(); return NULL; } - SDL_memcpy(colorBits, surface->pixels, surface->pitch * surface->h); - - /* Scan lines in 1 bpp mask should be aligned to WORD boundary. */ - maskPitch = (((surface->w + 15) & ~15) / 8); - if ((maskBits = SDL_stack_alloc(Uint8, maskPitch * surface->h))) { - SDL_WindowShapeMode mode = { ShapeModeDefault }; - SDL_CalculateShapeBitmap(mode, surface, maskBits, 8, sizeof(WORD)); - maskBitmap = CreateBitmap(surface->w, surface->h, 1, 1, maskBits); - SDL_stack_free(maskBits); - } + /* AND the cursor against full bits: no change. We already have alpha. */ + SDL_memset(maskbits, 0xFF, maskbitslen); + hdc = GetDC(NULL); SDL_zero(ii); ii.fIcon = FALSE; ii.xHotspot = (DWORD)hot_x; ii.yHotspot = (DWORD)hot_y; - ii.hbmColor = colorBitmap; - ii.hbmMask = maskBitmap; + ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0); + ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits); + ReleaseDC(NULL, hdc); + SDL_small_free(maskbits, isstack); - hicon = CreateIconIndirect(&ii); + SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); + SDL_assert(surface->pitch == surface->w * 4); + SDL_memcpy(pixels, surface->pixels, (size_t)surface->h * surface->pitch); - if (colorBitmap) { - DeleteObject(colorBitmap); - } + hicon = CreateIconIndirect(&ii); - if (maskBitmap) { - DeleteObject(maskBitmap); - } + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); if (!hicon) { WIN_SetError("CreateIconIndirect()"); return NULL; } + /* The cursor returned by CreateIconIndirect does not respect system cursor size + preference, use CopyImage to duplicate the cursor with desired sizes */ + hcursor = CopyImage(hicon, IMAGE_CURSOR, surface->w, surface->h, 0); + DestroyIcon(hicon); + + if (!hcursor) { + WIN_SetError("CopyImage()"); + return NULL; + } + cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { - cursor->driverdata = hicon; + cursor->driverdata = hcursor; } else { - DestroyIcon(hicon); + DestroyIcon(hcursor); SDL_OutOfMemory(); } diff --git a/src/video/x11/SDL_x11shape.c b/src/video/x11/SDL_x11shape.c index f1fd20e145a2e..373d6eba1ae4b 100644 --- a/src/video/x11/SDL_x11shape.c +++ b/src/video/x11/SDL_x11shape.c @@ -81,7 +81,7 @@ int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowS data = shaper->driverdata; /* Assume that shaper->alphacutoff already has a value, because SDL_SetWindowShape() should have given it one. */ - SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8, 1); + SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8); windowdata = shaper->window->driverdata; shapemask = X11_XCreateBitmapFromData(windowdata->videodata->display, windowdata->xwindow, data->bitmap, shaper->window->w, shaper->window->h); From 0fe5713964287b17e05eb09dd4f83d8580dba254 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 14 Nov 2023 12:58:33 -0800 Subject: [PATCH 363/725] Improved GCController handling on Apple platforms Automatically map controllers as gamepads when using the GCController framework and prefer the physicalInputProfile when possible. Testing with macOS 13.4.1, macOS 14.1.1, iOS 15.7.4, tvOS 17.1: * iBuffalo Classic USB Gamepad (macOS only) * Logitech F310 (macOS only) * Apple TV remote (tvOS only) * Nimbus MFi controller * PS4 DualShock controller * PS5 DualSense controller * Xbox Series X controller * Xbox Elite Series 2 controller * Nintendo Switch Pro controller * Nintendo Switch Joy-Con controllers --- src/joystick/SDL_gamepad.c | 9 +- src/joystick/SDL_joystick.c | 21 + src/joystick/SDL_joystick_c.h | 18 +- src/joystick/apple/SDL_mfijoystick.m | 545 ++++++++++++++++++------- src/joystick/apple/SDL_mfijoystick_c.h | 10 +- 5 files changed, 446 insertions(+), 157 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index a365254b3b957..689816abd3701 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -935,7 +935,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForGUID(SDL_JoystickGUID gu /* Try harder to get the best match, or create a mapping */ - if (vendor && product) { + if (SDL_JoystickGUIDUsesVersion(guid)) { /* Try again, ignoring the version */ if (crc) { mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_TRUE, SDL_FALSE); @@ -1720,7 +1720,11 @@ static void SDL_PrivateAppendToMappingString(char *mapping_string, (void)SDL_snprintf(buffer, sizeof(buffer), "b%i", mapping->target); break; case EMappingKind_Axis: - (void)SDL_snprintf(buffer, sizeof(buffer), "a%i", mapping->target); + (void)SDL_snprintf(buffer, sizeof(buffer), "%sa%i%s", + mapping->half_axis_positive ? "+" : + mapping->half_axis_negative ? "-" : "", + mapping->target, + mapping->axis_reversed ? "~" : ""); break; case EMappingKind_Hat: (void)SDL_snprintf(buffer, sizeof(buffer), "h%i.%i", mapping->target >> 4, mapping->target & 0x0F); @@ -1780,6 +1784,7 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "righty", &raw_map->righty); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "lefttrigger", &raw_map->lefttrigger); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "righttrigger", &raw_map->righttrigger); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "touchpad", &raw_map->touchpad); return SDL_PrivateAddMappingForGUID(guid, mapping, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT); } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 664f05e7e9b88..f26c3db20ea55 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2436,6 +2436,22 @@ SDL_GamepadType SDL_GetGamepadTypeFromGUID(SDL_JoystickGUID guid, const char *na return type; } +SDL_bool SDL_JoystickGUIDUsesVersion(SDL_JoystickGUID guid) +{ + Uint16 vendor, product; + + if (SDL_IsJoystickMFI(guid)) { + /* The version bits are used as button capability mask */ + return SDL_FALSE; + } + + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); + if (vendor && product) { + return SDL_TRUE; + } + return SDL_FALSE; +} + SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); @@ -2656,6 +2672,11 @@ SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE; } +SDL_bool SDL_IsJoystickMFI(SDL_JoystickGUID guid) +{ + return (guid.data[14] == 'm') ? SDL_TRUE : SDL_FALSE; +} + SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid) { return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE; diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 8b37204d5a8e6..68424775b490f 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -80,6 +80,9 @@ extern void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc); extern SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI); extern SDL_GamepadType SDL_GetGamepadTypeFromGUID(SDL_JoystickGUID guid, const char *name); +/* Function to return whether a joystick GUID uses the version field */ +extern SDL_bool SDL_JoystickGUIDUsesVersion(SDL_JoystickGUID guid); + /* Function to return whether a joystick is an Xbox One controller */ extern SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id); @@ -132,6 +135,9 @@ extern SDL_bool SDL_IsJoystickWGI(SDL_JoystickGUID guid); /* Function to return whether a joystick guid comes from the HIDAPI driver */ extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid); +/* Function to return whether a joystick guid comes from the MFI driver */ +extern SDL_bool SDL_IsJoystickMFI(SDL_JoystickGUID guid); + /* Function to return whether a joystick guid comes from the RAWINPUT driver */ extern SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid); @@ -166,16 +172,19 @@ extern SDL_bool SDL_IsJoystickValid(SDL_Joystick *joystick); typedef enum { - EMappingKind_None = 0, - EMappingKind_Button = 1, - EMappingKind_Axis = 2, - EMappingKind_Hat = 3 + EMappingKind_None, + EMappingKind_Button, + EMappingKind_Axis, + EMappingKind_Hat, } EMappingKind; typedef struct SDL_InputMapping { EMappingKind kind; Uint8 target; + SDL_bool axis_reversed; + SDL_bool half_axis_positive; + SDL_bool half_axis_negative; } SDL_InputMapping; typedef struct SDL_GamepadMapping @@ -206,6 +215,7 @@ typedef struct SDL_GamepadMapping SDL_InputMapping righty; SDL_InputMapping lefttrigger; SDL_InputMapping righttrigger; + SDL_InputMapping touchpad; } SDL_GamepadMapping; /* Function to get autodetected gamepad controller mapping from the driver */ diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 624a8a0fe96dd..b3929f192903e 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -231,6 +231,78 @@ static BOOL IsControllerBackboneOne(GCController *controller) } return FALSE; } +static BOOL IsControllerSiriRemote(GCController *controller) +{ + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + if ([controller.productCategory hasPrefix:@"Siri Remote"]) { + return TRUE; + } + } + return FALSE; +} + +static BOOL ElementAlreadyHandled(NSString *element, NSDictionary *elements) +{ + if ([element isEqualToString:@"Left Thumbstick Left"] || + [element isEqualToString:@"Left Thumbstick Right"]) { + if (elements[@"Left Thumbstick X Axis"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Left Thumbstick Up"] || + [element isEqualToString:@"Left Thumbstick Down"]) { + if (elements[@"Left Thumbstick Y Axis"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Right Thumbstick Left"] || + [element isEqualToString:@"Right Thumbstick Right"]) { + if (elements[@"Right Thumbstick X Axis"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Right Thumbstick Up"] || + [element isEqualToString:@"Right Thumbstick Down"]) { + if (elements[@"Right Thumbstick Y Axis"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Direction Pad X Axis"]) { + if (elements[@"Direction Pad Left"] && + elements[@"Direction Pad Right"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Direction Pad Y Axis"]) { + if (elements[@"Direction Pad Up"] && + elements[@"Direction Pad Down"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Touchpad 1 X Axis"] || + [element isEqualToString:@"Touchpad 1 Y Axis"] || + [element isEqualToString:@"Touchpad 1 Left"] || + [element isEqualToString:@"Touchpad 1 Right"] || + [element isEqualToString:@"Touchpad 1 Up"] || + [element isEqualToString:@"Touchpad 1 Down"] || + [element isEqualToString:@"Touchpad 2 X Axis"] || + [element isEqualToString:@"Touchpad 2 Y Axis"] || + [element isEqualToString:@"Touchpad 2 Left"] || + [element isEqualToString:@"Touchpad 2 Right"] || + [element isEqualToString:@"Touchpad 2 Up"] || + [element isEqualToString:@"Touchpad 2 Down"]) { + /* The touchpad is handled separately */ + return TRUE; + } +#if TARGET_OS_TV + if ([element isEqualToString:GCInputButtonHome]) { + /* The OS uses the home button, it's not available to apps */ + return TRUE; + } +#endif + return FALSE; +} + static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller) { Uint16 vendor = 0; @@ -259,13 +331,20 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->name = SDL_CreateJoystickName(0, 0, NULL, name); #ifdef DEBUG_CONTROLLER_PROFILE + NSLog(@"Product name: %@\n", controller.vendorName); + NSLog(@"Product category: %@\n", controller.productCategory); + NSLog(@"Elements available:\n"); if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { if (controller.physicalInputProfile) { + NSDictionary *elements = controller.physicalInputProfile.elements; for (id key in controller.physicalInputProfile.buttons) { - NSLog(@"Button %@ available\n", key); + NSLog(@"\tButton: %@ (%s)\n", key, elements[key].analog ? "analog" : "digital"); } for (id key in controller.physicalInputProfile.axes) { - NSLog(@"Axis %@ available\n", key); + NSLog(@"\tAxis: %@\n", key); + } + for (id key in controller.physicalInputProfile.dpads) { + NSLog(@"\tHat: %@\n", key); } } } @@ -297,6 +376,21 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle (void)is_switch_joyconL; (void)is_switch_joyconR; #endif + device->is_siri_remote = IsControllerSiriRemote(controller); + +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) { + device->has_dualshock_touchpad = SDL_TRUE; + } + if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { + device->has_xbox_paddles = SDL_TRUE; + } + if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { + device->has_xbox_share_button = SDL_TRUE; + } + } +#endif // ENABLE_PHYSICAL_INPUT_PROFILE if (is_backbone_one) { vendor = USB_VENDOR_BACKBONE; @@ -305,21 +399,17 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } else { product = USB_PRODUCT_BACKBONE_ONE_IOS; } - subtype = 0; } else if (is_xbox) { vendor = USB_VENDOR_MICROSOFT; if (device->has_xbox_paddles) { /* Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID */ product = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH; - subtype = 1; } else if (device->has_xbox_share_button) { /* Assume Xbox Series X Controller unless/until GCController flows VID/PID */ product = USB_PRODUCT_XBOX_SERIES_X_BLE; - subtype = 1; } else { /* Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID */ product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; - subtype = 0; } } else if (is_ps4) { /* Assume DS4 Slim unless/until GCController flows VID/PID */ @@ -327,29 +417,32 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle product = USB_PRODUCT_SONY_DS4_SLIM; if (device->has_dualshock_touchpad) { subtype = 1; - } else { - subtype = 0; } } else if (is_ps5) { vendor = USB_VENDOR_SONY; product = USB_PRODUCT_SONY_DS5; - subtype = 0; } else if (is_switch_pro) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_PRO; - subtype = 0; + device->has_nintendo_buttons = SDL_TRUE; } else if (is_switch_joycon_pair) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; - subtype = 0; + device->has_nintendo_buttons = SDL_TRUE; } else if (is_switch_joyconL) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT; - subtype = 0; + device->is_single_joycon = SDL_TRUE; } else if (is_switch_joyconR) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT; - subtype = 0; + device->is_single_joycon = SDL_TRUE; +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + } else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + vendor = USB_VENDOR_APPLE; + product = 4; + subtype = 4; +#endif } else if (controller.extendedGamepad) { vendor = USB_VENDOR_APPLE; product = 1; @@ -363,12 +456,6 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle vendor = USB_VENDOR_APPLE; product = 3; subtype = 3; -#endif -#ifdef ENABLE_PHYSICAL_INPUT_PROFILE - } else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { - vendor = USB_VENDOR_APPLE; - product = 4; - subtype = 4; #endif } else { vendor = USB_VENDOR_APPLE; @@ -376,6 +463,61 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle subtype = 5; } +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + NSDictionary *elements = controller.physicalInputProfile.elements; + + /* Provide both axes and analog buttons as SDL axes */ + device->use_physical_profile = SDL_TRUE; + device->axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { + if (ElementAlreadyHandled((NSString *)object, elements)) { + return NO; + } + + GCControllerElement *element = elements[object]; + if (element.analog) { + if ([element isKindOfClass:[GCControllerAxisInput class]] || + [element isKindOfClass:[GCControllerButtonInput class]]) { + return YES; + } + } + return NO; + }]]; + device->naxes = device->axes.count; + device->buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { + if (ElementAlreadyHandled((NSString *)object, elements)) { + return NO; + } + + GCControllerElement *element = elements[object]; + if ([element isKindOfClass:[GCControllerButtonInput class]]) { + return YES; + } + return NO; + }]]; + device->nbuttons = device->buttons.count; + subtype = 4; + +#ifdef DEBUG_CONTROLLER_PROFILE + NSLog(@"Elements used:\n", controller.vendorName); + for (id key in device->buttons) { + NSLog(@"\tButton: %@ (%s)\n", key, elements[key].analog ? "analog" : "digital"); + } + for (id key in device->axes) { + NSLog(@"\tAxis: %@\n", key); + } +#endif /* DEBUG_CONTROLLER_PROFILE */ + +#if TARGET_OS_TV + /* tvOS turns the menu button into a system gesture, so we grab it here instead */ + if (elements[GCInputButtonMenu] && !elements[GCInputButtonHome]) { + device->pause_button_index = [device->buttons indexOfObject:GCInputButtonMenu]; + } +#endif + } else +#endif if (controller.extendedGamepad) { GCExtendedGamepad *gamepad = controller.extendedGamepad; int nbuttons = 0; @@ -415,12 +557,12 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu; if (!has_direct_menu) { - device->uses_pause_handler = SDL_TRUE; + device->pause_button_index = (nbuttons - 1); } #if TARGET_OS_TV /* The single menu button isn't very reliable, at least as of tvOS 16.1 */ if ((device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) == 0) { - device->uses_pause_handler = SDL_TRUE; + device->pause_button_index = (nbuttons - 1); } #endif @@ -437,15 +579,13 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle ++nbuttons; } if (controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo] != nil) { - /* TODO: Is this right? SDL_gamepad.h says P2 is the lower right */ device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2); ++nbuttons; } if (controller.physicalInputProfile.buttons[GCInputXboxPaddleThree] != nil) { - /* TODO: Is this right? SDL_gamepad.h says P3 is the upper left */ device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1); ++nbuttons; } if (controller.physicalInputProfile.buttons[GCInputXboxPaddleFour] != nil) { @@ -485,14 +625,9 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_NORTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); -#if TARGET_OS_TV - /* The menu button is used by the OS and not available to applications */ - nbuttons += 6; -#else device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_START); nbuttons += 7; - device->uses_pause_handler = SDL_TRUE; -#endif + device->pause_button_index = (nbuttons - 1); device->naxes = 0; /* no traditional analog inputs */ device->nhats = 1; /* d-pad */ @@ -504,11 +639,9 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); /* Button X on microGamepad */ - nbuttons += 2; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_START); - ++nbuttons; - device->uses_pause_handler = SDL_TRUE; + nbuttons += 3; + device->pause_button_index = (nbuttons - 1); device->naxes = 2; /* treat the touch surface as two axes */ device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */ @@ -516,35 +649,32 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE); } -#endif -#ifdef ENABLE_PHYSICAL_INPUT_PROFILE - else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { - device->use_physical_profile = SDL_TRUE; - device->axes = [controller.physicalInputProfile.axes allKeys]; - device->naxes = controller.physicalInputProfile.axes.count; - device->dpads = [controller.physicalInputProfile.dpads allKeys]; - device->nhats = controller.physicalInputProfile.dpads.count; - device->buttons = [controller.physicalInputProfile.buttons allKeys]; - device->nbuttons = controller.physicalInputProfile.buttons.count; - subtype = 4; - } #endif else { /* We can't detect any inputs on this */ return SDL_FALSE; } + Uint16 signature; + if (device->use_physical_profile) { + signature = 0; + signature = SDL_crc16(signature, device->name, SDL_strlen(device->name)); + for (id key in device->axes) { + const char *string = ((NSString *)key).UTF8String; + signature = SDL_crc16(signature, string, SDL_strlen(string)); + } + for (id key in device->buttons) { + const char *string = ((NSString *)key).UTF8String; + signature = SDL_crc16(signature, string, SDL_strlen(string)); + } + } else { + signature = device->button_mask; + } if (vendor == USB_VENDOR_APPLE) { /* Note that this is an MFI controller and what subtype it is */ - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, 0, name, 'm', subtype); + device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); } else { - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, 0, name, 0, subtype); - } - - /* Update the GUID with capability bits */ - { - Uint16 *guid16 = (Uint16 *)device->guid.data; - guid16[6] = SDL_SwapLE16(device->button_mask); + device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 0, subtype); } /* This will be set when the first button press of the controller is @@ -582,6 +712,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet device->accelerometer = accelerometer; device->instance_id = SDL_GetNextObjectID(); + device->pause_button_index = -1; if (accelerometer) { #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER @@ -864,11 +995,11 @@ static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index) #endif } else { #ifdef SDL_JOYSTICK_MFI - if (device->uses_pause_handler) { + if (device->pause_button_index >= 0) { GCController *controller = device->controller; controller.controllerPausedHandler = ^(GCController *c) { if (joystick->hwdata) { - ++joystick->hwdata->num_pause_presses; + joystick->hwdata->pause_button_pressed = SDL_GetTicks(); } }; } @@ -901,7 +1032,7 @@ static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index) #endif /* SDL_JOYSTICK_MFI */ } } - if (device->remote) { + if (device->is_siri_remote) { ++SDL_AppleTVRemoteOpenedAsJoystick; } @@ -985,9 +1116,9 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) GCController *controller = device->controller; Uint8 hatstate = SDL_HAT_CENTERED; int i; - int pause_button_index = 0; Uint64 timestamp = SDL_GetTicksNS(); +#define DEBUG_CONTROLLER_STATE #ifdef DEBUG_CONTROLLER_STATE if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { if (controller.physicalInputProfile) { @@ -1016,23 +1147,31 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) #endif if (device->use_physical_profile) { + NSDictionary *elements = controller.physicalInputProfile.elements; + NSDictionary *buttons = controller.physicalInputProfile.buttons; + int axis = 0; for (id key in device->axes) { - Sint16 value = (Sint16)(controller.physicalInputProfile.axes[key].value * 32767); + Sint16 value; + GCControllerElement *element = elements[key]; + if ([element isKindOfClass:[GCControllerAxisInput class]]) { + value = (Sint16)([(GCControllerAxisInput *)element value] * 32767); + } else { + value = (Sint16)([(GCControllerButtonInput *)element value] * 32767); + } SDL_SendJoystickAxis(timestamp, joystick, axis++, value); } int button = 0; for (id key in device->buttons) { - Uint8 value = controller.physicalInputProfile.buttons[key].isPressed; + Uint8 value; + if (button == device->pause_button_index) { + value = (device->pause_button_pressed > 0); + } else { + value = buttons[key].isPressed; + } SDL_SendJoystickButton(timestamp, joystick, button++, value); } - - int hat = 0; - for (id key in device->dpads) { - hatstate = IOS_MFIJoystickHatStateForDPad(controller.physicalInputProfile.dpads[key]); - SDL_SendJoystickHat(timestamp, joystick, hat++, hatstate); - } } else if (controller.extendedGamepad) { SDL_bool isstack; GCExtendedGamepad *gamepad = controller.extendedGamepad; @@ -1079,11 +1218,9 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) { buttons[button_count++] = gamepad.buttonHome.isPressed; } - /* This must be the last button, so we can optionally handle it with pause_button_index below */ if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { - if (device->uses_pause_handler) { - pause_button_index = button_count; - buttons[button_count++] = joystick->delayed_guide_button; + if (device->pause_button_index >= 0) { + buttons[button_count++] = (device->pause_button_pressed > 0); } else { buttons[button_count++] = gamepad.buttonMenu.isPressed; } @@ -1091,45 +1228,22 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) #ifdef ENABLE_PHYSICAL_INPUT_PROFILE if (device->has_dualshock_touchpad) { - GCControllerDirectionPad *dpad; buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed; - - dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne]; - if (dpad.xAxis.value || dpad.yAxis.value) { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); - } else { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_RELEASED, 0.0f, 0.0f, 1.0f); - } - - dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadTwo]; - if (dpad.xAxis.value || dpad.yAxis.value) { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); - } else { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_RELEASED, 0.0f, 0.0f, 1.0f); - } } if (device->has_xbox_paddles) { if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed; } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed; } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed; } if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2)) { buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed; } - - /* - SDL_Log("Paddles: [%d,%d,%d,%d]", - controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed, - controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed, - controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed, - controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed); - */ } if (device->has_xbox_share_button) { @@ -1148,30 +1262,6 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) SDL_SendJoystickButton(timestamp, joystick, i, buttons[i]); } -#ifdef ENABLE_MFI_SENSORS - if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { - GCMotion *motion = controller.motion; - if (motion && motion.sensorsActive) { - float data[3]; - - if (motion.hasRotationRate) { - GCRotationRate rate = motion.rotationRate; - data[0] = rate.x; - data[1] = rate.z; - data[2] = -rate.y; - SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp, data, 3); - } - if (motion.hasGravityAndUserAcceleration) { - GCAcceleration accel = motion.acceleration; - data[0] = -accel.x * SDL_STANDARD_GRAVITY; - data[1] = -accel.y * SDL_STANDARD_GRAVITY; - data[2] = -accel.z * SDL_STANDARD_GRAVITY; - SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, data, 3); - } - } - } -#endif /* ENABLE_MFI_SENSORS */ - SDL_small_free(buttons, isstack); } else if (controller.gamepad) { SDL_bool isstack; @@ -1192,8 +1282,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) buttons[button_count++] = gamepad.buttonY.isPressed; buttons[button_count++] = gamepad.leftShoulder.isPressed; buttons[button_count++] = gamepad.rightShoulder.isPressed; - pause_button_index = button_count; - buttons[button_count++] = joystick->delayed_guide_button; + buttons[button_count++] = (device->pause_button_pressed > 0); hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad); @@ -1220,18 +1309,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) int button_count = 0; buttons[button_count++] = gamepad.buttonA.isPressed; buttons[button_count++] = gamepad.buttonX.isPressed; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* This must be the last button, so we can optionally handle it with pause_button_index below */ - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { - if (device->uses_pause_handler) { - pause_button_index = button_count; - buttons[button_count++] = joystick->delayed_guide_button; - } else { - buttons[button_count++] = gamepad.buttonMenu.isPressed; - } - } -#pragma clang diagnostic pop + buttons[button_count++] = (device->pause_button_pressed > 0); for (i = 0; i < button_count; i++) { SDL_SendJoystickButton(timestamp, joystick, i, buttons[i]); @@ -1239,17 +1317,61 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #endif /* TARGET_OS_TV */ - if (joystick->nhats > 0 && !device->use_physical_profile) { + if (joystick->nhats > 0) { SDL_SendJoystickHat(timestamp, joystick, 0, hatstate); } - if (device->uses_pause_handler) { - for (i = 0; i < device->num_pause_presses; i++) { - SDL_SendJoystickButton(timestamp, joystick, pause_button_index, SDL_PRESSED); - SDL_SendJoystickButton(timestamp, joystick, pause_button_index, SDL_RELEASED); + if (device->pause_button_pressed) { + /* The pause callback is instantaneous, so we extend the duration to allow "holding down" by pressing it repeatedly */ + const int PAUSE_BUTTON_PRESS_DURATION_MS = 250; + if (SDL_GetTicks() >= device->pause_button_pressed + PAUSE_BUTTON_PRESS_DURATION_MS) { + device->pause_button_pressed = 0; + } + } + +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + if (device->has_dualshock_touchpad) { + GCControllerDirectionPad *dpad; + + dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne]; + if (dpad.xAxis.value || dpad.yAxis.value) { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); + } else { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_RELEASED, 0.0f, 0.0f, 1.0f); + } + + dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadTwo]; + if (dpad.xAxis.value || dpad.yAxis.value) { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); + } else { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_RELEASED, 0.0f, 0.0f, 1.0f); } - device->num_pause_presses = 0; } +#endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ + +#ifdef ENABLE_MFI_SENSORS + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + GCMotion *motion = controller.motion; + if (motion && motion.sensorsActive) { + float data[3]; + + if (motion.hasRotationRate) { + GCRotationRate rate = motion.rotationRate; + data[0] = rate.x; + data[1] = rate.z; + data[2] = -rate.y; + SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp, data, 3); + } + if (motion.hasGravityAndUserAcceleration) { + GCAcceleration accel = motion.acceleration; + data[0] = -accel.x * SDL_STANDARD_GRAVITY; + data[1] = -accel.y * SDL_STANDARD_GRAVITY; + data[2] = -accel.z * SDL_STANDARD_GRAVITY; + SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, data, 3); + } + } + } +#endif /* ENABLE_MFI_SENSORS */ #ifdef ENABLE_MFI_BATTERY if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { @@ -1698,7 +1820,7 @@ static void IOS_JoystickClose(SDL_Joystick *joystick) #endif /* SDL_JOYSTICK_MFI */ } } - if (device->remote) { + if (device->is_siri_remote) { --SDL_AppleTVRemoteOpenedAsJoystick; } } @@ -1739,7 +1861,138 @@ static void IOS_JoystickQuit(void) static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) { - return SDL_FALSE; + SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); + if (device == NULL) { + return SDL_FALSE; + } + + if (!device->use_physical_profile) { + return SDL_FALSE; + } + + int axis = 0; + for (id key in device->axes) { + if ([(NSString *)key isEqualToString:@"Left Thumbstick X Axis"]) { + out->leftx.kind = EMappingKind_Axis; + out->leftx.target = axis; + } else if ([(NSString *)key isEqualToString:@"Left Thumbstick Y Axis"]) { + out->lefty.kind = EMappingKind_Axis; + out->lefty.target = axis; + out->lefty.axis_reversed = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Right Thumbstick X Axis"]) { + out->rightx.kind = EMappingKind_Axis; + out->rightx.target = axis; + } else if ([(NSString *)key isEqualToString:@"Right Thumbstick Y Axis"]) { + out->righty.kind = EMappingKind_Axis; + out->righty.target = axis; + out->righty.axis_reversed = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { + out->lefttrigger.kind = EMappingKind_Axis; + out->lefttrigger.target = axis; + out->lefttrigger.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { + out->righttrigger.kind = EMappingKind_Axis; + out->righttrigger.target = axis; + out->righttrigger.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"] && device->is_siri_remote) { + out->dpleft.kind = EMappingKind_Axis; + out->dpleft.target = axis; + out->dpleft.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"] && device->is_siri_remote) { + out->dpright.kind = EMappingKind_Axis; + out->dpright.target = axis; + out->dpright.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"] && device->is_siri_remote) { + out->dpup.kind = EMappingKind_Axis; + out->dpup.target = axis; + out->dpup.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"] && device->is_siri_remote) { + out->dpdown.kind = EMappingKind_Axis; + out->dpdown.target = axis; + out->dpdown.half_axis_positive = SDL_TRUE; + } + ++axis; + } + + int button = 0; + for (id key in device->buttons) { + SDL_InputMapping *mapping = NULL; + + if ([(NSString *)key isEqualToString:GCInputButtonA]) { + if (device->has_nintendo_buttons) { + mapping = &out->b; + } else { + mapping = &out->a; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonB]) { + if (device->has_nintendo_buttons) { + mapping = &out->a; + } else if (device->is_single_joycon) { + mapping = &out->x; + } else { + mapping = &out->b; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonX]) { + if (device->has_nintendo_buttons) { + mapping = &out->y; + } else if (device->is_single_joycon) { + mapping = &out->b; + } else { + mapping = &out->x; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonY]) { + if (device->has_nintendo_buttons) { + mapping = &out->x; + } else { + mapping = &out->y; + } + } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"] && !device->is_siri_remote) { + mapping = &out->dpleft; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"] && !device->is_siri_remote) { + mapping = &out->dpright; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"] && !device->is_siri_remote) { + mapping = &out->dpup; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"] && !device->is_siri_remote) { + mapping = &out->dpdown; + } else if ([(NSString *)key isEqualToString:GCInputLeftShoulder]) { + mapping = &out->leftshoulder; + } else if ([(NSString *)key isEqualToString:GCInputRightShoulder]) { + mapping = &out->rightshoulder; + } else if ([(NSString *)key isEqualToString:GCInputLeftThumbstickButton]) { + mapping = &out->leftstick; + } else if ([(NSString *)key isEqualToString:GCInputRightThumbstickButton]) { + mapping = &out->rightstick; + } else if ([(NSString *)key isEqualToString:GCInputButtonHome]) { + mapping = &out->guide; + } else if ([(NSString *)key isEqualToString:GCInputButtonMenu]) { + mapping = &out->start; + } else if ([(NSString *)key isEqualToString:GCInputButtonOptions]) { + mapping = &out->back; + } else if ([(NSString *)key isEqualToString:GCInputButtonShare]) { + mapping = &out->misc1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleOne]) { + mapping = &out->right_paddle1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleTwo]) { + mapping = &out->right_paddle2; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleThree]) { + mapping = &out->left_paddle1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleFour]) { + mapping = &out->left_paddle2; + } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { + mapping = &out->lefttrigger; + } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { + mapping = &out->righttrigger; + } else if ([(NSString *)key isEqualToString:GCInputDualShockTouchpadButton]) { + mapping = &out->touchpad; + } + if (mapping && mapping->kind == EMappingKind_None) { + mapping->kind = EMappingKind_Button; + mapping->target = button; + } + ++button; + } + + return SDL_TRUE; } #if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) @@ -1777,6 +2030,10 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * static GCControllerDirectionPad *GetDirectionalPadForController(GCController *controller) { + if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + return controller.physicalInputProfile.dpads[GCInputDirectionPad]; + } + if (controller.extendedGamepad) { return controller.extendedGamepad.dpad; } @@ -1789,10 +2046,6 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * return controller.microGamepad.dpad; } - if ([controller respondsToSelector:@selector(physicalInputProfile)]) { - return controller.physicalInputProfile.dpads[GCInputDirectionPad]; - } - return nil; } #endif /* SDL_JOYSTICK_MFI && ENABLE_PHYSICAL_INPUT_PROFILE */ diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index 06a9cd8f2b968..fa289fc84f87a 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -32,13 +32,11 @@ typedef struct joystick_hwdata { SDL_bool accelerometer; - SDL_bool remote; GCController __unsafe_unretained *controller; void *rumble; - SDL_bool uses_pause_handler; - int num_pause_presses; - Uint32 pause_button_down_time; + int pause_button_index; + Uint64 pause_button_pressed; char *name; SDL_Joystick *joystick; @@ -52,10 +50,12 @@ typedef struct joystick_hwdata SDL_bool has_dualshock_touchpad; SDL_bool has_xbox_paddles; SDL_bool has_xbox_share_button; + SDL_bool has_nintendo_buttons; + SDL_bool is_single_joycon; + SDL_bool is_siri_remote; SDL_bool use_physical_profile; NSArray *axes; - NSArray *dpads; NSArray *buttons; struct joystick_hwdata *next; From 64939d3586db1bb1e55bf48b18d5ad2081590780 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 17:30:27 -0800 Subject: [PATCH 364/725] Switch the menu button on the Apple TV remote to the B button to match UI guidelines --- src/joystick/apple/SDL_mfijoystick.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index b3929f192903e..d8d21892d1d9c 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -638,8 +638,8 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle int nbuttons = 0; device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); /* Button X on microGamepad */ - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_START); + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_WEST); /* Button X on microGamepad */ + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_EAST); nbuttons += 3; device->pause_button_index = (nbuttons - 1); @@ -1965,7 +1965,11 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi } else if ([(NSString *)key isEqualToString:GCInputButtonHome]) { mapping = &out->guide; } else if ([(NSString *)key isEqualToString:GCInputButtonMenu]) { - mapping = &out->start; + if (device->is_siri_remote) { + mapping = &out->b; + } else { + mapping = &out->start; + } } else if ([(NSString *)key isEqualToString:GCInputButtonOptions]) { mapping = &out->back; } else if ([(NSString *)key isEqualToString:GCInputButtonShare]) { From 2ff9255f299b0d54032235719516f07014013b21 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 20:54:38 -0800 Subject: [PATCH 365/725] Print the GUID for controllers that don't have a mapping --- test/testcontroller.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index a8b8bfa38d88e..91f334f3caf1d 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -849,9 +849,12 @@ static void AddController(SDL_JoystickID id, SDL_bool verbose) joystick = new_controller->joystick; if (joystick) { if (verbose && !SDL_IsGamepad(id)) { - const char *name = SDL_GetJoystickName(new_controller->joystick); - const char *path = SDL_GetJoystickPath(new_controller->joystick); + const char *name = SDL_GetJoystickName(joystick); + const char *path = SDL_GetJoystickPath(joystick); + char guid[33]; SDL_Log("Opened joystick %s%s%s\n", name, path ? ", " : "", path ? path : ""); + SDL_GetJoystickGUIDString(SDL_GetJoystickGUID(joystick), guid, sizeof(guid)); + SDL_Log("No gamepad mapping for %s\n", guid); } } else { SDL_Log("Couldn't open joystick: %s", SDL_GetError()); From 2999634f2998845253c93a060d4d9823cae10978 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 20:55:32 -0800 Subject: [PATCH 366/725] Map Siri Remote touchpad to D-Pad for consistency with physicalInputProfile mapping --- src/joystick/SDL_gamepad_db.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 4253e498f3914..dc65a5574c334 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -853,7 +853,8 @@ static const char *s_GamepadMappings[] = { "050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", "050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,", "050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", - "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", + "05000000ac0500000300000007006d03,Remote,a:b0,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b1,", + "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b1,", "050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", From fb08c22abfb62cfefdf097c1bd835735f96f819e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 21:46:45 -0800 Subject: [PATCH 367/725] Disable controller state debug messages --- src/joystick/apple/SDL_mfijoystick.m | 1 - 1 file changed, 1 deletion(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index d8d21892d1d9c..290c96952f61d 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1118,7 +1118,6 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) int i; Uint64 timestamp = SDL_GetTicksNS(); -#define DEBUG_CONTROLLER_STATE #ifdef DEBUG_CONTROLLER_STATE if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { if (controller.physicalInputProfile) { From 051ed397d10c4cf4c360d84f664ca6376b7802c8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 21:51:22 -0800 Subject: [PATCH 368/725] Removed testautomation_syswm.c from the Xcode project --- Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj b/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj index 2642bca14ce84..f188f537210fb 100644 --- a/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj +++ b/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 55; objects = { /* Begin PBXAggregateTarget section */ @@ -153,7 +153,6 @@ F35E56DF2983130F00A43A5F /* testautomation_keyboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56C72983130E00A43A5F /* testautomation_keyboard.c */; }; F35E56E02983130F00A43A5F /* testautomation_sdltest.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56C82983130E00A43A5F /* testautomation_sdltest.c */; }; F35E56E12983130F00A43A5F /* testautomation_guid.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56C92983130E00A43A5F /* testautomation_guid.c */; }; - F35E56E22983130F00A43A5F /* testautomation_syswm.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CA2983130E00A43A5F /* testautomation_syswm.c */; }; F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CB2983130F00A43A5F /* testautomation_surface.c */; }; F35E56E42983130F00A43A5F /* testautomation.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CC2983130F00A43A5F /* testautomation.c */; }; F35E56E52983130F00A43A5F /* testautomation_mouse.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CD2983130F00A43A5F /* testautomation_mouse.c */; }; @@ -1329,7 +1328,6 @@ F35E56C72983130E00A43A5F /* testautomation_keyboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_keyboard.c; sourceTree = ""; }; F35E56C82983130E00A43A5F /* testautomation_sdltest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_sdltest.c; sourceTree = ""; }; F35E56C92983130E00A43A5F /* testautomation_guid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_guid.c; sourceTree = ""; }; - F35E56CA2983130E00A43A5F /* testautomation_syswm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_syswm.c; sourceTree = ""; }; F35E56CB2983130F00A43A5F /* testautomation_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_surface.c; sourceTree = ""; }; F35E56CC2983130F00A43A5F /* testautomation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation.c; sourceTree = ""; }; F35E56CD2983130F00A43A5F /* testautomation_mouse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_mouse.c; sourceTree = ""; }; @@ -1780,7 +1778,6 @@ F35E56C82983130E00A43A5F /* testautomation_sdltest.c */, F35E56BE2983130C00A43A5F /* testautomation_stdlib.c */, F35E56CB2983130F00A43A5F /* testautomation_surface.c */, - F35E56CA2983130E00A43A5F /* testautomation_syswm.c */, F35E56BD2983130B00A43A5F /* testautomation_timer.c */, F35E56C12983130C00A43A5F /* testautomation_video.c */, F35E56CC2983130F00A43A5F /* testautomation.c */, @@ -3357,7 +3354,6 @@ buildActionMask = 2147483647; files = ( F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */, - F35E56E22983130F00A43A5F /* testautomation_syswm.c in Sources */, F399C6512A7892D800C86979 /* testautomation_intrinsics.c in Sources */, F35E56D22983130F00A43A5F /* testautomation_rwops.c in Sources */, F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */, From 57e5c7f6ee525c16ebe6c95b365235c79f09cc59 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 22:09:09 -0800 Subject: [PATCH 369/725] We'll just use the legacy names for face buttons in the mappings This fixes being able to accidentally rebind the face buttons in testcontroller --- src/joystick/SDL_gamepad.c | 57 +++++++++++++------------------------- test/gamepadutils.c | 24 ---------------- 2 files changed, 19 insertions(+), 62 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 689816abd3701..d190aac80bda7 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1066,10 +1066,10 @@ const char *SDL_GetGamepadStringForAxis(SDL_GamepadAxis axis) } static const char *map_StringForGamepadButton[] = { - "s", - "e", - "w", - "n", + "a", + "b", + "x", + "y", "back", "guide", "start", @@ -1103,43 +1103,24 @@ SDL_GamepadButton SDL_PrivateGetGamepadButtonFromString(const char *str, SDL_boo for (i = 0; i < SDL_arraysize(map_StringForGamepadButton); ++i) { if (SDL_strcasecmp(str, map_StringForGamepadButton[i]) == 0) { + if (baxy) { + /* Need to swap face buttons */ + switch (i) { + case SDL_GAMEPAD_BUTTON_SOUTH: + return SDL_GAMEPAD_BUTTON_EAST; + case SDL_GAMEPAD_BUTTON_EAST: + return SDL_GAMEPAD_BUTTON_SOUTH; + case SDL_GAMEPAD_BUTTON_WEST: + return SDL_GAMEPAD_BUTTON_NORTH; + case SDL_GAMEPAD_BUTTON_NORTH: + return SDL_GAMEPAD_BUTTON_WEST; + default: + break; + } + } return (SDL_GamepadButton)i; } } - - if (SDL_strcasecmp(str, "a") == 0) { - if (baxy) { - return SDL_GAMEPAD_BUTTON_EAST; - } else { - return SDL_GAMEPAD_BUTTON_SOUTH; - } - } else if (SDL_strcasecmp(str, "b") == 0) { - if (baxy) { - return SDL_GAMEPAD_BUTTON_SOUTH; - } else { - return SDL_GAMEPAD_BUTTON_EAST; - } - } else if (SDL_strcasecmp(str, "x") == 0) { - if (baxy) { - return SDL_GAMEPAD_BUTTON_NORTH; - } else { - return SDL_GAMEPAD_BUTTON_WEST; - } - } else if (SDL_strcasecmp(str, "y") == 0) { - if (baxy) { - return SDL_GAMEPAD_BUTTON_WEST; - } else { - return SDL_GAMEPAD_BUTTON_NORTH; - } - } else if (SDL_strcasecmp(str, "cross") == 0) { - return SDL_GAMEPAD_BUTTON_SOUTH; - } else if (SDL_strcasecmp(str, "circle") == 0) { - return SDL_GAMEPAD_BUTTON_EAST; - } else if (SDL_strcasecmp(str, "square") == 0) { - return SDL_GAMEPAD_BUTTON_WEST; - } else if (SDL_strcasecmp(str, "triangle") == 0) { - return SDL_GAMEPAD_BUTTON_NORTH; - } return SDL_GAMEPAD_BUTTON_INVALID; } SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str) diff --git a/test/gamepadutils.c b/test/gamepadutils.c index a404591a16e94..01641ea3c6deb 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -2292,33 +2292,9 @@ static void ConvertBAXYMapping(MappingParts *parts) } } -static void UseLegacyButtonNames(MappingParts *parts) -{ - int i; - - for (i = 0; i < parts->num_elements; ++i) { - char *key = parts->keys[i]; - - if (SDL_strcmp(key, "s") == 0) { - parts->keys[i] = SDL_strdup("a"); - SDL_free(key); - } else if (SDL_strcmp(key, "e") == 0) { - parts->keys[i] = SDL_strdup("b"); - SDL_free(key); - } else if (SDL_strcmp(key, "w") == 0) { - parts->keys[i] = SDL_strdup("x"); - SDL_free(key); - } else if (SDL_strcmp(key, "n") == 0) { - parts->keys[i] = SDL_strdup("y"); - SDL_free(key); - } - } -} - static void UpdateLegacyElements(MappingParts *parts) { ConvertBAXYMapping(parts); - UseLegacyButtonNames(parts); } static SDL_bool CombineMappingAxes(MappingParts *parts) From 34bdd321bf78bc56875542a976171ea236e2b9d6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 23:46:31 -0800 Subject: [PATCH 370/725] Improved navigation while setting up controller mapping * Moving forward and backward don't clear the current binding * Use the tertiary face button to delete the current binding * More small improvements to make navigation more intuitive --- test/testcontroller.c | 76 +++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index 91f334f3caf1d..ea8f3e5adede4 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -86,6 +86,7 @@ static SDL_JoystickID mapping_controller = 0; static int binding_element = SDL_GAMEPAD_ELEMENT_INVALID; static int last_binding_element = SDL_GAMEPAD_ELEMENT_INVALID; static SDL_bool binding_flow = SDL_FALSE; +static int binding_flow_direction = 0; static Uint64 binding_advance_time = 0; static SDL_FRect title_area; static SDL_bool title_highlighted; @@ -331,6 +332,7 @@ static void SetCurrentBindingElement(int element, SDL_bool flow) } if (element == SDL_GAMEPAD_ELEMENT_INVALID) { + binding_flow_direction = 0; last_binding_element = SDL_GAMEPAD_ELEMENT_INVALID; } else { last_binding_element = binding_element; @@ -356,6 +358,7 @@ static void SetNextBindingElement(void) for (i = 0; i < SDL_arraysize(s_arrBindingOrder); ++i) { if (binding_element == s_arrBindingOrder[i]) { + binding_flow_direction = 1; SetCurrentBindingElement(s_arrBindingOrder[i + 1], SDL_TRUE); return; } @@ -373,6 +376,7 @@ static void SetPrevBindingElement(void) for (i = 1; i < SDL_arraysize(s_arrBindingOrder); ++i) { if (binding_element == s_arrBindingOrder[i]) { + binding_flow_direction = -1; SetCurrentBindingElement(s_arrBindingOrder[i - 1], SDL_TRUE); return; } @@ -500,32 +504,48 @@ static void CommitBindingElement(const char *binding, SDL_bool force) if (existing != SDL_GAMEPAD_ELEMENT_INVALID) { SDL_GamepadButton action_forward = SDL_GAMEPAD_BUTTON_SOUTH; SDL_GamepadButton action_backward = SDL_GAMEPAD_BUTTON_EAST; - if (existing == action_forward) { - if (binding_element == action_forward) { - /* Just move on to the next one */ + SDL_GamepadButton action_delete = SDL_GAMEPAD_BUTTON_WEST; + if (binding_element == action_forward) { + /* Bind it! */ + } else if (binding_element == action_backward) { + if (existing == action_forward) { + SDL_bool bound_backward = MappingHasElement(controller->mapping, action_backward); + if (bound_backward) { + /* Just move on to the next one */ + ignore_binding = SDL_TRUE; + SetNextBindingElement(); + } else { + /* You can't skip the backward action, go back and start over */ + ignore_binding = SDL_TRUE; + SetPrevBindingElement(); + } + } else if (existing == action_backward && binding_flow_direction == -1) { + /* Keep going backwards */ ignore_binding = SDL_TRUE; - SetNextBindingElement(); + SetPrevBindingElement(); } else { - /* Clear the current binding and move to the next one */ - binding = NULL; - direction = 1; - force = SDL_TRUE; + /* Bind it! */ } + } else if (existing == action_forward) { + /* Just move on to the next one */ + ignore_binding = SDL_TRUE; + SetNextBindingElement(); } else if (existing == action_backward) { - if (binding_element != action_forward && - last_binding_element != action_forward) { - /* Clear the current binding and move to the previous one */ - binding = NULL; - direction = -1; - force = SDL_TRUE; - } + ignore_binding = SDL_TRUE; + SetPrevBindingElement(); } else if (existing == binding_element) { /* We're rebinding the same thing, just move to the next one */ ignore_binding = SDL_TRUE; SetNextBindingElement(); + } else if (existing == action_delete) { + /* Clear the current binding and move to the next one */ + binding = NULL; + direction = 1; + force = SDL_TRUE; } else if (binding_element != action_forward && binding_element != action_backward) { - ignore_binding = SDL_TRUE; + /* Actually, we'll just clear the existing binding */ + /*ignore_binding = SDL_TRUE;*/ } } } @@ -1347,6 +1367,12 @@ static void DrawBindingTips(SDL_Renderer *renderer) } else { Uint8 r, g, b, a; SDL_FRect rect; + SDL_GamepadButton action_forward = SDL_GAMEPAD_BUTTON_SOUTH; + SDL_bool bound_forward = MappingHasElement(controller->mapping, action_forward); + SDL_GamepadButton action_backward = SDL_GAMEPAD_BUTTON_EAST; + SDL_bool bound_backward = MappingHasElement(controller->mapping, action_backward); + SDL_GamepadButton action_delete = SDL_GAMEPAD_BUTTON_WEST; + SDL_bool bound_delete = MappingHasElement(controller->mapping, action_delete); y -= (FONT_CHARACTER_SIZE + BUTTON_MARGIN) / 2; @@ -1365,20 +1391,22 @@ static void DrawBindingTips(SDL_Renderer *renderer) if (binding_element == SDL_GAMEPAD_ELEMENT_NAME) { text = "(press RETURN to complete)"; - } else if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) { + } else if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE || + binding_element == action_forward || + binding_element == action_backward) { text = "(press ESC to cancel)"; } else { + static char dynamic_text[128]; SDL_GamepadType type = GetGamepadImageType(image); - SDL_GamepadButton action_forward = SDL_GAMEPAD_BUTTON_SOUTH; - SDL_bool bound_forward = MappingHasElement(controller->mapping, action_forward); - SDL_GamepadButton action_backward = SDL_GAMEPAD_BUTTON_EAST; - SDL_bool bound_backward = MappingHasElement(controller->mapping, action_backward); if (binding_flow && bound_forward && bound_backward) { - static char dynamic_text[128]; - SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward)); + if (binding_element != action_delete && bound_delete) { + SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, %s to delete, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward), GetButtonLabel(type, action_delete)); + } else { + SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, SPACE to delete, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward), GetButtonLabel(type, action_delete)); + } text = dynamic_text; } else { - text = "(press SPACE to clear binding and ESC to cancel)"; + text = "(press SPACE to delete and ESC to cancel)"; } } SDLTest_DrawString(renderer, (float)x - (FONT_CHARACTER_SIZE * SDL_strlen(text)) / 2, (float)y, text); From f40f272107ff9e8cfe96f3a531944e7cc411cee6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 15 Nov 2023 23:58:39 -0800 Subject: [PATCH 371/725] Fixed build --- test/testcontroller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index ea8f3e5adede4..3dbafb59603ad 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1402,7 +1402,7 @@ static void DrawBindingTips(SDL_Renderer *renderer) if (binding_element != action_delete && bound_delete) { SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, %s to delete, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward), GetButtonLabel(type, action_delete)); } else { - SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, SPACE to delete, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward), GetButtonLabel(type, action_delete)); + SDL_snprintf(dynamic_text, sizeof(dynamic_text), "(press %s to skip, %s to go back, SPACE to delete, and ESC to cancel)", GetButtonLabel(type, action_forward), GetButtonLabel(type, action_backward)); } text = dynamic_text; } else { From d4448fe3d2cfaec73a2c7b0e9394fa87be4f1ab6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 00:02:47 -0800 Subject: [PATCH 372/725] Update virtual joystick test now that we're just using abxy for mappings, for compatibility --- test/testautomation_joystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testautomation_joystick.c b/test/testautomation_joystick.c index d3cc0793fe8ec..4f191047e1d51 100644 --- a/test/testautomation_joystick.c +++ b/test/testautomation_joystick.c @@ -97,7 +97,7 @@ static int TestVirtualJoystick(void *arg) SDLTest_AssertCheck(SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED, "SDL_GetGamepadButton(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_RELEASED"); /* Set an explicit mapping with PS4 style buttons */ - SDL_SetGamepadMapping(SDL_GetJoystickInstanceID(joystick), "ff0013db5669727475616c2043007601,Virtual PS4 Gamepad,type:ps4,cross:b0,circle:b1,square:b2,triangle:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,"); + SDL_SetGamepadMapping(SDL_GetJoystickInstanceID(joystick), "ff0013db5669727475616c2043007601,Virtual PS4 Gamepad,type:ps4,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetGamepadName(gamepad), "Virtual PS4 Gamepad") == 0, "SDL_GetGamepadName() == Virtual PS4 Gamepad"); SDLTest_AssertCheck(SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_CROSS, "SDL_GetGamepadButtonLabel(SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_CROSS"); From f2c12fe5f335efaea716beeba8f74095966a75be Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 16 Nov 2023 08:46:57 -0500 Subject: [PATCH 373/725] Removed TODO.txt This is obviously not how we track bugs at this point. :) --- TODO.txt | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 TODO.txt diff --git a/TODO.txt b/TODO.txt deleted file mode 100644 index 20b205f06ef0a..0000000000000 --- a/TODO.txt +++ /dev/null @@ -1,10 +0,0 @@ -Future work roadmap: - * http://wiki.libsdl.org/Roadmap - - * Check 1.2 revisions: - 3554 - Need to resolve semantics for locking keys on different platforms - 4874 - Do we want screen rotation? At what level? - 4974 - Windows file code needs to convert UTF-8 to Unicode, but we don't need to tap dance for Windows 95/98 - 4865 - See if this is still needed (mouse coordinate clamping) - 4866 - See if this is still needed (blocking window repositioning) - From bfba9de43a57f525a5abf523f1559c19f702ac10 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 09:02:54 -0800 Subject: [PATCH 374/725] Revert "Map Siri Remote touchpad to D-Pad for consistency with physicalInputProfile mapping" This reverts commit 2999634f2998845253c93a060d4d9823cae10978. The physicalInputProfile mapping maps the touchpad to left thumbstick now, as the 2nd generation Siri Remote has both touchpad and cardinal direction D-Pad functionality --- src/joystick/SDL_gamepad_db.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index dc65a5574c334..4253e498f3914 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -853,8 +853,7 @@ static const char *s_GamepadMappings[] = { "050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", "050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,", "050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", - "05000000ac0500000300000007006d03,Remote,a:b0,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b1,", - "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b1,", + "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", "050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", From 51fc134cadbc24bcb71dbaf1712cb108f0e30e02 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 09:07:04 -0800 Subject: [PATCH 375/725] Added support for the second generation Siri Remote on Apple TV --- src/joystick/apple/SDL_mfijoystick.m | 105 ++++++++++++++++--------- src/joystick/apple/SDL_mfijoystick_c.h | 2 +- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 290c96952f61d..591da67e290f5 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -231,17 +231,19 @@ static BOOL IsControllerBackboneOne(GCController *controller) } return FALSE; } -static BOOL IsControllerSiriRemote(GCController *controller) +static void CheckControllerSiriRemote(GCController *controller, int *is_siri_remote) { if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { if ([controller.productCategory hasPrefix:@"Siri Remote"]) { - return TRUE; + *is_siri_remote = 1; + SDL_sscanf(controller.productCategory.UTF8String, "Siri Remote (%i%*s Generation)", is_siri_remote); + return; } } - return FALSE; + *is_siri_remote = 0; } -static BOOL ElementAlreadyHandled(NSString *element, NSDictionary *elements) +static BOOL ElementAlreadyHandled(SDL_JoystickDeviceItem *device, NSString *element, NSDictionary *elements) { if ([element isEqualToString:@"Left Thumbstick Left"] || [element isEqualToString:@"Left Thumbstick Right"]) { @@ -267,15 +269,42 @@ static BOOL ElementAlreadyHandled(NSString *element, NSDictionaryis_siri_remote) { + if ([element isEqualToString:@"Direction Pad Left"] || + [element isEqualToString:@"Direction Pad Right"]) { + if (elements[@"Direction Pad X Axis"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Direction Pad Up"] || + [element isEqualToString:@"Direction Pad Down"]) { + if (elements[@"Direction Pad Y Axis"]) { + return TRUE; + } + } + } else { + if ([element isEqualToString:@"Direction Pad X Axis"]) { + if (elements[@"Direction Pad Left"] && + elements[@"Direction Pad Right"]) { + return TRUE; + } + } + if ([element isEqualToString:@"Direction Pad Y Axis"]) { + if (elements[@"Direction Pad Up"] && + elements[@"Direction Pad Down"]) { + return TRUE; + } + } + } + if ([element isEqualToString:@"Cardinal Direction Pad X Axis"]) { + if (elements[@"Cardinal Direction Pad Left"] && + elements[@"Cardinal Direction Pad Right"]) { return TRUE; } } - if ([element isEqualToString:@"Direction Pad Y Axis"]) { - if (elements[@"Direction Pad Up"] && - elements[@"Direction Pad Down"]) { + if ([element isEqualToString:@"Cardinal Direction Pad Y Axis"]) { + if (elements[@"Cardinal Direction Pad Up"] && + elements[@"Cardinal Direction Pad Down"]) { return TRUE; } } @@ -376,7 +405,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle (void)is_switch_joyconL; (void)is_switch_joyconR; #endif - device->is_siri_remote = IsControllerSiriRemote(controller); + CheckControllerSiriRemote(controller, &device->is_siri_remote); #ifdef ENABLE_PHYSICAL_INPUT_PROFILE if ([controller respondsToSelector:@selector(physicalInputProfile)]) { @@ -471,7 +500,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->use_physical_profile = SDL_TRUE; device->axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { - if (ElementAlreadyHandled((NSString *)object, elements)) { + if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; } @@ -484,10 +513,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->naxes = device->axes.count; + device->naxes = (int)device->axes.count; device->buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { - if (ElementAlreadyHandled((NSString *)object, elements)) { + if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; } @@ -497,7 +526,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->nbuttons = device->buttons.count; + device->nbuttons = (int)device->buttons.count; subtype = 4; #ifdef DEBUG_CONTROLLER_PROFILE @@ -1143,7 +1172,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } } } -#endif +#endif /* DEBUG_CONTROLLER_STATE */ if (device->use_physical_profile) { NSDictionary *elements = controller.physicalInputProfile.elements; @@ -1871,10 +1900,12 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi int axis = 0; for (id key in device->axes) { - if ([(NSString *)key isEqualToString:@"Left Thumbstick X Axis"]) { + if ([(NSString *)key isEqualToString:@"Left Thumbstick X Axis"] || + [(NSString *)key isEqualToString:@"Direction Pad X Axis"]) { out->leftx.kind = EMappingKind_Axis; out->leftx.target = axis; - } else if ([(NSString *)key isEqualToString:@"Left Thumbstick Y Axis"]) { + } else if ([(NSString *)key isEqualToString:@"Left Thumbstick Y Axis"] || + [(NSString *)key isEqualToString:@"Direction Pad Y Axis"]) { out->lefty.kind = EMappingKind_Axis; out->lefty.target = axis; out->lefty.axis_reversed = SDL_TRUE; @@ -1893,22 +1924,6 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi out->righttrigger.kind = EMappingKind_Axis; out->righttrigger.target = axis; out->righttrigger.half_axis_positive = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"] && device->is_siri_remote) { - out->dpleft.kind = EMappingKind_Axis; - out->dpleft.target = axis; - out->dpleft.half_axis_positive = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"] && device->is_siri_remote) { - out->dpright.kind = EMappingKind_Axis; - out->dpright.target = axis; - out->dpright.half_axis_positive = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"] && device->is_siri_remote) { - out->dpup.kind = EMappingKind_Axis; - out->dpup.target = axis; - out->dpup.half_axis_positive = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"] && device->is_siri_remote) { - out->dpdown.kind = EMappingKind_Axis; - out->dpdown.target = axis; - out->dpdown.half_axis_positive = SDL_TRUE; } ++axis; } @@ -1918,7 +1933,9 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi SDL_InputMapping *mapping = NULL; if ([(NSString *)key isEqualToString:GCInputButtonA]) { - if (device->has_nintendo_buttons) { + if (device->is_siri_remote > 1) { + /* GCInputButtonA is triggered for any D-Pad press, ignore it in favor of "Button Center" */ + } else if (device->has_nintendo_buttons) { mapping = &out->b; } else { mapping = &out->a; @@ -1945,13 +1962,21 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi } else { mapping = &out->y; } - } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"] && !device->is_siri_remote) { + } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"]) { + mapping = &out->dpleft; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"]) { + mapping = &out->dpright; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"]) { + mapping = &out->dpup; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"]) { + mapping = &out->dpdown; + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Left"]) { mapping = &out->dpleft; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"] && !device->is_siri_remote) { + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Right"]) { mapping = &out->dpright; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"] && !device->is_siri_remote) { + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Up"]) { mapping = &out->dpup; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"] && !device->is_siri_remote) { + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Down"]) { mapping = &out->dpdown; } else if ([(NSString *)key isEqualToString:GCInputLeftShoulder]) { mapping = &out->leftshoulder; @@ -1987,6 +2012,8 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi mapping = &out->righttrigger; } else if ([(NSString *)key isEqualToString:GCInputDualShockTouchpadButton]) { mapping = &out->touchpad; + } else if ([(NSString *)key isEqualToString:@"Button Center"]) { + mapping = &out->a; } if (mapping && mapping->kind == EMappingKind_None) { mapping->kind = EMappingKind_Button; diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index fa289fc84f87a..d1d984fd18952 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -52,7 +52,7 @@ typedef struct joystick_hwdata SDL_bool has_xbox_share_button; SDL_bool has_nintendo_buttons; SDL_bool is_single_joycon; - SDL_bool is_siri_remote; + int is_siri_remote; SDL_bool use_physical_profile; NSArray *axes; From f61c0f3dc1a8c63c83129a1c3176e00bdbecff87 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 09:19:27 -0800 Subject: [PATCH 376/725] SDL_HINT_TV_REMOTE_AS_JOYSTICK should only affect Siri Remotes on Apple TV Other gamepads like the iBuffalo Classic USB Gamepad will not have a standard profile, but shouldn't be ignored when this hint is enabled. --- src/joystick/apple/SDL_mfijoystick.m | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 591da67e290f5..1bdc9e17872a6 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -407,6 +407,11 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle #endif CheckControllerSiriRemote(controller, &device->is_siri_remote); + if (device->is_siri_remote && !SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + /* Ignore remotes, they'll be handled as keyboard input */ + return SDL_FALSE; + } + #ifdef ENABLE_PHYSICAL_INPUT_PROFILE if ([controller respondsToSelector:@selector(physicalInputProfile)]) { if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) { @@ -718,15 +723,6 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet { SDL_JoystickDeviceItem *device = deviceList; -#if TARGET_OS_TV - if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { - /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */ - if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) { - return; - } - } -#endif - while (device != NULL) { if (device->controller == controller) { return; From e0d0d140b224151ae363c9aaaa7c1cdc264c9a4e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 09:55:06 -0800 Subject: [PATCH 377/725] Fixed SDL_GetWindowWMInfo() code example --- docs/README-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index a93074cd67c65..f34119252a8a0 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1175,7 +1175,7 @@ The information previously available in SDL_GetWindowWMInfo() is now available a ```c HWND hwnd = NULL; SDL_SysWMinfo info; - SDL_VERSION(&info); + SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { hwnd = info.info.win.window; } From 5c8c3931f26c5de3c010c5e0aeb6303c6df8e444 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 09:56:16 -0800 Subject: [PATCH 378/725] Removed outdated information about SDL_GetWindowWMInfo() --- docs/README-migration.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index f34119252a8a0..0601988fcfce2 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1191,11 +1191,6 @@ becomes: } ``` -### SDL_GetWindowWMInfo - -This function now returns a standard int result instead of SDL_bool, returning 0 if the function succeeds or a negative error code if there was an error. You should also pass SDL_SYSWM_CURRENT_VERSION as the new third version parameter. The version member of the info structure will be filled in with the version of data that is returned, the minimum of the version you requested and the version supported by the runtime SDL library. - - ## SDL_thread.h The following functions have been renamed: From 8043dad369bd5c75607620c6466ac4eaad86d9e6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 10:28:41 -0800 Subject: [PATCH 379/725] Fixed build warning --- src/audio/coreaudio/SDL_coreaudio.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 807ad8a675f74..0690de3e20686 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -231,7 +231,7 @@ static OSStatus DeviceListChangedNotification(AudioObjectID systemObj, UInt32 nu static OSStatus DefaultAudioDeviceChangedNotification(AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr) { AudioDeviceID devid; - Uint32 size = sizeof(devid); + UInt32 size = sizeof(devid); if (AudioObjectGetPropertyData(inObjectID, addr, 0, NULL, &size, &devid) == noErr) { SDL_DefaultAudioDeviceChanged(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)devid))); } From ac1f896f89b5bea7a92e2a724c1c9ddbe1435299 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 10:49:13 -0800 Subject: [PATCH 380/725] Fixed building with older macOS SDK --- src/joystick/apple/SDL_mfijoystick.m | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 1bdc9e17872a6..29039d79a1c9e 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -50,7 +50,6 @@ static id connectObserver = nil; static id disconnectObserver = nil; -static NSString *GCInputXboxShareButton = @"Button Share"; #include #include @@ -420,7 +419,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { device->has_xbox_paddles = SDL_TRUE; } - if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { + if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { device->has_xbox_share_button = SDL_TRUE; } } @@ -627,7 +626,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2); ++nbuttons; } - if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { + if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { device->has_xbox_share_button = SDL_TRUE; device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_MISC1); ++nbuttons; @@ -1271,7 +1270,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } if (device->has_xbox_share_button) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxShareButton].isPressed; + buttons[button_count++] = controller.physicalInputProfile.buttons[@"Button Share"].isPressed; } #endif #pragma clang diagnostic pop @@ -1885,6 +1884,7 @@ static void IOS_JoystickQuit(void) static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) { +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); if (device == NULL) { return SDL_FALSE; @@ -2019,6 +2019,9 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi } return SDL_TRUE; +#else + return SDL_FALSE; +#endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ } #if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) From 7abacc9f9f17aa2980336fb467be2be42bfce5c2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 11:44:59 -0800 Subject: [PATCH 381/725] Fixed build --- src/joystick/apple/SDL_mfijoystick.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 29039d79a1c9e..92299ad76a154 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -50,6 +50,7 @@ static id connectObserver = nil; static id disconnectObserver = nil; +static NSString *GCInputXboxShareButton = @"Button Share"; #include #include @@ -419,7 +420,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { device->has_xbox_paddles = SDL_TRUE; } - if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { + if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { device->has_xbox_share_button = SDL_TRUE; } } @@ -626,7 +627,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2); ++nbuttons; } - if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { + if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { device->has_xbox_share_button = SDL_TRUE; device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_MISC1); ++nbuttons; @@ -1270,7 +1271,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } if (device->has_xbox_share_button) { - buttons[button_count++] = controller.physicalInputProfile.buttons[@"Button Share"].isPressed; + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxShareButton].isPressed; } #endif #pragma clang diagnostic pop From 4ebb0c6dacb50668881fcb946a08794f4f4f1276 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 12:03:39 -0800 Subject: [PATCH 382/725] Revert "Fixed build" This reverts commit 7abacc9f9f17aa2980336fb467be2be42bfce5c2. --- src/joystick/apple/SDL_mfijoystick.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 92299ad76a154..29039d79a1c9e 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -50,7 +50,6 @@ static id connectObserver = nil; static id disconnectObserver = nil; -static NSString *GCInputXboxShareButton = @"Button Share"; #include #include @@ -420,7 +419,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { device->has_xbox_paddles = SDL_TRUE; } - if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { + if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { device->has_xbox_share_button = SDL_TRUE; } } @@ -627,7 +626,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2); ++nbuttons; } - if (controller.physicalInputProfile.buttons[GCInputXboxShareButton] != nil) { + if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { device->has_xbox_share_button = SDL_TRUE; device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_MISC1); ++nbuttons; @@ -1271,7 +1270,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } if (device->has_xbox_share_button) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxShareButton].isPressed; + buttons[button_count++] = controller.physicalInputProfile.buttons[@"Button Share"].isPressed; } #endif #pragma clang diagnostic pop From e424dcca4b210249939dea453a7915473d2c5825 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 12:04:45 -0800 Subject: [PATCH 383/725] More fixing the build with older macOS SDKs --- src/joystick/apple/SDL_mfijoystick.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 29039d79a1c9e..f4c94eb79b1ac 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1992,7 +1992,7 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi } } else if ([(NSString *)key isEqualToString:GCInputButtonOptions]) { mapping = &out->back; - } else if ([(NSString *)key isEqualToString:GCInputButtonShare]) { + } else if ([(NSString *)key isEqualToString:@"Button Share"]) { mapping = &out->misc1; } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleOne]) { mapping = &out->right_paddle1; From 238987df3bcb349899ccbe117500dd3a1d4eaafe Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 16:08:53 -0800 Subject: [PATCH 384/725] Always use physicalInputProfile on OS versions that support it Also cleaned up @available warnings in the GCController support --- src/joystick/apple/SDL_mfijoystick.m | 546 +++++++++++-------------- src/joystick/apple/SDL_mfijoystick_c.h | 20 +- 2 files changed, 253 insertions(+), 313 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index f4c94eb79b1ac..b39943f3a289f 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -322,12 +322,22 @@ static BOOL ElementAlreadyHandled(SDL_JoystickDeviceItem *device, NSString *elem /* The touchpad is handled separately */ return TRUE; } + if ([element isEqualToString:@"Button Home"]) { + if (device->is_switch_joycon_pair) { + /* The Nintendo Switch JoyCon home button doesn't ever show as being held down */ + return TRUE; + } #if TARGET_OS_TV - if ([element isEqualToString:GCInputButtonHome]) { /* The OS uses the home button, it's not available to apps */ return TRUE; - } #endif + } + if ([element isEqualToString:@"Button Share"]) { + if (device->is_backbone_one) { + /* The Backbone app uses share button */ + return TRUE; + } + } return FALSE; } @@ -363,46 +373,40 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle NSLog(@"Product category: %@\n", controller.productCategory); NSLog(@"Elements available:\n"); if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { - if (controller.physicalInputProfile) { - NSDictionary *elements = controller.physicalInputProfile.elements; - for (id key in controller.physicalInputProfile.buttons) { - NSLog(@"\tButton: %@ (%s)\n", key, elements[key].analog ? "analog" : "digital"); - } - for (id key in controller.physicalInputProfile.axes) { - NSLog(@"\tAxis: %@\n", key); - } - for (id key in controller.physicalInputProfile.dpads) { - NSLog(@"\tHat: %@\n", key); - } + NSDictionary *elements = controller.physicalInputProfile.elements; + for (id key in controller.physicalInputProfile.buttons) { + NSLog(@"\tButton: %@ (%s)\n", key, elements[key].analog ? "analog" : "digital"); + } + for (id key in controller.physicalInputProfile.axes) { + NSLog(@"\tAxis: %@\n", key); + } + for (id key in controller.physicalInputProfile.dpads) { + NSLog(@"\tHat: %@\n", key); } } #endif - BOOL is_xbox = IsControllerXbox(controller); - BOOL is_ps4 = IsControllerPS4(controller); - BOOL is_ps5 = IsControllerPS5(controller); - BOOL is_switch_pro = IsControllerSwitchPro(controller); - BOOL is_switch_joycon_pair = IsControllerSwitchJoyConPair(controller); - BOOL is_stadia = IsControllerStadia(controller); - BOOL is_backbone_one = IsControllerBackboneOne(controller); - BOOL is_switch_joyconL = IsControllerSwitchJoyConL(controller); - BOOL is_switch_joyconR = IsControllerSwitchJoyConR(controller); + device->is_xbox = IsControllerXbox(controller); + device->is_ps4 = IsControllerPS4(controller); + device->is_ps5 = IsControllerPS5(controller); + device->is_switch_pro = IsControllerSwitchPro(controller); + device->is_switch_joycon_pair = IsControllerSwitchJoyConPair(controller); + device->is_stadia = IsControllerStadia(controller); + device->is_backbone_one = IsControllerBackboneOne(controller); + device->is_switch_joyconL = IsControllerSwitchJoyConL(controller); + device->is_switch_joyconR = IsControllerSwitchJoyConR(controller); #ifdef SDL_JOYSTICK_HIDAPI - if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE)) || - (is_ps4 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS4)) || - (is_ps5 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS5)) || - (is_switch_pro && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO)) || - (is_switch_joycon_pair && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR, 0, "")) || - (is_stadia && HIDAPI_IsDevicePresent(USB_VENDOR_GOOGLE, USB_PRODUCT_GOOGLE_STADIA_CONTROLLER, 0, "")) || - (is_switch_joyconL && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT, 0, "")) || - (is_switch_joyconR && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT, 0, ""))) { + if ((device->is_xbox && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE)) || + (device->is_ps4 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS4)) || + (device->is_ps5 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS5)) || + (device->is_switch_pro && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO)) || + (device->is_switch_joycon_pair && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR, 0, "")) || + (device->is_stadia && HIDAPI_IsDevicePresent(USB_VENDOR_GOOGLE, USB_PRODUCT_GOOGLE_STADIA_CONTROLLER, 0, "")) || + (device->is_switch_joyconL && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT, 0, "")) || + (device->is_switch_joyconR && HIDAPI_IsDevicePresent(USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT, 0, ""))) { /* The HIDAPI driver is taking care of this device */ return FALSE; } -#else - (void)is_stadia; - (void)is_switch_joyconL; - (void)is_switch_joyconR; #endif CheckControllerSiriRemote(controller, &device->is_siri_remote); @@ -412,27 +416,27 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } #ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) { - device->has_dualshock_touchpad = SDL_TRUE; + device->has_dualshock_touchpad = TRUE; } if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { - device->has_xbox_paddles = SDL_TRUE; + device->has_xbox_paddles = TRUE; } if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { - device->has_xbox_share_button = SDL_TRUE; + device->has_xbox_share_button = TRUE; } } #endif // ENABLE_PHYSICAL_INPUT_PROFILE - if (is_backbone_one) { + if (device->is_backbone_one) { vendor = USB_VENDOR_BACKBONE; - if (is_ps5) { + if (device->is_ps5) { product = USB_PRODUCT_BACKBONE_ONE_IOS_PS5; } else { product = USB_PRODUCT_BACKBONE_ONE_IOS; } - } else if (is_xbox) { + } else if (device->is_xbox) { vendor = USB_VENDOR_MICROSOFT; if (device->has_xbox_paddles) { /* Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID */ @@ -444,34 +448,32 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle /* Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID */ product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; } - } else if (is_ps4) { + } else if (device->is_ps4) { /* Assume DS4 Slim unless/until GCController flows VID/PID */ vendor = USB_VENDOR_SONY; product = USB_PRODUCT_SONY_DS4_SLIM; if (device->has_dualshock_touchpad) { subtype = 1; } - } else if (is_ps5) { + } else if (device->is_ps5) { vendor = USB_VENDOR_SONY; product = USB_PRODUCT_SONY_DS5; - } else if (is_switch_pro) { + } else if (device->is_switch_pro) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_PRO; - device->has_nintendo_buttons = SDL_TRUE; - } else if (is_switch_joycon_pair) { + device->has_nintendo_buttons = TRUE; + } else if (device->is_switch_joycon_pair) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; - device->has_nintendo_buttons = SDL_TRUE; - } else if (is_switch_joyconL) { + device->has_nintendo_buttons = TRUE; + } else if (device->is_switch_joyconL) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT; - device->is_single_joycon = SDL_TRUE; - } else if (is_switch_joyconR) { + } else if (device->is_switch_joyconR) { vendor = USB_VENDOR_NINTENDO; product = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT; - device->is_single_joycon = SDL_TRUE; #ifdef ENABLE_PHYSICAL_INPUT_PROFILE - } else if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + } else if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { vendor = USB_VENDOR_APPLE; product = 4; subtype = 4; @@ -491,17 +493,15 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle subtype = 3; #endif } else { - vendor = USB_VENDOR_APPLE; - product = 5; - subtype = 5; + /* We don't know how to get input events from this device */ + return SDL_FALSE; } #ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { NSDictionary *elements = controller.physicalInputProfile.elements; /* Provide both axes and analog buttons as SDL axes */ - device->use_physical_profile = SDL_TRUE; device->axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { if (ElementAlreadyHandled(device, (NSString *)object, elements)) { @@ -545,7 +545,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle #if TARGET_OS_TV /* tvOS turns the menu button into a system gesture, so we grab it here instead */ - if (elements[GCInputButtonMenu] && !elements[GCInputButtonHome]) { + if (elements[GCInputButtonMenu] && !elements[@"Button Home"]) { device->pause_button_index = [device->buttons indexOfObject:GCInputButtonMenu]; } #endif @@ -566,82 +566,38 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle nbuttons += 6; /* These buttons are available on some newer controllers */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - if ([gamepad respondsToSelector:@selector(leftThumbstickButton)] && gamepad.leftThumbstickButton) { - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK); - ++nbuttons; - } - if ([gamepad respondsToSelector:@selector(rightThumbstickButton)] && gamepad.rightThumbstickButton) { - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK); - ++nbuttons; - } - if ([gamepad respondsToSelector:@selector(buttonOptions)] && gamepad.buttonOptions) { - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_BACK); - ++nbuttons; + if (@available(macOS 10.14.1, iOS 12.1, tvOS 12.1, *)) { + if (gamepad.leftThumbstickButton) { + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK); + ++nbuttons; + } + if (gamepad.rightThumbstickButton) { + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK); + ++nbuttons; + } } - /* The Nintendo Switch JoyCon home button doesn't ever show as being held down */ - if ([gamepad respondsToSelector:@selector(buttonHome)] && gamepad.buttonHome && !is_switch_joycon_pair) { - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_GUIDE); - ++nbuttons; + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + if (gamepad.buttonOptions) { + device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_BACK); + ++nbuttons; + } } device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_START); ++nbuttons; - has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu; - if (!has_direct_menu) { - device->pause_button_index = (nbuttons - 1); + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + if (gamepad.buttonMenu) { + has_direct_menu = TRUE; + } } #if TARGET_OS_TV /* The single menu button isn't very reliable, at least as of tvOS 16.1 */ if ((device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) == 0) { - device->pause_button_index = (nbuttons - 1); - } -#endif - -#ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if ([controller respondsToSelector:@selector(physicalInputProfile)]) { - if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) { - device->has_dualshock_touchpad = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_MISC1); - ++nbuttons; - } - if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { - device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1); - ++nbuttons; - } - if (controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo] != nil) { - device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2); - ++nbuttons; - } - if (controller.physicalInputProfile.buttons[GCInputXboxPaddleThree] != nil) { - device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1); - ++nbuttons; - } - if (controller.physicalInputProfile.buttons[GCInputXboxPaddleFour] != nil) { - device->has_xbox_paddles = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2); - ++nbuttons; - } - if (controller.physicalInputProfile.buttons[@"Button Share"] != nil) { - device->has_xbox_share_button = SDL_TRUE; - device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_MISC1); - ++nbuttons; - } + has_direct_menu = FALSE; } #endif -#pragma clang diagnostic pop - - if (is_backbone_one) { - /* The Backbone app uses share button */ - if ((device->button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC1)) != 0) { - device->button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_MISC1); - --nbuttons; - device->has_xbox_share_button = SDL_FALSE; - } + if (!has_direct_menu) { + device->pause_button_index = (nbuttons - 1); } device->naxes = 6; /* 2 thumbsticks and 2 triggers */ @@ -684,12 +640,12 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } #endif else { - /* We can't detect any inputs on this */ + /* We don't know how to get input events from this device */ return SDL_FALSE; } Uint16 signature; - if (device->use_physical_profile) { + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { signature = 0; signature = SDL_crc16(signature, device->name, SDL_strlen(device->name)); for (id key in device->axes) { @@ -1169,7 +1125,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #endif /* DEBUG_CONTROLLER_STATE */ - if (device->use_physical_profile) { + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { NSDictionary *elements = controller.physicalInputProfile.elements; NSDictionary *buttons = controller.physicalInputProfile.buttons; @@ -1227,54 +1183,30 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) buttons[button_count++] = gamepad.rightShoulder.isPressed; /* These buttons are available on some newer controllers */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) { - buttons[button_count++] = gamepad.leftThumbstickButton.isPressed; - } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) { - buttons[button_count++] = gamepad.rightThumbstickButton.isPressed; - } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { - buttons[button_count++] = gamepad.buttonOptions.isPressed; + if (@available(macOS 10.14.1, iOS 12.1, tvOS 12.1, *)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) { + buttons[button_count++] = gamepad.leftThumbstickButton.isPressed; + } + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) { + buttons[button_count++] = gamepad.rightThumbstickButton.isPressed; + } } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) { - buttons[button_count++] = gamepad.buttonHome.isPressed; + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) { + buttons[button_count++] = gamepad.buttonOptions.isPressed; + } } if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) { if (device->pause_button_index >= 0) { + /* Guaranteed if buttonMenu is not supported on this OS */ buttons[button_count++] = (device->pause_button_pressed > 0); } else { - buttons[button_count++] = gamepad.buttonMenu.isPressed; - } - } - -#ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if (device->has_dualshock_touchpad) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed; - } - - if (device->has_xbox_paddles) { - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1)) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed; - } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2)) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed; - } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE1)) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed; - } - if (device->button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_PADDLE2)) { - buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed; + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + buttons[button_count++] = gamepad.buttonMenu.isPressed; + } } } - if (device->has_xbox_share_button) { - buttons[button_count++] = controller.physicalInputProfile.buttons[@"Button Share"].isPressed; - } -#endif -#pragma clang diagnostic pop - hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad); for (i = 0; i < SDL_arraysize(axes); i++) { @@ -1353,21 +1285,23 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #ifdef ENABLE_PHYSICAL_INPUT_PROFILE - if (device->has_dualshock_touchpad) { - GCControllerDirectionPad *dpad; + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + if (device->has_dualshock_touchpad) { + GCControllerDirectionPad *dpad; - dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne]; - if (dpad.xAxis.value || dpad.yAxis.value) { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); - } else { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_RELEASED, 0.0f, 0.0f, 1.0f); - } + dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne]; + if (dpad.xAxis.value || dpad.yAxis.value) { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); + } else { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, SDL_RELEASED, 0.0f, 0.0f, 1.0f); + } - dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadTwo]; - if (dpad.xAxis.value || dpad.yAxis.value) { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); - } else { - SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_RELEASED, 0.0f, 0.0f, 1.0f); + dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadTwo]; + if (dpad.xAxis.value || dpad.yAxis.value) { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_PRESSED, (1.0f + dpad.xAxis.value) * 0.5f, 1.0f - (1.0f + dpad.yAxis.value) * 0.5f, 1.0f); + } else { + SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, SDL_RELEASED, 0.0f, 0.0f, 1.0f); + } } } #endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ @@ -1890,138 +1824,136 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi return SDL_FALSE; } - if (!device->use_physical_profile) { - return SDL_FALSE; - } + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + int axis = 0; + for (id key in device->axes) { + if ([(NSString *)key isEqualToString:@"Left Thumbstick X Axis"] || + [(NSString *)key isEqualToString:@"Direction Pad X Axis"]) { + out->leftx.kind = EMappingKind_Axis; + out->leftx.target = axis; + } else if ([(NSString *)key isEqualToString:@"Left Thumbstick Y Axis"] || + [(NSString *)key isEqualToString:@"Direction Pad Y Axis"]) { + out->lefty.kind = EMappingKind_Axis; + out->lefty.target = axis; + out->lefty.axis_reversed = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:@"Right Thumbstick X Axis"]) { + out->rightx.kind = EMappingKind_Axis; + out->rightx.target = axis; + } else if ([(NSString *)key isEqualToString:@"Right Thumbstick Y Axis"]) { + out->righty.kind = EMappingKind_Axis; + out->righty.target = axis; + out->righty.axis_reversed = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { + out->lefttrigger.kind = EMappingKind_Axis; + out->lefttrigger.target = axis; + out->lefttrigger.half_axis_positive = SDL_TRUE; + } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { + out->righttrigger.kind = EMappingKind_Axis; + out->righttrigger.target = axis; + out->righttrigger.half_axis_positive = SDL_TRUE; + } + ++axis; + } + + int button = 0; + for (id key in device->buttons) { + SDL_InputMapping *mapping = NULL; - int axis = 0; - for (id key in device->axes) { - if ([(NSString *)key isEqualToString:@"Left Thumbstick X Axis"] || - [(NSString *)key isEqualToString:@"Direction Pad X Axis"]) { - out->leftx.kind = EMappingKind_Axis; - out->leftx.target = axis; - } else if ([(NSString *)key isEqualToString:@"Left Thumbstick Y Axis"] || - [(NSString *)key isEqualToString:@"Direction Pad Y Axis"]) { - out->lefty.kind = EMappingKind_Axis; - out->lefty.target = axis; - out->lefty.axis_reversed = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:@"Right Thumbstick X Axis"]) { - out->rightx.kind = EMappingKind_Axis; - out->rightx.target = axis; - } else if ([(NSString *)key isEqualToString:@"Right Thumbstick Y Axis"]) { - out->righty.kind = EMappingKind_Axis; - out->righty.target = axis; - out->righty.axis_reversed = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { - out->lefttrigger.kind = EMappingKind_Axis; - out->lefttrigger.target = axis; - out->lefttrigger.half_axis_positive = SDL_TRUE; - } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { - out->righttrigger.kind = EMappingKind_Axis; - out->righttrigger.target = axis; - out->righttrigger.half_axis_positive = SDL_TRUE; - } - ++axis; - } - - int button = 0; - for (id key in device->buttons) { - SDL_InputMapping *mapping = NULL; - - if ([(NSString *)key isEqualToString:GCInputButtonA]) { - if (device->is_siri_remote > 1) { - /* GCInputButtonA is triggered for any D-Pad press, ignore it in favor of "Button Center" */ - } else if (device->has_nintendo_buttons) { - mapping = &out->b; - } else { - mapping = &out->a; - } - } else if ([(NSString *)key isEqualToString:GCInputButtonB]) { - if (device->has_nintendo_buttons) { + if ([(NSString *)key isEqualToString:GCInputButtonA]) { + if (device->is_siri_remote > 1) { + /* GCInputButtonA is triggered for any D-Pad press, ignore it in favor of "Button Center" */ + } else if (device->has_nintendo_buttons) { + mapping = &out->b; + } else { + mapping = &out->a; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonB]) { + if (device->has_nintendo_buttons) { + mapping = &out->a; + } else if (device->is_switch_joyconL || device->is_switch_joyconR) { + mapping = &out->x; + } else { + mapping = &out->b; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonX]) { + if (device->has_nintendo_buttons) { + mapping = &out->y; + } else if (device->is_switch_joyconL || device->is_switch_joyconR) { + mapping = &out->b; + } else { + mapping = &out->x; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonY]) { + if (device->has_nintendo_buttons) { + mapping = &out->x; + } else { + mapping = &out->y; + } + } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"]) { + mapping = &out->dpleft; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"]) { + mapping = &out->dpright; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"]) { + mapping = &out->dpup; + } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"]) { + mapping = &out->dpdown; + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Left"]) { + mapping = &out->dpleft; + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Right"]) { + mapping = &out->dpright; + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Up"]) { + mapping = &out->dpup; + } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Down"]) { + mapping = &out->dpdown; + } else if ([(NSString *)key isEqualToString:GCInputLeftShoulder]) { + mapping = &out->leftshoulder; + } else if ([(NSString *)key isEqualToString:GCInputRightShoulder]) { + mapping = &out->rightshoulder; + } else if ([(NSString *)key isEqualToString:GCInputLeftThumbstickButton]) { + mapping = &out->leftstick; + } else if ([(NSString *)key isEqualToString:GCInputRightThumbstickButton]) { + mapping = &out->rightstick; + } else if ([(NSString *)key isEqualToString:@"Button Home"]) { + mapping = &out->guide; + } else if ([(NSString *)key isEqualToString:GCInputButtonMenu]) { + if (device->is_siri_remote) { + mapping = &out->b; + } else { + mapping = &out->start; + } + } else if ([(NSString *)key isEqualToString:GCInputButtonOptions]) { + mapping = &out->back; + } else if ([(NSString *)key isEqualToString:@"Button Share"]) { + mapping = &out->misc1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleOne]) { + mapping = &out->right_paddle1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleTwo]) { + mapping = &out->right_paddle2; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleThree]) { + mapping = &out->left_paddle1; + } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleFour]) { + mapping = &out->left_paddle2; + } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { + mapping = &out->lefttrigger; + } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { + mapping = &out->righttrigger; + } else if ([(NSString *)key isEqualToString:GCInputDualShockTouchpadButton]) { + mapping = &out->touchpad; + } else if ([(NSString *)key isEqualToString:@"Button Center"]) { mapping = &out->a; - } else if (device->is_single_joycon) { - mapping = &out->x; - } else { - mapping = &out->b; - } - } else if ([(NSString *)key isEqualToString:GCInputButtonX]) { - if (device->has_nintendo_buttons) { - mapping = &out->y; - } else if (device->is_single_joycon) { - mapping = &out->b; - } else { - mapping = &out->x; } - } else if ([(NSString *)key isEqualToString:GCInputButtonY]) { - if (device->has_nintendo_buttons) { - mapping = &out->x; - } else { - mapping = &out->y; + if (mapping && mapping->kind == EMappingKind_None) { + mapping->kind = EMappingKind_Button; + mapping->target = button; } - } else if ([(NSString *)key isEqualToString:@"Direction Pad Left"]) { - mapping = &out->dpleft; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Right"]) { - mapping = &out->dpright; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Up"]) { - mapping = &out->dpup; - } else if ([(NSString *)key isEqualToString:@"Direction Pad Down"]) { - mapping = &out->dpdown; - } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Left"]) { - mapping = &out->dpleft; - } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Right"]) { - mapping = &out->dpright; - } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Up"]) { - mapping = &out->dpup; - } else if ([(NSString *)key isEqualToString:@"Cardinal Direction Pad Down"]) { - mapping = &out->dpdown; - } else if ([(NSString *)key isEqualToString:GCInputLeftShoulder]) { - mapping = &out->leftshoulder; - } else if ([(NSString *)key isEqualToString:GCInputRightShoulder]) { - mapping = &out->rightshoulder; - } else if ([(NSString *)key isEqualToString:GCInputLeftThumbstickButton]) { - mapping = &out->leftstick; - } else if ([(NSString *)key isEqualToString:GCInputRightThumbstickButton]) { - mapping = &out->rightstick; - } else if ([(NSString *)key isEqualToString:GCInputButtonHome]) { - mapping = &out->guide; - } else if ([(NSString *)key isEqualToString:GCInputButtonMenu]) { - if (device->is_siri_remote) { - mapping = &out->b; - } else { - mapping = &out->start; - } - } else if ([(NSString *)key isEqualToString:GCInputButtonOptions]) { - mapping = &out->back; - } else if ([(NSString *)key isEqualToString:@"Button Share"]) { - mapping = &out->misc1; - } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleOne]) { - mapping = &out->right_paddle1; - } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleTwo]) { - mapping = &out->right_paddle2; - } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleThree]) { - mapping = &out->left_paddle1; - } else if ([(NSString *)key isEqualToString:GCInputXboxPaddleFour]) { - mapping = &out->left_paddle2; - } else if ([(NSString *)key isEqualToString:GCInputLeftTrigger]) { - mapping = &out->lefttrigger; - } else if ([(NSString *)key isEqualToString:GCInputRightTrigger]) { - mapping = &out->righttrigger; - } else if ([(NSString *)key isEqualToString:GCInputDualShockTouchpadButton]) { - mapping = &out->touchpad; - } else if ([(NSString *)key isEqualToString:@"Button Center"]) { - mapping = &out->a; - } - if (mapping && mapping->kind == EMappingKind_None) { - mapping->kind = EMappingKind_Button; - mapping->target = button; - } - ++button; - } - - return SDL_TRUE; -#else - return SDL_FALSE; + ++button; + } + + return SDL_TRUE; + } #endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ + + return SDL_FALSE; } #if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) @@ -2059,7 +1991,7 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * static GCControllerDirectionPad *GetDirectionalPadForController(GCController *controller) { - if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { return controller.physicalInputProfile.dpads[GCInputDirectionPad]; } @@ -2107,7 +2039,7 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * GetAppleSFSymbolsNameForElement(elements[GCInputButtonOptions], elementName); break; case SDL_GAMEPAD_BUTTON_GUIDE: - GetAppleSFSymbolsNameForElement(elements[GCInputButtonHome], elementName); + GetAppleSFSymbolsNameForElement(elements[@"Button Home"], elementName); break; case SDL_GAMEPAD_BUTTON_START: GetAppleSFSymbolsNameForElement(elements[GCInputButtonMenu], elementName); diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index d1d984fd18952..7bd52d79d3cec 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -47,17 +47,25 @@ typedef struct joystick_hwdata int nbuttons; int nhats; Uint32 button_mask; - SDL_bool has_dualshock_touchpad; - SDL_bool has_xbox_paddles; - SDL_bool has_xbox_share_button; - SDL_bool has_nintendo_buttons; - SDL_bool is_single_joycon; + BOOL is_xbox; + BOOL is_ps4; + BOOL is_ps5; + BOOL is_switch_pro; + BOOL is_switch_joycon_pair; + BOOL is_switch_joyconL; + BOOL is_switch_joyconR; + BOOL is_stadia; + BOOL is_backbone_one; int is_siri_remote; - SDL_bool use_physical_profile; NSArray *axes; NSArray *buttons; + BOOL has_dualshock_touchpad; + BOOL has_xbox_paddles; + BOOL has_xbox_share_button; + BOOL has_nintendo_buttons; + struct joystick_hwdata *next; } joystick_hwdata; From 666301f9f969eef83087bdf5368a05a1f5d4a0b2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 16 Nov 2023 21:01:28 -0800 Subject: [PATCH 385/725] Fixed build with older macOS SDK --- src/joystick/apple/SDL_mfijoystick_c.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index 7bd52d79d3cec..0b32885886271 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -47,24 +47,24 @@ typedef struct joystick_hwdata int nbuttons; int nhats; Uint32 button_mask; - BOOL is_xbox; - BOOL is_ps4; - BOOL is_ps5; - BOOL is_switch_pro; - BOOL is_switch_joycon_pair; - BOOL is_switch_joyconL; - BOOL is_switch_joyconR; - BOOL is_stadia; - BOOL is_backbone_one; + SDL_bool is_xbox; + SDL_bool is_ps4; + SDL_bool is_ps5; + SDL_bool is_switch_pro; + SDL_bool is_switch_joycon_pair; + SDL_bool is_switch_joyconL; + SDL_bool is_switch_joyconR; + SDL_bool is_stadia; + SDL_bool is_backbone_one; int is_siri_remote; NSArray *axes; NSArray *buttons; - BOOL has_dualshock_touchpad; - BOOL has_xbox_paddles; - BOOL has_xbox_share_button; - BOOL has_nintendo_buttons; + SDL_bool has_dualshock_touchpad; + SDL_bool has_xbox_paddles; + SDL_bool has_xbox_share_button; + SDL_bool has_nintendo_buttons; struct joystick_hwdata *next; } joystick_hwdata; From 39870031d1a5d36dac2f0100554a836e5afe2e7b Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Fri, 17 Nov 2023 15:56:10 +0300 Subject: [PATCH 386/725] use format string attributes for functions accepting va_list params, too --- include/SDL3/SDL_log.h | 2 +- include/SDL3/SDL_rwops.h | 2 +- include/SDL3/SDL_stdinc.h | 12 +++++++++--- src/dynapi/gendynapi.py | 4 ++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h index 370c4de2795e0..bda15070fa3e4 100644 --- a/include/SDL3/SDL_log.h +++ b/include/SDL3/SDL_log.h @@ -351,7 +351,7 @@ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, */ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, - const char *fmt, va_list ap); + SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); /** * The prototype for the log output callback function. diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 88495d1583611..86b53347b3653 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -541,7 +541,7 @@ extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMA * \sa SDL_RWseek * \sa SDL_RWwrite */ -extern DECLSPEC size_t SDLCALL SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap); +extern DECLSPEC size_t SDLCALL SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); /** * Close and free an allocated SDL_RWops structure. diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 5d1483cefed6b..520c7561a6fc0 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -281,7 +281,9 @@ typedef uint64_t Uint64; #define SDL_PRINTF_FORMAT_STRING #define SDL_SCANF_FORMAT_STRING #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) +#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) +#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) #define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) #else @@ -309,12 +311,16 @@ typedef uint64_t Uint64; #endif #ifdef __GNUC__ #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) +#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 ))) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) +#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 ))) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) /* __attribute__ (( format( __wprintf__, fmtargnumber, fmtargnumber+1 ))) */ #define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) /* __attribute__ (( format( __wscanf__, fmtargnumber, fmtargnumber+1 ))) */ #else #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) +#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) +#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) #define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) #endif @@ -580,13 +586,13 @@ extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len); extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap); +extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); extern DECLSPEC int SDLCALL SDL_swprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ... ) SDL_WPRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap); +extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); extern DECLSPEC int SDLCALL SDL_vswprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, const wchar_t *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap); +extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); #ifndef SDL_PI_D #define SDL_PI_D 3.141592653589793238462643383279502884 /**< pi (double) */ diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index e08ce2cc60308..3c5f73cd92781 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -150,8 +150,12 @@ def main(): func = func.replace(" SDL_PRINTF_VARARG_FUNC(1)", ""); func = func.replace(" SDL_PRINTF_VARARG_FUNC(2)", ""); func = func.replace(" SDL_PRINTF_VARARG_FUNC(3)", ""); + func = func.replace(" SDL_PRINTF_VARARG_FUNCV(1)", ""); + func = func.replace(" SDL_PRINTF_VARARG_FUNCV(2)", ""); + func = func.replace(" SDL_PRINTF_VARARG_FUNCV(3)", ""); func = func.replace(" SDL_WPRINTF_VARARG_FUNC(3)", ""); func = func.replace(" SDL_SCANF_VARARG_FUNC(2)", ""); + func = func.replace(" SDL_SCANF_VARARG_FUNCV(2)", ""); func = func.replace(" __attribute__((analyzer_noreturn))", ""); func = func.replace(" SDL_MALLOC", ""); func = func.replace(" SDL_ALLOC_SIZE2(1, 2)", ""); From fda69e5e79142f9ebbf8aa0de9f369ff5f06eb1a Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 11:42:14 +0000 Subject: [PATCH 387/725] Test both MSB and LSB indexed surfaces in testautomation --- test/testautomation_surface.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index 5567ece46bebd..9226fb9192b09 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -632,12 +632,12 @@ static int surface_testOverflow(void *arg) /* Less than 1 byte per pixel: the pitch can legitimately be less than * the width, but it must be enough to hold the appropriate number of - * bits per pixel. SDL_PIXELFORMAT_INDEX4LSB* needs 1 byte per 2 pixels. */ + * bits per pixel. SDL_PIXELFORMAT_INDEX4* needs 1 byte per 2 pixels. */ surface = SDL_CreateSurfaceFrom(buf, 6, 1, 3, SDL_PIXELFORMAT_INDEX4LSB); SDLTest_AssertCheck(surface != NULL, "6px * 4 bits per px fits in 3 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); - surface = SDL_CreateSurfaceFrom(buf, 6, 1, 3, SDL_PIXELFORMAT_INDEX4LSB); + surface = SDL_CreateSurfaceFrom(buf, 6, 1, 3, SDL_PIXELFORMAT_INDEX4MSB); SDLTest_AssertCheck(surface != NULL, "6px * 4 bits per px fits in 3 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); @@ -646,7 +646,7 @@ static int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - surface = SDL_CreateSurfaceFrom(buf, 7, 1, 3, SDL_PIXELFORMAT_INDEX4LSB); + surface = SDL_CreateSurfaceFrom(buf, 7, 1, 3, SDL_PIXELFORMAT_INDEX4MSB); SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); @@ -655,7 +655,7 @@ static int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface != NULL, "7px * 4 bits per px fits in 4 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); - surface = SDL_CreateSurfaceFrom(buf, 7, 1, 4, SDL_PIXELFORMAT_INDEX4LSB); + surface = SDL_CreateSurfaceFrom(buf, 7, 1, 4, SDL_PIXELFORMAT_INDEX4MSB); SDLTest_AssertCheck(surface != NULL, "7px * 4 bits per px fits in 4 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); @@ -665,7 +665,7 @@ static int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface != NULL, "16px * 1 bit per px fits in 2 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); - surface = SDL_CreateSurfaceFrom(buf, 16, 1, 2, SDL_PIXELFORMAT_INDEX1LSB); + surface = SDL_CreateSurfaceFrom(buf, 16, 1, 2, SDL_PIXELFORMAT_INDEX1MSB); SDLTest_AssertCheck(surface != NULL, "16px * 1 bit per px fits in 2 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); @@ -674,7 +674,7 @@ static int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - surface = SDL_CreateSurfaceFrom(buf, 17, 1, 2, SDL_PIXELFORMAT_INDEX1LSB); + surface = SDL_CreateSurfaceFrom(buf, 17, 1, 2, SDL_PIXELFORMAT_INDEX1MSB); SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); @@ -683,7 +683,7 @@ static int surface_testOverflow(void *arg) SDLTest_AssertCheck(surface != NULL, "17px * 1 bit per px fits in 3 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); - surface = SDL_CreateSurfaceFrom(buf, 17, 1, 3, SDL_PIXELFORMAT_INDEX1LSB); + surface = SDL_CreateSurfaceFrom(buf, 17, 1, 3, SDL_PIXELFORMAT_INDEX1MSB); SDLTest_AssertCheck(surface != NULL, "17px * 1 bit per px fits in 3 bytes: %s", surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); From 753bbd199ef98ac350af4e86b0987c96d5f5339d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 11:43:39 +0000 Subject: [PATCH 388/725] Add SDL_PIXELFORMAT_INDEX2LSB and SDL_PIXELFORMAT_INDEX2MSB --- include/SDL3/SDL_pixels.h | 8 ++++++++ src/test/SDL_test_common.c | 6 ++++++ src/video/SDL_pixels.c | 5 +++++ test/testautomation_pixels.c | 4 ++++ test/testautomation_surface.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index cde70c116face..02bae04101e76 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -88,6 +88,7 @@ typedef enum { SDL_PIXELTYPE_UNKNOWN, SDL_PIXELTYPE_INDEX1, + SDL_PIXELTYPE_INDEX2, SDL_PIXELTYPE_INDEX4, SDL_PIXELTYPE_INDEX8, SDL_PIXELTYPE_PACKED8, @@ -166,6 +167,7 @@ typedef enum #define SDL_ISPIXELFORMAT_INDEXED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))) @@ -208,6 +210,12 @@ typedef enum SDL_PIXELFORMAT_INDEX1MSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, 1, 0), + SDL_PIXELFORMAT_INDEX2LSB = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, + 2, 0), + SDL_PIXELFORMAT_INDEX2MSB = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, + 2, 0), SDL_PIXELFORMAT_INDEX4LSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, 4, 0), diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 12b7fee5e3b0b..8507807fd8f39 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -908,6 +908,12 @@ static void SDLTest_PrintPixelFormat(char *text, size_t maxlen, Uint32 format) case SDL_PIXELFORMAT_INDEX1MSB: SDL_snprintfcat(text, maxlen, "Index1MSB"); break; + case SDL_PIXELFORMAT_INDEX2LSB: + SDL_snprintfcat(text, maxlen, "Index2LSB"); + break; + case SDL_PIXELFORMAT_INDEX2MSB: + SDL_snprintfcat(text, maxlen, "Index2MSB"); + break; case SDL_PIXELFORMAT_INDEX4LSB: SDL_snprintfcat(text, maxlen, "Index4LSB"); break; diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 262880c83da04..aaeb1d9f2a819 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -89,6 +89,8 @@ const char *SDL_GetPixelFormatName(Uint32 format) CASE(SDL_PIXELFORMAT_INDEX1LSB) CASE(SDL_PIXELFORMAT_INDEX1MSB) + CASE(SDL_PIXELFORMAT_INDEX2LSB) + CASE(SDL_PIXELFORMAT_INDEX2MSB) CASE(SDL_PIXELFORMAT_INDEX4LSB) CASE(SDL_PIXELFORMAT_INDEX4MSB) CASE(SDL_PIXELFORMAT_INDEX8) @@ -309,6 +311,9 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3 case 1: /* SDL defaults to MSB ordering */ return SDL_PIXELFORMAT_INDEX1MSB; + case 2: + /* SDL defaults to MSB ordering */ + return SDL_PIXELFORMAT_INDEX2MSB; case 4: /* SDL defaults to MSB ordering */ return SDL_PIXELFORMAT_INDEX4MSB; diff --git a/test/testautomation_pixels.c b/test/testautomation_pixels.c index 62d1b1b5cb5c7..790c9d861a73e 100644 --- a/test/testautomation_pixels.c +++ b/test/testautomation_pixels.c @@ -11,6 +11,8 @@ static const Uint32 g_AllFormats[] = { SDL_PIXELFORMAT_INDEX1LSB, SDL_PIXELFORMAT_INDEX1MSB, + SDL_PIXELFORMAT_INDEX2LSB, + SDL_PIXELFORMAT_INDEX2MSB, SDL_PIXELFORMAT_INDEX4LSB, SDL_PIXELFORMAT_INDEX4MSB, SDL_PIXELFORMAT_INDEX8, @@ -56,6 +58,8 @@ static const int g_numAllFormats = SDL_arraysize(g_AllFormats); static const char *g_AllFormatsVerbose[] = { "SDL_PIXELFORMAT_INDEX1LSB", "SDL_PIXELFORMAT_INDEX1MSB", + "SDL_PIXELFORMAT_INDEX2LSB", + "SDL_PIXELFORMAT_INDEX2MSB", "SDL_PIXELFORMAT_INDEX4LSB", "SDL_PIXELFORMAT_INDEX4MSB", "SDL_PIXELFORMAT_INDEX8", diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index 9226fb9192b09..93da3740f35f1 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -660,6 +660,34 @@ static int surface_testOverflow(void *arg) surface != NULL ? "(success)" : SDL_GetError()); SDL_DestroySurface(surface); + /* SDL_PIXELFORMAT_INDEX2* needs 1 byte per 4 pixels. */ + surface = SDL_CreateSurfaceFrom(buf, 12, 1, 3, SDL_PIXELFORMAT_INDEX2LSB); + SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s", + surface != NULL ? "(success)" : SDL_GetError()); + SDL_DestroySurface(surface); + surface = SDL_CreateSurfaceFrom(buf, 12, 1, 3, SDL_PIXELFORMAT_INDEX2MSB); + SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s", + surface != NULL ? "(success)" : SDL_GetError()); + SDL_DestroySurface(surface); + + surface = SDL_CreateSurfaceFrom(buf, 13, 1, 3, SDL_PIXELFORMAT_INDEX2LSB); + SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp (%d)", surface ? surface->pitch : 0); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, + "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); + surface = SDL_CreateSurfaceFrom(buf, 13, 1, 3, SDL_PIXELFORMAT_INDEX2MSB); + SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); + SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, + "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); + + surface = SDL_CreateSurfaceFrom(buf, 13, 1, 4, SDL_PIXELFORMAT_INDEX2LSB); + SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s", + surface != NULL ? "(success)" : SDL_GetError()); + SDL_DestroySurface(surface); + surface = SDL_CreateSurfaceFrom(buf, 13, 1, 4, SDL_PIXELFORMAT_INDEX2MSB); + SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s", + surface != NULL ? "(success)" : SDL_GetError()); + SDL_DestroySurface(surface); + /* SDL_PIXELFORMAT_INDEX1* needs 1 byte per 8 pixels. */ surface = SDL_CreateSurfaceFrom(buf, 16, 1, 2, SDL_PIXELFORMAT_INDEX1LSB); SDLTest_AssertCheck(surface != NULL, "16px * 1 bit per px fits in 2 bytes: %s", From 773ec1cfcbe53faf9811580e2cb91107fe4b5bdc Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 14:08:20 +0000 Subject: [PATCH 389/725] Extend blitting support for all <8bpp formats --- src/video/SDL_blit_0.c | 558 +++++++++++++++++++++++++++-------------- 1 file changed, 374 insertions(+), 184 deletions(-) diff --git a/src/video/SDL_blit_0.c b/src/video/SDL_blit_0.c index dd859636b0cc6..6ad4331f5546d 100644 --- a/src/video/SDL_blit_0.c +++ b/src/video/SDL_blit_0.c @@ -26,8 +26,11 @@ /* Functions to blit from bitmaps to other surfaces */ -static void BlitBto1(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int c; int width, height; Uint8 *src, *map, *dst; @@ -41,22 +44,28 @@ static void BlitBto1(SDL_BlitInfo *info) dst = info->dst; dstskip = info->dst_skip; map = info->table; - srcskip += width - (width + 7) / 8; + + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; if (map) { - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { *dst = map[bit]; } dst++; - byte >>= 1; + byte >>= srcbpp; } src += srcskip; dst += dstskip; @@ -65,34 +74,34 @@ static void BlitBto1(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { *dst = map[bit]; } dst++; - byte <<= 1; + byte <<= srcbpp; } src += srcskip; dst += dstskip; } } } else { - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { *dst = bit; } dst++; - byte >>= 1; + byte >>= srcbpp; } src += srcskip; dst += dstskip; @@ -101,15 +110,15 @@ static void BlitBto1(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { *dst = bit; } dst++; - byte <<= 1; + byte <<= srcbpp; } src += srcskip; dst += dstskip; @@ -118,8 +127,11 @@ static void BlitBto1(SDL_BlitInfo *info) } } -static void BlitBto2(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto2(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int c; int width, height; Uint8 *src; @@ -134,20 +146,26 @@ static void BlitBto2(SDL_BlitInfo *info) dst = (Uint16 *)info->dst; dstskip = info->dst_skip / 2; map = (Uint16 *)info->table; - srcskip += width - (width + 7) / 8; - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { *dst = map[bit]; } - byte >>= 1; + byte >>= srcbpp; dst++; } src += srcskip; @@ -157,14 +175,14 @@ static void BlitBto2(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { *dst = map[bit]; } - byte <<= 1; + byte <<= srcbpp; dst++; } src += srcskip; @@ -173,8 +191,11 @@ static void BlitBto2(SDL_BlitInfo *info) } } -static void BlitBto3(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto3(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int c, o; int width, height; Uint8 *src, *map, *dst; @@ -188,23 +209,29 @@ static void BlitBto3(SDL_BlitInfo *info) dst = info->dst; dstskip = info->dst_skip; map = info->table; - srcskip += width - (width + 7) / 8; - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { o = bit * 4; dst[0] = map[o++]; dst[1] = map[o++]; dst[2] = map[o++]; } - byte >>= 1; + byte >>= srcbpp; dst += 3; } src += srcskip; @@ -214,17 +241,17 @@ static void BlitBto3(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { o = bit * 4; dst[0] = map[o++]; dst[1] = map[o++]; dst[2] = map[o++]; } - byte <<= 1; + byte <<= srcbpp; dst += 3; } src += srcskip; @@ -233,8 +260,11 @@ static void BlitBto3(SDL_BlitInfo *info) } } -static void BlitBto4(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto4(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width, height; Uint8 *src; Uint32 *map, *dst; @@ -249,20 +279,26 @@ static void BlitBto4(SDL_BlitInfo *info) dst = (Uint32 *)info->dst; dstskip = info->dst_skip / 4; map = (Uint32 *)info->table; - srcskip += width - (width + 7) / 8; - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { *dst = map[bit]; } - byte >>= 1; + byte >>= srcbpp; dst++; } src += srcskip; @@ -272,14 +308,14 @@ static void BlitBto4(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { *dst = map[bit]; } - byte <<= 1; + byte <<= srcbpp; dst++; } src += srcskip; @@ -288,8 +324,11 @@ static void BlitBto4(SDL_BlitInfo *info) } } -static void BlitBto1Key(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -301,22 +340,27 @@ static void BlitBto1Key(SDL_BlitInfo *info) int c; /* Set up some basic variables */ - srcskip += width - (width + 7) / 8; + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; if (palmap) { - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { *dst = palmap[bit]; } dst++; - byte >>= 1; + byte >>= srcbpp; } src += srcskip; dst += dstskip; @@ -325,34 +369,34 @@ static void BlitBto1Key(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { *dst = palmap[bit]; } dst++; - byte <<= 1; + byte <<= srcbpp; } src += srcskip; dst += dstskip; } } } else { - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { *dst = bit; } dst++; - byte >>= 1; + byte >>= srcbpp; } src += srcskip; dst += dstskip; @@ -361,15 +405,15 @@ static void BlitBto1Key(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { *dst = bit; } dst++; - byte <<= 1; + byte <<= srcbpp; } src += srcskip; dst += dstskip; @@ -378,8 +422,11 @@ static void BlitBto1Key(SDL_BlitInfo *info) } } -static void BlitBto2Key(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto2Key(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -391,21 +438,26 @@ static void BlitBto2Key(SDL_BlitInfo *info) int c; /* Set up some basic variables */ - srcskip += width - (width + 7) / 8; + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; dstskip /= 2; - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { *dstp = ((Uint16 *)palmap)[bit]; } - byte >>= 1; + byte >>= srcbpp; dstp++; } src += srcskip; @@ -415,14 +467,14 @@ static void BlitBto2Key(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { *dstp = ((Uint16 *)palmap)[bit]; } - byte <<= 1; + byte <<= srcbpp; dstp++; } src += srcskip; @@ -431,8 +483,11 @@ static void BlitBto2Key(SDL_BlitInfo *info) } } -static void BlitBto3Key(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto3Key(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -444,20 +499,25 @@ static void BlitBto3Key(SDL_BlitInfo *info) int c; /* Set up some basic variables */ - srcskip += width - (width + 7) / 8; - - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { SDL_memcpy(dst, &palmap[bit * 4], 3); } - byte >>= 1; + byte >>= srcbpp; dst += 3; } src += srcskip; @@ -467,14 +527,14 @@ static void BlitBto3Key(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { SDL_memcpy(dst, &palmap[bit * 4], 3); } - byte <<= 1; + byte <<= srcbpp; dst += 3; } src += srcskip; @@ -483,8 +543,11 @@ static void BlitBto3Key(SDL_BlitInfo *info) } } -static void BlitBto4Key(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBto4Key(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -496,21 +559,26 @@ static void BlitBto4Key(SDL_BlitInfo *info) int c; /* Set up some basic variables */ - srcskip += width - (width + 7) / 8; + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; dstskip /= 4; - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { *dstp = ((Uint32 *)palmap)[bit]; } - byte >>= 1; + byte >>= srcbpp; dstp++; } src += srcskip; @@ -520,14 +588,14 @@ static void BlitBto4Key(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { *dstp = ((Uint32 *)palmap)[bit]; } - byte <<= 1; + byte <<= srcbpp; dstp++; } src += srcskip; @@ -536,8 +604,11 @@ static void BlitBto4Key(SDL_BlitInfo *info) } } -static void BlitBtoNAlpha(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBtoNAlpha(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -555,16 +626,21 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info) /* Set up some basic variables */ dstbpp = dstfmt->BytesPerPixel; - srcskip += width - (width + 7) / 8; - - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (1) { sR = srcpal[bit].r; sG = srcpal[bit].g; @@ -573,7 +649,7 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info) ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); } - byte >>= 1; + byte >>= srcbpp; dst += dstbpp; } src += srcskip; @@ -583,10 +659,10 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (1) { sR = srcpal[bit].r; sG = srcpal[bit].g; @@ -595,7 +671,7 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info) ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); } - byte <<= 1; + byte <<= srcbpp; dst += dstbpp; } src += srcskip; @@ -604,8 +680,11 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info) } } -static void BlitBtoNAlphaKey(SDL_BlitInfo *info) +SDL_FORCE_INLINE void BlitBtoNAlphaKey(SDL_BlitInfo *info, const Uint32 srcbpp) { + const Uint32 mask = (1 << srcbpp) - 1; + const Uint32 align = (8 / srcbpp) - 1; + int width = info->dst_w; int height = info->dst_h; Uint8 *src = info->src; @@ -625,16 +704,21 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info) /* Set up some basic variables */ dstbpp = dstfmt->BytesPerPixel; - srcskip += width - (width + 7) / 8; - - if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) { + if (srcbpp == 4) + srcskip += width - (width + 1) / 2; + else if (srcbpp == 2) + srcskip += width - (width + 3) / 4; + else if (srcbpp == 1) + srcskip += width - (width + 7) / 8; + + if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) { while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x01); + bit = (byte & mask); if (bit != ckey) { sR = srcpal[bit].r; sG = srcpal[bit].g; @@ -643,7 +727,7 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info) ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); } - byte >>= 1; + byte >>= srcbpp; dst += dstbpp; } src += srcskip; @@ -653,10 +737,10 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info) while (height--) { Uint8 byte = 0, bit; for (c = 0; c < width; ++c) { - if (!(c & 7)) { + if (!(c & align)) { byte = *src++; } - bit = (byte & 0x80) >> 7; + bit = (byte >> (8 - srcbpp)) & mask; if (bit != ckey) { sR = srcpal[bit].r; sG = srcpal[bit].g; @@ -665,7 +749,7 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info) ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); } - byte <<= 1; + byte <<= srcbpp; dst += dstbpp; } src += srcskip; @@ -674,115 +758,221 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info) } } -static const SDL_BlitFunc bitmap_blit[] = { - (SDL_BlitFunc)NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4 + + +static void Blit1bto1(SDL_BlitInfo *info) { + BlitBto1(info, 1); +} + +static void Blit1bto2(SDL_BlitInfo *info) { + BlitBto2(info, 1); +} + +static void Blit1bto3(SDL_BlitInfo *info) { + BlitBto3(info, 1); +} + +static void Blit1bto4(SDL_BlitInfo *info) { + BlitBto4(info, 1); +} + +static const SDL_BlitFunc bitmap_blit_1b[] = { + (SDL_BlitFunc)NULL, Blit1bto1, Blit1bto2, Blit1bto3, Blit1bto4 }; -static const SDL_BlitFunc colorkey_blit[] = { - (SDL_BlitFunc)NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key +static void Blit1bto1Key(SDL_BlitInfo *info) { + BlitBto1Key(info, 1); +} + +static void Blit1bto2Key(SDL_BlitInfo *info) { + BlitBto2Key(info, 1); +} + +static void Blit1bto3Key(SDL_BlitInfo *info) { + BlitBto3Key(info, 1); +} + +static void Blit1bto4Key(SDL_BlitInfo *info) { + BlitBto4Key(info, 1); +} + +static const SDL_BlitFunc colorkey_blit_1b[] = { + (SDL_BlitFunc)NULL, Blit1bto1Key, Blit1bto2Key, Blit1bto3Key, Blit1bto4Key }; -static void Blit4bto4(SDL_BlitInfo *info) +static void Blit1btoNAlpha(SDL_BlitInfo *info) { - int width = info->dst_w; - int height = info->dst_h; - Uint8 *src = info->src; - Uint32 *dst = (Uint32 *)info->dst; - int srcskip = info->src_skip; - int dstskip = info->dst_skip; - Uint32 *map = (Uint32 *)info->table; - int c; + BlitBtoNAlpha(info, 1); +} - /* Set up some basic variables */ - srcskip += width - (width + 1) / 2; +static void Blit1btoNAlphaKey(SDL_BlitInfo *info) +{ + BlitBtoNAlphaKey(info, 1); +} - while (height--) { - Uint8 byte = 0, bit; - for (c = 0; c < width; ++c) { - if (!(c & 0x1)) { - byte = *src++; - } - bit = (byte & 0xF0) >> 4; - if (1) { - *dst = map[bit]; - } - byte <<= 4; - dst++; - } - src += srcskip; - dst = (Uint32 *)((Uint8 *)dst + dstskip); - } + + +static void Blit2bto1(SDL_BlitInfo *info) { + BlitBto1(info, 2); } -static void Blit4bto4Key(SDL_BlitInfo *info) +static void Blit2bto2(SDL_BlitInfo *info) { + BlitBto2(info, 2); +} + +static void Blit2bto3(SDL_BlitInfo *info) { + BlitBto3(info, 2); +} + +static void Blit2bto4(SDL_BlitInfo *info) { + BlitBto4(info, 2); +} + +static const SDL_BlitFunc bitmap_blit_2b[] = { + (SDL_BlitFunc)NULL, Blit2bto1, Blit2bto2, Blit2bto3, Blit2bto4 +}; + +static void Blit2bto1Key(SDL_BlitInfo *info) { + BlitBto1Key(info, 2); +} + +static void Blit2bto2Key(SDL_BlitInfo *info) { + BlitBto2Key(info, 2); +} + +static void Blit2bto3Key(SDL_BlitInfo *info) { + BlitBto3Key(info, 2); +} + +static void Blit2bto4Key(SDL_BlitInfo *info) { + BlitBto4Key(info, 2); +} + +static const SDL_BlitFunc colorkey_blit_2b[] = { + (SDL_BlitFunc)NULL, Blit2bto1Key, Blit2bto2Key, Blit2bto3Key, Blit2bto4Key +}; + +static void Blit2btoNAlpha(SDL_BlitInfo *info) { - int width = info->dst_w; - int height = info->dst_h; - Uint8 *src = info->src; - Uint32 *dst = (Uint32 *)info->dst; - int srcskip = info->src_skip; - int dstskip = info->dst_skip; - Uint32 ckey = info->colorkey; - Uint32 *map = (Uint32 *)info->table; - int c; + BlitBtoNAlpha(info, 2); +} - /* Set up some basic variables */ - srcskip += width - (width + 1) / 2; +static void Blit2btoNAlphaKey(SDL_BlitInfo *info) +{ + BlitBtoNAlphaKey(info, 2); +} - while (height--) { - Uint8 byte = 0, bit; - for (c = 0; c < width; ++c) { - if (!(c & 0x1)) { - byte = *src++; - } - bit = (byte & 0xF0) >> 4; - if (bit != ckey) { - *dst = map[bit]; - } - byte <<= 4; - dst++; - } - src += srcskip; - dst = (Uint32 *)((Uint8 *)dst + dstskip); - } + + +static void Blit4bto1(SDL_BlitInfo *info) { + BlitBto1(info, 4); +} + +static void Blit4bto2(SDL_BlitInfo *info) { + BlitBto2(info, 4); +} + +static void Blit4bto3(SDL_BlitInfo *info) { + BlitBto3(info, 4); +} + +static void Blit4bto4(SDL_BlitInfo *info) { + BlitBto4(info, 4); +} + +static const SDL_BlitFunc bitmap_blit_4b[] = { + (SDL_BlitFunc)NULL, Blit4bto1, Blit4bto2, Blit4bto3, Blit4bto4 +}; + +static void Blit4bto1Key(SDL_BlitInfo *info) { + BlitBto1Key(info, 4); +} + +static void Blit4bto2Key(SDL_BlitInfo *info) { + BlitBto2Key(info, 4); +} + +static void Blit4bto3Key(SDL_BlitInfo *info) { + BlitBto3Key(info, 4); +} + +static void Blit4bto4Key(SDL_BlitInfo *info) { + BlitBto4Key(info, 4); } +static const SDL_BlitFunc colorkey_blit_4b[] = { + (SDL_BlitFunc)NULL, Blit4bto1Key, Blit4bto2Key, Blit4bto3Key, Blit4bto4Key +}; + +static void Blit4btoNAlpha(SDL_BlitInfo *info) +{ + BlitBtoNAlpha(info, 4); +} + +static void Blit4btoNAlphaKey(SDL_BlitInfo *info) +{ + BlitBtoNAlphaKey(info, 4); +} + + + SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface) { int which; - /* 4bits to 32bits */ - if (surface->format->format == SDL_PIXELFORMAT_INDEX4MSB) { - if (surface->map->dst->format->BytesPerPixel == 4) { - switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { - case 0: - return Blit4bto4; + if (surface->map->dst->format->BitsPerPixel < 8) { + which = 0; + } else { + which = surface->map->dst->format->BytesPerPixel; + } - case SDL_COPY_COLORKEY: - return Blit4bto4Key; - } + if (SDL_PIXELTYPE(surface->format->format) == SDL_PIXELTYPE_INDEX1) { + switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { + case 0: + return bitmap_blit_1b[which]; + + case SDL_COPY_COLORKEY: + return colorkey_blit_1b[which]; + + case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: + return which >= 2 ? Blit1btoNAlpha : (SDL_BlitFunc)NULL; + + case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: + return which >= 2 ? Blit1btoNAlphaKey : (SDL_BlitFunc)NULL; } return NULL; } - if (surface->format->format == SDL_PIXELFORMAT_INDEX1MSB) { - if (surface->map->dst->format->BitsPerPixel < 8) { - which = 0; - } else { - which = surface->map->dst->format->BytesPerPixel; + if (SDL_PIXELTYPE(surface->format->format) == SDL_PIXELTYPE_INDEX2) { + switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { + case 0: + return bitmap_blit_2b[which]; + + case SDL_COPY_COLORKEY: + return colorkey_blit_2b[which]; + + case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: + return which >= 2 ? Blit2btoNAlpha : (SDL_BlitFunc)NULL; + + case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: + return which >= 2 ? Blit2btoNAlphaKey : (SDL_BlitFunc)NULL; } + return NULL; + } + + if (SDL_PIXELTYPE(surface->format->format) == SDL_PIXELTYPE_INDEX4) { switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { case 0: - return bitmap_blit[which]; + return bitmap_blit_4b[which]; case SDL_COPY_COLORKEY: - return colorkey_blit[which]; + return colorkey_blit_4b[which]; case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: - return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc)NULL; + return which >= 2 ? Blit4btoNAlpha : (SDL_BlitFunc)NULL; case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: - return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc)NULL; + return which >= 2 ? Blit4btoNAlphaKey : (SDL_BlitFunc)NULL; } return NULL; } From 05e7dcf8f80724c46d44e736c9b7d3714529c761 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 14:10:32 +0000 Subject: [PATCH 390/725] Support returning <8bpp surfaces in SDL_LoadBMP_RW --- src/video/SDL_bmp.c | 101 +++++++++++----------------------------- test/testcustomcursor.c | 7 ++- test/testutils.c | 7 ++- 3 files changed, 38 insertions(+), 77 deletions(-) diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index c9fdcdbaf5185..c5fe6c7deb01d 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -197,7 +197,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) { SDL_bool was_error = SDL_TRUE; Sint64 fp_offset = 0; - int bmpPitch; int i, pad; SDL_Surface *surface; Uint32 Rmask = 0; @@ -208,7 +207,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) Uint8 *bits; Uint8 *top, *end; SDL_bool topDown; - int ExpandBMP; SDL_bool haveRGBMasks = SDL_FALSE; SDL_bool haveAlphaMask = SDL_FALSE; SDL_bool correctAlpha = SDL_FALSE; @@ -365,14 +363,8 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) goto done; } - /* Expand 1, 2 and 4 bit bitmaps to 8 bits per pixel */ + /* Reject invalid bit depths */ switch (biBitCount) { - case 1: - case 2: - case 4: - ExpandBMP = biBitCount; - biBitCount = 8; - break; case 0: case 3: case 5: @@ -381,7 +373,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) SDL_SetError("%d-bpp BMP images are not supported", biBitCount); goto done; default: - ExpandBMP = 0; break; } @@ -514,89 +505,49 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) } top = (Uint8 *)surface->pixels; end = (Uint8 *)surface->pixels + (surface->h * surface->pitch); - switch (ExpandBMP) { - case 1: - bmpPitch = (biWidth + 7) >> 3; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - case 2: - bmpPitch = (biWidth + 3) >> 2; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - case 4: - bmpPitch = (biWidth + 1) >> 1; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - default: - pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); - break; - } + pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); if (topDown) { bits = top; } else { bits = end - surface->pitch; } while (bits >= top && bits < end) { - switch (ExpandBMP) { - case 1: - case 2: - case 4: - { - Uint8 pixel = 0; - int shift = (8 - ExpandBMP); + if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) { + goto done; + } + if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) { for (i = 0; i < surface->w; ++i) { - if (i % (8 / ExpandBMP) == 0) { - if (!SDL_ReadU8(src, &pixel)) { - goto done; - } - } - bits[i] = (pixel >> shift); if (bits[i] >= biClrUsed) { SDL_SetError("A BMP image contains a pixel with a color out of the palette"); goto done; } - pixel <<= ExpandBMP; - } - } break; - - default: - if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) { - goto done; - } - if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) { - for (i = 0; i < surface->w; ++i) { - if (bits[i] >= biClrUsed) { - SDL_SetError("A BMP image contains a pixel with a color out of the palette"); - goto done; - } - } } + } #if SDL_BYTEORDER == SDL_BIG_ENDIAN - /* Byte-swap the pixels if needed. Note that the 24bpp - case has already been taken care of above. */ - switch (biBitCount) { - case 15: - case 16: - { - Uint16 *pix = (Uint16 *)bits; - for (i = 0; i < surface->w; i++) { - pix[i] = SDL_Swap16(pix[i]); - } - break; + /* Byte-swap the pixels if needed. Note that the 24bpp + case has already been taken care of above. */ + switch (biBitCount) { + case 15: + case 16: + { + Uint16 *pix = (Uint16 *)bits; + for (i = 0; i < surface->w; i++) { + pix[i] = SDL_Swap16(pix[i]); } + break; + } - case 32: - { - Uint32 *pix = (Uint32 *)bits; - for (i = 0; i < surface->w; i++) { - pix[i] = SDL_Swap32(pix[i]); - } - break; - } + case 32: + { + Uint32 *pix = (Uint32 *)bits; + for (i = 0; i < surface->w; i++) { + pix[i] = SDL_Swap32(pix[i]); } -#endif break; } + } +#endif + /* Skip padding bytes, ugh */ if (pad) { Uint8 padbyte; diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index ee90c782dba23..afd74b121135d 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -72,7 +72,12 @@ init_color_cursor(const char *file) SDL_Surface *surface = SDL_LoadBMP(file); if (surface) { if (surface->format->palette) { - SDL_SetSurfaceColorKey(surface, 1, *(Uint8 *)surface->pixels); + const Uint8 bpp = surface->format->BitsPerPixel; + const Uint8 mask = (1 << bpp) - 1; + if (SDL_PIXELORDER(surface->format->format) == SDL_BITMAPORDER_4321) + SDL_SetSurfaceColorKey(surface, 1, (*(Uint8 *)surface->pixels) & mask); + else + SDL_SetSurfaceColorKey(surface, 1, ((*(Uint8 *)surface->pixels) >> (8 - bpp)) & mask); } else { switch (surface->format->BitsPerPixel) { case 15: diff --git a/test/testutils.c b/test/testutils.c index f6eb3780eeaba..e9d505297bb89 100644 --- a/test/testutils.c +++ b/test/testutils.c @@ -116,7 +116,12 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, /* Set transparent pixel as the pixel at (0,0) */ if (transparent) { if (temp->format->palette) { - SDL_SetSurfaceColorKey(temp, SDL_TRUE, *(Uint8 *)temp->pixels); + const Uint8 bpp = temp->format->BitsPerPixel; + const Uint8 mask = (1 << bpp) - 1; + if (SDL_PIXELORDER(temp->format->format) == SDL_BITMAPORDER_4321) + SDL_SetSurfaceColorKey(temp, SDL_TRUE, (*(Uint8 *)temp->pixels) & mask); + else + SDL_SetSurfaceColorKey(temp, SDL_TRUE, ((*(Uint8 *)temp->pixels) >> (8 - bpp)) & mask); } else { switch (temp->format->BitsPerPixel) { case 15: From 5db781cc3d47df639a132533de67769c4f5d73e8 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 18:40:50 +0000 Subject: [PATCH 391/725] Use the correct pixel formats for OpenGL ES on big endian --- src/render/opengles2/SDL_render_gles2.c | 92 +++++++++---------------- 1 file changed, 33 insertions(+), 59 deletions(-) diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index d56568877095f..9b7ca50c43eac 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -730,7 +730,7 @@ static int GLES2_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) { - const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888)); + const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32)); SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first); int i; SDL_Color color; @@ -762,7 +762,7 @@ static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, static int GLES2_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) { - const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888)); + const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32)); int i; GLfloat prevx, prevy; SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first); @@ -822,7 +822,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S float scale_x, float scale_y) { int i; - const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888)); + const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32)); int count = indices ? num_indices : num_vertices; cmd->data.draw.count = count; @@ -1020,50 +1020,50 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo /* Check if we need to do color mapping between the source and render target textures */ if (renderer->target->format != texture->format) { switch (texture->format) { - case SDL_PIXELFORMAT_ARGB8888: + case SDL_PIXELFORMAT_BGRA32: switch (renderer->target->format) { - case SDL_PIXELFORMAT_ABGR8888: - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_RGBA32: + case SDL_PIXELFORMAT_RGBX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; - case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_BGRX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; break; } break; - case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_RGBA32: switch (renderer->target->format) { - case SDL_PIXELFORMAT_ARGB8888: - case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_BGRA32: + case SDL_PIXELFORMAT_BGRX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_RGBX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; break; } break; - case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_BGRX32: switch (renderer->target->format) { - case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_RGBA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; - case SDL_PIXELFORMAT_ARGB8888: + case SDL_PIXELFORMAT_BGRA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; break; - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_RGBX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; } break; - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_RGBX32: switch (renderer->target->format) { - case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_RGBA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; break; - case SDL_PIXELFORMAT_ARGB8888: + case SDL_PIXELFORMAT_BGRA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; break; - case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_BGRX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; } @@ -1091,16 +1091,16 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo } } else { switch (texture->format) { - case SDL_PIXELFORMAT_ARGB8888: + case SDL_PIXELFORMAT_BGRA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; break; - case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_RGBA32: sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; break; - case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_BGRX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; break; - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_RGBX32: sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; break; #if SDL_HAVE_YUV @@ -1153,7 +1153,7 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; - const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888)); + const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32)); #if USE_VERTEX_BUFFER_OBJECTS const int vboidx = data->current_vertex_buffer; @@ -1413,10 +1413,10 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL /* Determine the corresponding GLES texture format params */ switch (texture->format) { - case SDL_PIXELFORMAT_ARGB8888: - case SDL_PIXELFORMAT_ABGR8888: - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_XBGR8888: + case SDL_PIXELFORMAT_BGRA32: + case SDL_PIXELFORMAT_RGBA32: + case SDL_PIXELFORMAT_BGRX32: + case SDL_PIXELFORMAT_RGBX32: format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; @@ -1590,9 +1590,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp) { Uint8 *blob = NULL; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - Uint32 *blob2 = NULL; -#endif Uint8 *src; size_t src_pitch; int y; @@ -1618,33 +1615,10 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff src = blob; } -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - if (format == GL_RGBA) { - int i; - Uint32 *src32 = (Uint32 *)src; - blob2 = (Uint32 *)SDL_malloc(src_pitch * height); - if (!blob2) { - if (blob) { - SDL_free(blob); - } - return SDL_OutOfMemory(); - } - for (i = 0; i < (src_pitch * height) / 4; i++) { - blob2[i] = SDL_Swap32(src32[i]); - } - src = (Uint8 *)blob2; - } -#endif - data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src); if (blob) { SDL_free(blob); } -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - if (blob2) { - SDL_free(blob2); - } -#endif return 0; } @@ -1937,7 +1911,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 pixel_format, void *pixels, int pitch) { GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; - Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; + Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_RGBA32; size_t buflen; void *temp_pixels; int temp_pitch; @@ -2291,10 +2265,10 @@ SDL_RenderDriver GLES2_RenderDriver = { { "opengles2", (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 4, - { SDL_PIXELFORMAT_ARGB8888, - SDL_PIXELFORMAT_ABGR8888, - SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_XBGR8888 }, + { SDL_PIXELFORMAT_RGBA32, + SDL_PIXELFORMAT_BGRA32, + SDL_PIXELFORMAT_BGRX32, + SDL_PIXELFORMAT_RGBX32 }, 0, 0 } }; From 4722269fb62315640cbdbd8916cfc937ee3603d4 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 18 Nov 2023 10:50:39 -0500 Subject: [PATCH 392/725] tests: Print window occluded log events --- src/test/SDL_test_common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 8507807fd8f39..45928628df90d 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1667,6 +1667,9 @@ static void SDLTest_PrintEvent(const SDL_Event *event) case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " display scale changed to %d%%", event->window.windowID, (int)(SDL_GetWindowDisplayScale(SDL_GetWindowFromID(event->window.windowID)) * 100.0f)); break; + case SDL_EVENT_WINDOW_OCCLUDED: + SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " occluded", event->window.windowID); + break; case SDL_EVENT_KEY_DOWN: SDL_Log("SDL EVENT: Keyboard: key pressed in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s", event->key.windowID, From 49d58bc73af79bc893c861d84abf256b79ec9fbe Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Fri, 17 Nov 2023 12:23:06 +0200 Subject: [PATCH 393/725] Cleanup WIN_CreateCursor() code a bit Generate bimap mask from the alpha channel. --- src/video/windows/SDL_windowsmouse.c | 142 ++++++++++++++++----------- 1 file changed, 85 insertions(+), 57 deletions(-) diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 44491d37abcbb..521b8c679221e 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -84,75 +84,103 @@ static SDL_Cursor *WIN_CreateDefaultCursor() return cursor; } -static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) +static HBITMAP CreateColorBitmap(SDL_Surface *surface) { - /* msdn says cursor mask has to be padded out to word alignment. Not sure - if that means machine word or WORD, but this handles either case. */ - const size_t pad = (sizeof(size_t) * 8); /* 32 or 64, or whatever. */ - SDL_Cursor *cursor; - HICON hicon; - HICON hcursor; - HDC hdc; - BITMAPV4HEADER bmh; - LPVOID pixels; - LPVOID maskbits; - size_t maskbitslen; - SDL_bool isstack; - ICONINFO ii; + HBITMAP bitmap; + BITMAPINFO bi; + void *pixels; + + SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); + + SDL_zero(bi); + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = surface->w; + bi.bmiHeader.biHeight = -surface->h; /* Invert height to make the top-down DIB. */ + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + + bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pixels, NULL, 0); + if (!bitmap || !pixels) { + WIN_SetError("CreateDIBSection()"); + return NULL; + } + + SDL_memcpy(pixels, surface->pixels, surface->pitch * surface->h); + + return bitmap; +} - SDL_zero(bmh); - bmh.bV4Size = sizeof(bmh); - bmh.bV4Width = surface->w; - bmh.bV4Height = -surface->h; /* Invert the image */ - bmh.bV4Planes = 1; - bmh.bV4BitCount = 32; - bmh.bV4V4Compression = BI_BITFIELDS; - bmh.bV4AlphaMask = 0xFF000000; - bmh.bV4RedMask = 0x00FF0000; - bmh.bV4GreenMask = 0x0000FF00; - bmh.bV4BlueMask = 0x000000FF; - - maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h; - maskbits = SDL_small_alloc(Uint8, maskbitslen, &isstack); - if (!maskbits) { +static HBITMAP CreateMaskBitmap(SDL_Surface *surface) +{ + HBITMAP bitmap; + void *pixels; + int x, y; + Uint8 *src, *dst; + const int pitch = (((surface->w + 15) & ~15) / 8); + static const unsigned char masks[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + + SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); + + pixels = SDL_stack_alloc(Uint8, pitch * surface->h); + if (!pixels) { SDL_OutOfMemory(); return NULL; } - /* AND the cursor against full bits: no change. We already have alpha. */ - SDL_memset(maskbits, 0xFF, maskbitslen); + /* Make the entire mask completely transparent. */ + SDL_memset(pixels, 0xff, pitch * surface->h); + + SDL_LockSurface(surface); + + src = surface->pixels; + dst = pixels; + for (y = 0; y < surface->h; y++, src += surface->pitch, dst += pitch) { + for (x = 0; x < surface->w; x++) { + Uint8 alpha = src[x * 4 + 3]; + if (alpha != 0) { + /* Reset bit of an opaque pixel. */ + dst[x >> 3] &= ~masks[x & 7]; + } + } + } + + SDL_UnlockSurface(surface); + + bitmap = CreateBitmap(surface->w, surface->h, 1, 1, pixels); + SDL_stack_free(pixels); + if (!bitmap) { + WIN_SetError("CreateBitmap()"); + return NULL; + } + + return bitmap; +} + +static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) +{ + HCURSOR hcursor; + SDL_Cursor *cursor; + ICONINFO ii; - hdc = GetDC(NULL); SDL_zero(ii); ii.fIcon = FALSE; ii.xHotspot = (DWORD)hot_x; ii.yHotspot = (DWORD)hot_y; - ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0); - ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits); - ReleaseDC(NULL, hdc); - SDL_small_free(maskbits, isstack); + ii.hbmColor = CreateColorBitmap(surface); + ii.hbmMask = CreateMaskBitmap(surface); - SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); - SDL_assert(surface->pitch == surface->w * 4); - SDL_memcpy(pixels, surface->pixels, (size_t)surface->h * surface->pitch); + if (!ii.hbmColor || !ii.hbmMask) { + return NULL; + } - hicon = CreateIconIndirect(&ii); + hcursor = CreateIconIndirect(&ii); DeleteObject(ii.hbmColor); DeleteObject(ii.hbmMask); - if (!hicon) { - WIN_SetError("CreateIconIndirect()"); - return NULL; - } - - /* The cursor returned by CreateIconIndirect does not respect system cursor size - preference, use CopyImage to duplicate the cursor with desired sizes */ - hcursor = CopyImage(hicon, IMAGE_CURSOR, surface->w, surface->h, 0); - DestroyIcon(hicon); - if (!hcursor) { - WIN_SetError("CopyImage()"); + WIN_SetError("CreateIconIndirect()"); return NULL; } @@ -160,7 +188,7 @@ static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) if (cursor) { cursor->driverdata = hcursor; } else { - DestroyIcon(hcursor); + DestroyCursor(hcursor); SDL_OutOfMemory(); } @@ -227,11 +255,11 @@ static SDL_Cursor *WIN_CreateSystemCursor(SDL_SystemCursor id) cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { - HICON hicon; + HCURSOR hcursor; - hicon = LoadCursor(NULL, name); + hcursor = LoadCursor(NULL, name); - cursor->driverdata = hicon; + cursor->driverdata = hcursor; } else { SDL_OutOfMemory(); } @@ -241,9 +269,9 @@ static SDL_Cursor *WIN_CreateSystemCursor(SDL_SystemCursor id) static void WIN_FreeCursor(SDL_Cursor *cursor) { - HICON hicon = (HICON)cursor->driverdata; + HCURSOR hcursor = (HCURSOR)cursor->driverdata; - DestroyIcon(hicon); + DestroyCursor(hcursor); SDL_free(cursor); } From 30a2291d594a1ccb0b67e2bff2d805c531d2f47f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 20 Nov 2023 08:46:12 -0800 Subject: [PATCH 394/725] Fixed compatibility with sdl2-compat (thanks @sezero!) --- include/SDL3/SDL_pixels.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 02bae04101e76..3d39e2e982598 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -88,7 +88,6 @@ typedef enum { SDL_PIXELTYPE_UNKNOWN, SDL_PIXELTYPE_INDEX1, - SDL_PIXELTYPE_INDEX2, SDL_PIXELTYPE_INDEX4, SDL_PIXELTYPE_INDEX8, SDL_PIXELTYPE_PACKED8, @@ -98,7 +97,9 @@ typedef enum SDL_PIXELTYPE_ARRAYU16, SDL_PIXELTYPE_ARRAYU32, SDL_PIXELTYPE_ARRAYF16, - SDL_PIXELTYPE_ARRAYF32 + SDL_PIXELTYPE_ARRAYF32, + /* appended at the end for compatibility with sdl2-compat: */ + SDL_PIXELTYPE_INDEX2 } SDL_PixelType; /** Bitmap pixel order, high bit -> low bit. */ From 5b1c68c2f3cf487b7f15a41b45239a5b33c8222b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 20 Nov 2023 15:10:30 -0500 Subject: [PATCH 395/725] testshader: Don't make local variables with the same name as GL entry points. Reference Issue #2706. (cherry picked from commit cb5b8c97472ed1c759bb6934372e3c3ff4aad8f3) --- test/testshader.c | 118 +++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/test/testshader.c b/test/testshader.c index 3cb552fca4b51..e28c12366f8f5 100644 --- a/test/testshader.c +++ b/test/testshader.c @@ -115,36 +115,36 @@ static ShaderData shaders[NUM_SHADERS] = { "}" }, }; -static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; -static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; -static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; -static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; -static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; -static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; -static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; -static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; -static PFNGLUNIFORM1IARBPROC glUniform1iARB; -static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; +static PFNGLATTACHOBJECTARBPROC pglAttachObjectARB; +static PFNGLCOMPILESHADERARBPROC pglCompileShaderARB; +static PFNGLCREATEPROGRAMOBJECTARBPROC pglCreateProgramObjectARB; +static PFNGLCREATESHADEROBJECTARBPROC pglCreateShaderObjectARB; +static PFNGLDELETEOBJECTARBPROC pglDeleteObjectARB; +static PFNGLGETINFOLOGARBPROC pglGetInfoLogARB; +static PFNGLGETOBJECTPARAMETERIVARBPROC pglGetObjectParameterivARB; +static PFNGLGETUNIFORMLOCATIONARBPROC pglGetUniformLocationARB; +static PFNGLLINKPROGRAMARBPROC pglLinkProgramARB; +static PFNGLSHADERSOURCEARBPROC pglShaderSourceARB; +static PFNGLUNIFORM1IARBPROC pglUniform1iARB; +static PFNGLUSEPROGRAMOBJECTARBPROC pglUseProgramObjectARB; static SDL_bool CompileShader(GLhandleARB shader, const char *source) { GLint status = 0; - glShaderSourceARB(shader, 1, &source, NULL); - glCompileShaderARB(shader); - glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); + pglShaderSourceARB(shader, 1, &source, NULL); + pglCompileShaderARB(shader); + pglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); if (status == 0) { GLint length = 0; char *info; - glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + pglGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); if (!info) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { - glGetInfoLogARB(shader, length, NULL, info); + pglGetInfoLogARB(shader, length, NULL, info); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info); SDL_free(info); } @@ -158,21 +158,21 @@ static SDL_bool LinkProgram(ShaderData *data) { GLint status = 0; - glAttachObjectARB(data->program, data->vert_shader); - glAttachObjectARB(data->program, data->frag_shader); - glLinkProgramARB(data->program); + pglAttachObjectARB(data->program, data->vert_shader); + pglAttachObjectARB(data->program, data->frag_shader); + pglLinkProgramARB(data->program); - glGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status); + pglGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status); if (status == 0) { GLint length = 0; char *info; - glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + pglGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); if (!info) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { - glGetInfoLogARB(data->program, length, NULL, info); + pglGetInfoLogARB(data->program, length, NULL, info); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info); SDL_free(info); } @@ -191,16 +191,16 @@ static SDL_bool CompileShaderProgram(ShaderData *data) glGetError(); /* Create one program object to rule them all */ - data->program = glCreateProgramObjectARB(); + data->program = pglCreateProgramObjectARB(); /* Create the vertex shader */ - data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + data->vert_shader = pglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); if (!CompileShader(data->vert_shader, data->vert_source)) { return SDL_FALSE; } /* Create the fragment shader */ - data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + data->frag_shader = pglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); if (!CompileShader(data->frag_shader, data->frag_source)) { return SDL_FALSE; } @@ -211,16 +211,16 @@ static SDL_bool CompileShaderProgram(ShaderData *data) } /* Set up some uniform variables */ - glUseProgramObjectARB(data->program); + pglUseProgramObjectARB(data->program); for (i = 0; i < num_tmus_bound; ++i) { char tex_name[5]; (void)SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i); - location = glGetUniformLocationARB(data->program, tex_name); + location = pglGetUniformLocationARB(data->program, tex_name); if (location >= 0) { - glUniform1iARB(location, i); + pglUniform1iARB(location, i); } } - glUseProgramObjectARB(0); + pglUseProgramObjectARB(0); return (glGetError() == GL_NO_ERROR); } @@ -228,9 +228,9 @@ static SDL_bool CompileShaderProgram(ShaderData *data) static void DestroyShaderProgram(ShaderData *data) { if (shaders_supported) { - glDeleteObjectARB(data->vert_shader); - glDeleteObjectARB(data->frag_shader); - glDeleteObjectARB(data->program); + pglDeleteObjectARB(data->vert_shader); + pglDeleteObjectARB(data->frag_shader); + pglDeleteObjectARB(data->program); } } @@ -244,30 +244,30 @@ static SDL_bool InitShaders(void) SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") && SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") && SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) { - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); - glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); - glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); - if (glAttachObjectARB && - glCompileShaderARB && - glCreateProgramObjectARB && - glCreateShaderObjectARB && - glDeleteObjectARB && - glGetInfoLogARB && - glGetObjectParameterivARB && - glGetUniformLocationARB && - glLinkProgramARB && - glShaderSourceARB && - glUniform1iARB && - glUseProgramObjectARB) { + pglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); + pglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); + pglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); + pglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); + pglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); + pglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); + pglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); + pglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); + pglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); + pglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); + pglUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); + pglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); + if (pglAttachObjectARB && + pglCompileShaderARB && + pglCreateProgramObjectARB && + pglCreateShaderObjectARB && + pglDeleteObjectARB && + pglGetInfoLogARB && + pglGetObjectParameterivARB && + pglGetUniformLocationARB && + pglLinkProgramARB && + pglShaderSourceARB && + pglUniform1iARB && + pglUseProgramObjectARB) { shaders_supported = SDL_TRUE; } } @@ -418,7 +418,7 @@ static void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord) glBindTexture(GL_TEXTURE_2D, texture); glColor3f(1.0f, 1.0f, 1.0f); if (shaders_supported) { - glUseProgramObjectARB(shaders[current_shader].program); + pglUseProgramObjectARB(shaders[current_shader].program); } glBegin(GL_QUADS); /* start drawing a polygon (4 sided) */ @@ -433,7 +433,7 @@ static void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord) glEnd(); /* done with the polygon */ if (shaders_supported) { - glUseProgramObjectARB(0); + pglUseProgramObjectARB(0); } glDisable(GL_TEXTURE_2D); From b76f8de298fe5476b77fa562df07b57d5837bab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionu=C8=9B=20Leonte?= Date: Mon, 20 Nov 2023 23:33:11 +0200 Subject: [PATCH 396/725] Hit testing tweaks for X11 and Wayland (#8582) Hit testing on X11 and Wayland should now behave more like it does on Windows - the current active zone is tracked on mouse motion events and the cursor is changed accordingly when hovering a "special" zone (such as the resize handles). --- src/video/wayland/SDL_waylandevents.c | 40 +++++++++++++------ src/video/wayland/SDL_waylandmouse.c | 55 ++++++++++++++++++++------- src/video/wayland/SDL_waylandmouse.h | 1 + src/video/wayland/SDL_waylandwindow.c | 2 + src/video/wayland/SDL_waylandwindow.h | 2 + src/video/x11/SDL_x11events.c | 26 ++++++++++--- src/video/x11/SDL_x11events.h | 3 +- src/video/x11/SDL_x11mouse.c | 28 ++++++++++++++ src/video/x11/SDL_x11mouse.h | 1 + src/video/x11/SDL_x11window.c | 1 + src/video/x11/SDL_x11window.h | 1 + src/video/x11/SDL_x11xinput2.c | 10 ++--- 12 files changed, 134 insertions(+), 36 deletions(-) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 1a954c59ccd4f..e8eb58be2dad5 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -32,6 +32,7 @@ #include "SDL_waylandvideo.h" #include "SDL_waylandevents_c.h" #include "SDL_waylandwindow.h" +#include "SDL_waylandmouse.h" #include "pointer-constraints-unstable-v1-client-protocol.h" #include "relative-pointer-unstable-v1-client-protocol.h" @@ -490,13 +491,26 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { struct SDL_WaylandInput *input = data; - SDL_WindowData *window = input->pointer_focus; + SDL_WindowData *window_data = input->pointer_focus; + SDL_Window *window = window_data ? window_data->sdlwindow : NULL; + input->sx_w = sx_w; input->sy_w = sy_w; if (input->pointer_focus) { - float sx = (float)(wl_fixed_to_double(sx_w) * window->pointer_scale_x); - float sy = (float)(wl_fixed_to_double(sy_w) * window->pointer_scale_y); - SDL_SendMouseMotion(Wayland_GetPointerTimestamp(input, time), window->sdlwindow, 0, 0, sx, sy); + float sx = (float)(wl_fixed_to_double(sx_w) * window_data->pointer_scale_x); + float sy = (float)(wl_fixed_to_double(sy_w) * window_data->pointer_scale_y); + SDL_SendMouseMotion(Wayland_GetPointerTimestamp(input, time), window_data->sdlwindow, 0, 0, sx, sy); + } + + if (window && window->hit_test) { + const SDL_Point point = { wl_fixed_to_int(sx_w), wl_fixed_to_int(sy_w) }; + SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); + if (rc == window_data->hit_test_result) { + return; + } + + Wayland_SetHitTestCursor(rc); + window_data->hit_test_result = rc; } } @@ -540,7 +554,7 @@ static void pointer_handle_enter(void *data, struct wl_pointer *pointer, /* If the cursor was changed while our window didn't have pointer * focus, we might need to trigger another call to * wl_pointer_set_cursor() for the new cursor to be displayed. */ - SDL_SetCursor(NULL); + Wayland_SetHitTestCursor(window->hit_test_result); } } @@ -580,9 +594,6 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data, SDL_Window *window = window_data->sdlwindow; if (window->hit_test) { - const SDL_Point point = { wl_fixed_to_int(sx_w), wl_fixed_to_int(sy_w) }; - const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); - static const uint32_t directions[] = { XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT, @@ -599,12 +610,14 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data, }; #endif - switch (rc) { + switch (window_data->hit_test_result) { case SDL_HITTEST_DRAGGABLE: #ifdef HAVE_LIBDECOR_H if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (window_data->shell_surface.libdecor.frame) { - libdecor_frame_move(window_data->shell_surface.libdecor.frame, seat, serial); + libdecor_frame_move(window_data->shell_surface.libdecor.frame, + seat, + serial); } } else #endif @@ -628,7 +641,10 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data, #ifdef HAVE_LIBDECOR_H if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (window_data->shell_surface.libdecor.frame) { - libdecor_frame_resize(window_data->shell_surface.libdecor.frame, seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]); + libdecor_frame_resize(window_data->shell_surface.libdecor.frame, + seat, + serial, + directions_libdecor[window_data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]); } } else #endif @@ -637,7 +653,7 @@ static SDL_bool ProcessHitTest(SDL_WindowData *window_data, xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel, seat, serial, - directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]); + directions[window_data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]); } } return SDL_TRUE; diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 8c1bae80fce53..037df7bce6332 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -41,6 +41,8 @@ #include "../../SDL_hints_c.h" +static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1]; + static int Wayland_SetRelativeMouseMode(SDL_bool enabled); typedef struct @@ -315,43 +317,44 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa vdata->cursor_themes[vdata->num_cursor_themes++].theme = theme; } - /* Next, find the cursor from the theme... */ + /* Next, find the cursor from the theme. Names taken from: */ + /* https://www.freedesktop.org/wiki/Specifications/cursor-spec/ */ switch (cdata->system_cursor) { case SDL_SYSTEM_CURSOR_ARROW: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "left_ptr"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "default"); break; case SDL_SYSTEM_CURSOR_IBEAM: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "xterm"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "text"); break; case SDL_SYSTEM_CURSOR_WAIT: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "watch"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "wait"); break; case SDL_SYSTEM_CURSOR_CROSSHAIR: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "tcross"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "crosshair"); break; case SDL_SYSTEM_CURSOR_WAITARROW: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "watch"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "progress"); break; case SDL_SYSTEM_CURSOR_SIZENWSE: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "top_left_corner"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nw-resize"); break; case SDL_SYSTEM_CURSOR_SIZENESW: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "top_right_corner"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ne-resize"); break; case SDL_SYSTEM_CURSOR_SIZEWE: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "sb_h_double_arrow"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "e-resize"); break; case SDL_SYSTEM_CURSOR_SIZENS: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "sb_v_double_arrow"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "n-resize"); break; case SDL_SYSTEM_CURSOR_SIZEALL: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "fleur"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "fleur"); // ? break; case SDL_SYSTEM_CURSOR_NO: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "pirate"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "not-allowed"); break; case SDL_SYSTEM_CURSOR_HAND: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "hand2"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "pointer"); break; default: SDL_assert(0); @@ -771,6 +774,23 @@ void Wayland_InitMouse(void) input->relative_mode_override = SDL_FALSE; input->cursor_visible = SDL_TRUE; + SDL_HitTestResult r = SDL_HITTEST_NORMAL; + while (r <= SDL_HITTEST_RESIZE_LEFT) { + switch (r) { + case SDL_HITTEST_NORMAL: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; + case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; + case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; + case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; + case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; + case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; + case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; + case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; + case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + } + r++; + } + #ifdef SDL_USE_LIBDBUS Wayland_DBusInitCursorProperties(d); #endif @@ -795,4 +815,13 @@ void Wayland_FiniMouse(SDL_VideoData *data) Wayland_EmulateMouseWarpChanged, input); } +void Wayland_SetHitTestCursor(SDL_HitTestResult rc) +{ + if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) { + SDL_SetCursor(NULL); + } else { + Wayland_ShowCursor(sys_cursors[rc]); + } +} + #endif /* SDL_VIDEO_DRIVER_WAYLAND */ diff --git a/src/video/wayland/SDL_waylandmouse.h b/src/video/wayland/SDL_waylandmouse.h index ac194af0c064e..0f63d11e48e98 100644 --- a/src/video/wayland/SDL_waylandmouse.h +++ b/src/video/wayland/SDL_waylandmouse.h @@ -26,6 +26,7 @@ extern void Wayland_InitMouse(void); extern void Wayland_FiniMouse(SDL_VideoData *data); +extern void Wayland_SetHitTestCursor(SDL_HitTestResult rc); #if 0 /* TODO RECONNECT: See waylandvideo.c for more information! */ extern void Wayland_RecreateCursors(void); #endif /* 0 */ diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 043571aaceb67..ad2ce5c41fedc 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2109,6 +2109,8 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert SDL_SetProperty(props, "SDL.window.wayland.surface", data->surface); SDL_SetProperty(props, "SDL.window.wayland.egl_window", data->egl_window); + data->hit_test_result = SDL_HITTEST_NORMAL; + return 0; } diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index e53fe31680669..0821cd6163901 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -121,6 +121,8 @@ struct SDL_WindowData SDL_bool is_fullscreen; SDL_bool in_fullscreen_transition; SDL_bool fullscreen_was_positioned; + + SDL_HitTestResult hit_test_result; }; extern void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 52ef9575ae8ef..512b69a272251 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -559,13 +559,26 @@ static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *d X11_XSync(display, 0); } -SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y) +SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result) +{ + SDL_Window *window = data->window; + if (!window->hit_test) return SDL_FALSE; + const SDL_Point point = { x, y }; + SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); + if (!force_new_result && rc == data->hit_test_result) { + return SDL_TRUE; + } + X11_SetHitTestCursor(rc); + data->hit_test_result = rc; + return SDL_TRUE; +} + +SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y) { SDL_Window *window = data->window; if (window->hit_test) { const SDL_Point point = { x, y }; - const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); static const int directions[] = { _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP, _NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT, @@ -573,7 +586,7 @@ SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT }; - switch (rc) { + switch (data->hit_test_result) { case SDL_HITTEST_DRAGGABLE: InitiateWindowMove(_this, data, &point); return SDL_TRUE; @@ -586,7 +599,7 @@ SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, case SDL_HITTEST_RESIZE_BOTTOM: case SDL_HITTEST_RESIZE_BOTTOMLEFT: case SDL_HITTEST_RESIZE_LEFT: - InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]); + InitiateWindowResize(_this, data, &point, directions[data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]); return SDL_TRUE; default: @@ -819,7 +832,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, i } else { SDL_bool ignore_click = SDL_FALSE; if (button == Button1) { - if (X11_ProcessHitTest(_this, windowdata, x, y)) { + if (X11_TriggerHitTestAction(_this, windowdata, x, y)) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); return; /* don't pass this event on to app. */ } @@ -1078,6 +1091,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) /* We ungrab in LeaveNotify, so we may need to grab again here */ SDL_UpdateWindowGrab(data->window); + + X11_ProcessHitTest(_this, data, mouse->last_x, mouse->last_y, SDL_TRUE); } break; /* Losing mouse coverage? */ case LeaveNotify: @@ -1483,6 +1498,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) printf("window %p: X11 motion: %d,%d\n", data, xevent->xmotion.x, xevent->xmotion.y); #endif + X11_ProcessHitTest(_this, data, (float)xevent->xmotion.x, (float)xevent->xmotion.y, SDL_FALSE); SDL_SendMouseMotion(0, data->window, 0, 0, (float)xevent->xmotion.x, (float)xevent->xmotion.y); } } break; diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index 02c666540514e..4aadd290bf8d7 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -32,6 +32,7 @@ extern void X11_GetBorderValues(SDL_WindowData *data); extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time); extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button); extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window); -extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y); +extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result); +extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y); #endif /* SDL_x11events_h_ */ diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 3f2d3d3dd9f29..895bed9232289 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -31,6 +31,8 @@ /* FIXME: Find a better place to put this... */ static Cursor x11_empty_cursor = None; +static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1]; + static Display *GetDisplay(void) { return SDL_GetVideoDevice()->driverdata->display; @@ -472,6 +474,23 @@ void X11_InitMouse(SDL_VideoDevice *_this) mouse->CaptureMouse = X11_CaptureMouse; mouse->GetGlobalMouseState = X11_GetGlobalMouseState; + SDL_HitTestResult r = SDL_HITTEST_NORMAL; + while (r <= SDL_HITTEST_RESIZE_LEFT) { + switch (r) { + case SDL_HITTEST_NORMAL: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; + case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; + case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; + case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; + case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; + case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; + case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; + case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; + case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + } + r++; + } + SDL_SetDefaultCursor(X11_CreateDefaultCursor()); } @@ -490,4 +509,13 @@ void X11_QuitMouse(SDL_VideoDevice *_this) X11_DestroyEmptyCursor(); } +void X11_SetHitTestCursor(SDL_HitTestResult rc) +{ + if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) { + SDL_SetCursor(NULL); + } else { + X11_ShowCursor(sys_cursors[rc]); + } +} + #endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/src/video/x11/SDL_x11mouse.h b/src/video/x11/SDL_x11mouse.h index 96e0f93195d50..902f9b7791d9c 100644 --- a/src/video/x11/SDL_x11mouse.h +++ b/src/video/x11/SDL_x11mouse.h @@ -35,5 +35,6 @@ typedef struct SDL_XInput2DeviceInfo extern void X11_InitMouse(SDL_VideoDevice *_this); extern void X11_QuitMouse(SDL_VideoDevice *_this); +extern void X11_SetHitTestCursor(SDL_HitTestResult rc); #endif /* SDL_x11mouse_h_ */ diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index e17113cf25b57..c750ea76090a2 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -317,6 +317,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) } data->window = window; data->xwindow = w; + data->hit_test_result = SDL_HITTEST_NORMAL; #ifdef X_HAVE_UTF8_STRING if (SDL_X11_HAVE_UTF8 && videodata->im) { diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 56bc6193b63de..d1f5b8b67a099 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -79,6 +79,7 @@ struct SDL_WindowData PointerBarrier barrier[4]; SDL_Rect barrier_rect; #endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ + SDL_HitTestResult hit_test_result; }; extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags); diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index 68eaaf5d889d9..ef97d33c31c3c 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -395,11 +395,10 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) /* button 1 is the pen tip */ if (pressed && SDL_PenPerformHitTest()) { /* Check whether we should handle window resize / move events */ - const SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event); - - if (X11_ProcessHitTest(_this, windowdata, pen->last.x, pen->last.y)) { - SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); - return 1; /* Don't pass on this event */ + SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event); + if (windowdata && X11_TriggerHitTestAction(_this, windowdata, pen->last.x, pen->last.y)) { + SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); + return 1; /* Don't pass on this event */ } } SDL_SendPenTipEvent(0, pen->header.id, @@ -467,6 +466,7 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) if (!mouse->relative_mode || mouse->relative_mode_warp) { SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); if (window) { + X11_ProcessHitTest(_this, window->driverdata, (float)xev->event_x, (float)xev->event_y, SDL_FALSE); SDL_SendMouseMotion(0, window, 0, 0, (float)xev->event_x, (float)xev->event_y); } } From 91e122316c753be28706fb82988bc6de1caf253c Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Tue, 21 Nov 2023 14:09:41 +0200 Subject: [PATCH 397/725] Use SDL_small_alloc() instead of SDL_stack_alloc() in CreateMaskBitmap() --- src/video/windows/SDL_windowsmouse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 521b8c679221e..dff79343f9eca 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -114,15 +114,16 @@ static HBITMAP CreateColorBitmap(SDL_Surface *surface) static HBITMAP CreateMaskBitmap(SDL_Surface *surface) { HBITMAP bitmap; + SDL_bool isstack; void *pixels; int x, y; Uint8 *src, *dst; - const int pitch = (((surface->w + 15) & ~15) / 8); + const int pitch = ((surface->w + 15) & ~15) / 8; static const unsigned char masks[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); - pixels = SDL_stack_alloc(Uint8, pitch * surface->h); + pixels = SDL_small_alloc(Uint8, pitch * surface->h, &isstack); if (!pixels) { SDL_OutOfMemory(); return NULL; @@ -148,7 +149,7 @@ static HBITMAP CreateMaskBitmap(SDL_Surface *surface) SDL_UnlockSurface(surface); bitmap = CreateBitmap(surface->w, surface->h, 1, 1, pixels); - SDL_stack_free(pixels); + SDL_small_free(pixels, isstack); if (!bitmap) { WIN_SetError("CreateBitmap()"); return NULL; From 5e9b0820f34f2db2b713f6fad76f11380f3a5285 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Mon, 20 Nov 2023 21:41:18 -0600 Subject: [PATCH 398/725] Add cursors for X11/Wayland window resizing --- .../main/java/org/libsdl/app/SDLActivity.java | 32 +++++++++++++++ include/SDL3/SDL_mouse.h | 8 ++++ src/video/cocoa/SDL_cocoamouse.m | 24 +++++++++++ src/video/emscripten/SDL_emscriptenmouse.c | 24 +++++++++++ src/video/haiku/SDL_bvideo.cc | 8 ++++ src/video/wayland/SDL_waylandmouse.c | 40 +++++++++++++++---- src/video/windows/SDL_windowsmouse.c | 24 +++++++++++ src/video/winrt/SDL_winrtmouse.cpp | 24 +++++++++++ src/video/x11/SDL_x11mouse.c | 40 +++++++++++++++---- test/testcustomcursor.c | 24 +++++++++++ 10 files changed, 232 insertions(+), 16 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 82ba742a429c2..676faee36e9a7 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -180,6 +180,14 @@ public static void debugSource(int sources, String prefix) { private static final int SDL_SYSTEM_CURSOR_SIZEALL = 9; private static final int SDL_SYSTEM_CURSOR_NO = 10; private static final int SDL_SYSTEM_CURSOR_HAND = 11; + private static final int SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT = 12; + private static final int SDL_SYSTEM_CURSOR_WINDOW_TOP = 13; + private static final int SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT = 14; + private static final int SDL_SYSTEM_CURSOR_WINDOW_RIGHT = 15; + private static final int SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT = 16; + private static final int SDL_SYSTEM_CURSOR_WINDOW_BOTTOM = 17; + private static final int SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT = 18; + private static final int SDL_SYSTEM_CURSOR_WINDOW_LEFT = 19; protected static final int SDL_ORIENTATION_UNKNOWN = 0; protected static final int SDL_ORIENTATION_LANDSCAPE = 1; @@ -1831,6 +1839,30 @@ public static boolean setSystemCursor(int cursorID) { case SDL_SYSTEM_CURSOR_HAND: cursor_type = 1002; //PointerIcon.TYPE_HAND; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + cursor_type = 1017; //PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + cursor_type = 1015; //PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + cursor_type = 1016; //PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + cursor_type = 1014; //PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + cursor_type = 1017; //PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + cursor_type = 1015; //PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + cursor_type = 1016; //PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + cursor_type = 1014; //PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW; + break; } if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) { try { diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index 51751df029313..c00d769885f12 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -59,6 +59,14 @@ typedef enum SDL_SYSTEM_CURSOR_SIZEALL, /**< Four pointed arrow pointing north, south, east, and west */ SDL_SYSTEM_CURSOR_NO, /**< Slashed circle or crossbones */ SDL_SYSTEM_CURSOR_HAND, /**< Hand */ + SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT, /**< Window resize top-left (or SIZENWSE) */ + SDL_SYSTEM_CURSOR_WINDOW_TOP, /**< Window resize top (or SIZENS) */ + SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT, /**< Window resize top-right (or SIZENESW) */ + SDL_SYSTEM_CURSOR_WINDOW_RIGHT, /**< Window resize right (or SIZEWE) */ + SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT, /**< Window resize bottom-right (or SIZENWSE) */ + SDL_SYSTEM_CURSOR_WINDOW_BOTTOM, /**< Window resize bottom (or SIZENS) */ + SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT, /**< Window resize bottom-left (or SIZENESW) */ + SDL_SYSTEM_CURSOR_WINDOW_LEFT, /**< Window resize left (or SIZEWE) */ SDL_NUM_SYSTEM_CURSORS } SDL_SystemCursor; diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index 2231ce7dcf393..e570397ee2521 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -188,6 +188,30 @@ + (NSCursor *)invisibleCursor case SDL_SYSTEM_CURSOR_HAND: nscursor = [NSCursor pointingHandCursor]; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + nscursor = LoadHiddenSystemCursor(@"resizenorthwestsoutheast", @selector(closedHandCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + nscursor = LoadHiddenSystemCursor(@"resizenorthsouth", @selector(resizeUpDownCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + nscursor = LoadHiddenSystemCursor(@"resizenortheastsouthwest", @selector(closedHandCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + nscursor = LoadHiddenSystemCursor(@"resizeeastwest", @selector(resizeLeftRightCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + nscursor = LoadHiddenSystemCursor(@"resizenorthwestsoutheast", @selector(closedHandCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + nscursor = LoadHiddenSystemCursor(@"resizenorthsouth", @selector(resizeUpDownCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + nscursor = LoadHiddenSystemCursor(@"resizenortheastsouthwest", @selector(closedHandCursor)); + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + nscursor = LoadHiddenSystemCursor(@"resizeeastwest", @selector(resizeLeftRightCursor)); + break; default: SDL_assert(!"Unknown system cursor"); return NULL; diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c index 1913c068698b9..2362d88373e0a 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.c +++ b/src/video/emscripten/SDL_emscriptenmouse.c @@ -161,6 +161,30 @@ static SDL_Cursor *Emscripten_CreateSystemCursor(SDL_SystemCursor id) case SDL_SYSTEM_CURSOR_HAND: cursor_name = "pointer"; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + cursor_name = "nwse-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + cursor_name = "ns-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + cursor_name = "nesw-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + cursor_name = "ew-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + cursor_name = "nwse-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + cursor_name = "ns-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + cursor_name = "nesw-resize"; + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + cursor_name = "ew-resize"; + break; default: SDL_assert(0); return NULL; diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 21d1b864cb8d5..6e881a6e9bf94 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -152,6 +152,14 @@ static SDL_Cursor * HAIKU_CreateSystemCursor(SDL_SystemCursor id) case SDL_SYSTEM_CURSOR_SIZEALL: cursorId = B_CURSOR_ID_MOVE; break; case SDL_SYSTEM_CURSOR_NO: cursorId = B_CURSOR_ID_NOT_ALLOWED; break; case SDL_SYSTEM_CURSOR_HAND: cursorId = B_CURSOR_ID_FOLLOW_LINK; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: cursorId = B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: cursorId = B_CURSOR_ID_RESIZE_NORTH_SOUTH; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: cursorId = B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST; break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: cursorId = B_CURSOR_ID_RESIZE_EAST_WEST; break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: cursorId = B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST; break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: cursorId = B_CURSOR_ID_RESIZE_NORTH_SOUTH; break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: cursorId = B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST; break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: cursorId = B_CURSOR_ID_RESIZE_EAST_WEST; break; } cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor)); diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 037df7bce6332..de209e776c524 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -356,6 +356,30 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa case SDL_SYSTEM_CURSOR_HAND: cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "pointer"); break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nw-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "n-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ne-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "e-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "se-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "s-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "sw-resize"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "w-resize"); + break; default: SDL_assert(0); return SDL_FALSE; @@ -779,14 +803,14 @@ void Wayland_InitMouse(void) switch (r) { case SDL_HITTEST_NORMAL: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; - case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; - case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; - case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; - case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; - case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; - case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; - case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; - case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT); break; + case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOP); break; + case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT); break; + case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_RIGHT); break; + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT); break; + case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOM); break; + case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT); break; + case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = Wayland_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_LEFT); break; } r++; } diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index dff79343f9eca..6bd9515b68562 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -252,6 +252,30 @@ static SDL_Cursor *WIN_CreateSystemCursor(SDL_SystemCursor id) case SDL_SYSTEM_CURSOR_HAND: name = IDC_HAND; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + name = IDC_SIZENWSE; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + name = IDC_SIZENS; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + name = IDC_SIZENESW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + name = IDC_SIZEWE; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + name = IDC_SIZENWSE; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + name = IDC_SIZENS; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + name = IDC_SIZENESW; + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + name = IDC_SIZEWE; + break; } cursor = SDL_calloc(1, sizeof(*cursor)); diff --git a/src/video/winrt/SDL_winrtmouse.cpp b/src/video/winrt/SDL_winrtmouse.cpp index 826a75bc80c96..30ebfbcb5ce96 100644 --- a/src/video/winrt/SDL_winrtmouse.cpp +++ b/src/video/winrt/SDL_winrtmouse.cpp @@ -90,6 +90,30 @@ static SDL_Cursor *WINRT_CreateSystemCursor(SDL_SystemCursor id) case SDL_SYSTEM_CURSOR_HAND: cursorType = CoreCursorType::Hand; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + cursorType = CoreCursorType::SizeNorthwestSoutheast; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + cursorType = CoreCursorType::SizeNorthSouth; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + cursorType = CoreCursorType::SizeNortheastSouthwest; + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + cursorType = CoreCursorType::SizeWestEast; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + cursorType = CoreCursorType::SizeNorthwestSoutheast; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + cursorType = CoreCursorType::SizeNorthSouth; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + cursorType = CoreCursorType::SizeNortheastSouthwest; + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + cursorType = CoreCursorType::SizeWestEast; + break; } cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 895bed9232289..980aed60a72e4 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -269,6 +269,30 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id) case SDL_SYSTEM_CURSOR_HAND: shape = XC_hand2; break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + shape = XC_top_left_corner; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + shape = XC_top_side; + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + shape = XC_top_right_corner; + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + shape = XC_right_side; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + shape = XC_bottom_right_corner; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + shape = XC_bottom_side; + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + shape = XC_bottom_left_corner; + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + shape = XC_left_side; + break; } cursor = SDL_calloc(1, sizeof(*cursor)); @@ -479,14 +503,14 @@ void X11_InitMouse(SDL_VideoDevice *_this) switch (r) { case SDL_HITTEST_NORMAL: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break; - case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; - case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; - case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; - case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; - case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); break; - case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); break; - case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); break; - case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); break; + case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT); break; + case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOP); break; + case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT); break; + case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_RIGHT); break; + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT); break; + case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOM); break; + case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT); break; + case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_LEFT); break; } r++; } diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index afd74b121135d..c46a250863920 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -215,6 +215,30 @@ static void loop(void) case SDL_SYSTEM_CURSOR_HAND: SDL_Log("Hand"); break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + SDL_Log("Window resize top-left"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + SDL_Log("Window resize top"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + SDL_Log("Window resize top-right"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + SDL_Log("Window resize right"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + SDL_Log("Window resize bottom-right"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + SDL_Log("Window resize bottom"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + SDL_Log("Window resize bottom-left"); + break; + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + SDL_Log("Window resize left"); + break; default: SDL_Log("UNKNOWN CURSOR TYPE, FIX THIS PROGRAM."); break; From fd91178d7f9b268299a9c1e99e2be757617c4acf Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Mon, 20 Nov 2023 21:34:55 -0600 Subject: [PATCH 399/725] Make size cursors be double arrows on Wayland I added fallbacks as they are listed under "to be discussed" in the spec but I don't know if they're necessary. https://www.freedesktop.org/wiki/Specifications/cursor-spec/ --- src/video/wayland/SDL_waylandmouse.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index de209e776c524..7012c2fb1945e 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -336,19 +336,33 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "progress"); break; case SDL_SYSTEM_CURSOR_SIZENWSE: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nw-resize"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nwse-resize"); + if (!cursor) { + /* only a single arrow */ + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nw-resize"); + } break; case SDL_SYSTEM_CURSOR_SIZENESW: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ne-resize"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "nesw-resize"); + if (!cursor) { + /* only a single arrow */ + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ne-resize"); + } break; case SDL_SYSTEM_CURSOR_SIZEWE: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "e-resize"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ew-resize"); + if (!cursor) { + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "col-resize"); + } break; case SDL_SYSTEM_CURSOR_SIZENS: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "n-resize"); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "ns-resize"); + if (!cursor) { + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "row-resize"); + } break; case SDL_SYSTEM_CURSOR_SIZEALL: - cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "fleur"); // ? + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "all-scroll"); break; case SDL_SYSTEM_CURSOR_NO: cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, "not-allowed"); From 0413f6fc49848604c8c6cb719a6dd6c10849dc68 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Tue, 21 Nov 2023 18:36:32 +0200 Subject: [PATCH 400/725] Use SDL_iscntrl() call instead of manual code that is doing the same (#8593) --- src/events/SDL_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index c8ddf125034a2..2a92707d34112 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1063,7 +1063,7 @@ int SDL_SendKeyboardText(const char *text) int posted; /* Don't post text events for unprintable characters */ - if ((unsigned char)*text < ' ' || *text == 127) { + if (SDL_iscntrl((int)*text)) { return 0; } From 0d431015bffe613f390db495097e12a5f418481e Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Tue, 21 Nov 2023 14:11:33 +0200 Subject: [PATCH 401/725] Extract BMP magic into separate define --- src/video/windows/SDL_windowsclipboard.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video/windows/SDL_windowsclipboard.c b/src/video/windows/SDL_windowsclipboard.c index bac510aaea17a..933cce0294d86 100644 --- a/src/video/windows/SDL_windowsclipboard.c +++ b/src/video/windows/SDL_windowsclipboard.c @@ -35,12 +35,11 @@ #define IMAGE_FORMAT CF_DIB #define IMAGE_MIME_TYPE "image/bmp" +#define BFT_BITMAP 0x4d42 /* 'BM' */ /* Assume we can directly read and write BMP fields without byte swapping */ SDL_COMPILE_TIME_ASSERT(verify_byte_order, SDL_BYTEORDER == SDL_LIL_ENDIAN); -static const char bmp_magic[2] = { 'B', 'M' }; - static BOOL WIN_OpenClipboard(SDL_VideoDevice *_this) { /* Retry to open the clipboard in case another application has it open */ @@ -69,7 +68,7 @@ static HANDLE WIN_ConvertBMPtoDIB(const void *bmp, size_t bmp_size) { HANDLE hMem = NULL; - if (bmp && bmp_size > sizeof(BITMAPFILEHEADER) && SDL_memcmp(bmp, bmp_magic, sizeof(bmp_magic)) == 0) { + if (bmp && bmp_size > sizeof(BITMAPFILEHEADER) && ((BITMAPFILEHEADER *)bmp)->bfType == BFT_BITMAP) { BITMAPFILEHEADER *pbfh = (BITMAPFILEHEADER *)bmp; BITMAPINFOHEADER *pbih = (BITMAPINFOHEADER *)((Uint8 *)bmp + sizeof(BITMAPFILEHEADER)); size_t bih_size = pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD); @@ -119,7 +118,7 @@ static void *WIN_ConvertDIBtoBMP(HANDLE hMem, size_t *size) bmp = SDL_malloc(bmp_size); if (bmp) { BITMAPFILEHEADER *pbfh = (BITMAPFILEHEADER *)bmp; - pbfh->bfType = 0x4d42; /* bmp_magic */ + pbfh->bfType = BFT_BITMAP; pbfh->bfSize = (DWORD)bmp_size; pbfh->bfReserved1 = 0; pbfh->bfReserved2 = 0; From 75df4cc5c2cd6b098f49855437c5262263489eab Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 Nov 2023 13:23:14 -0800 Subject: [PATCH 402/725] Don't tickle PS4 Bluetooth controllers in simple mode The 8BitDo Zero 2 only sends reports when state changes, so trips the disconnected Bluetooth controller detection. The expected use case is that most people will have official PS4 controllers in enhanced report mode, so disconnected Bluetooth controller detection will still work for those. Fixes https://github.com/libsdl-org/SDL/issues/8556 --- src/joystick/hidapi/SDL_hidapi_ps4.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index cec3b2dc33fc0..33a262dcd2f43 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -685,10 +685,14 @@ static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device) SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data)); } } else { +#if 0 /* The 8BitDo Zero 2 has perfect emulation of a PS4 controllers, except it + * only sends reports when the state changes, so we can't disconnect here. + */ /* We can't even send an invalid effects packet, or it will put the controller in enhanced mode */ if (device->num_joysticks > 0) { HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } +#endif } } From 119e02f31454b437b442a026a764d95288d5c014 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 Nov 2023 15:19:23 -0800 Subject: [PATCH 403/725] Always use 'm' for controllers provided by the MFI joystick driver This makes sure that SDL_JoystickGUIDUsesVersion() returns false and we don't try to match against other similar controllers using old mappings. --- src/joystick/apple/SDL_mfijoystick.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index b39943f3a289f..6462a9eb5c2b1 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -659,12 +659,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } else { signature = device->button_mask; } - if (vendor == USB_VENDOR_APPLE) { - /* Note that this is an MFI controller and what subtype it is */ - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); - } else { - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 0, subtype); - } + device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); /* This will be set when the first button press of the controller is * detected. */ From b7d7e548958e830841bd0103db75202304ad8841 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 Nov 2023 15:26:34 -0800 Subject: [PATCH 404/725] Fixed uninitialized variable --- src/joystick/apple/SDL_mfijoystick.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 6462a9eb5c2b1..9e106ce930afb 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -554,7 +554,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle if (controller.extendedGamepad) { GCExtendedGamepad *gamepad = controller.extendedGamepad; int nbuttons = 0; - BOOL has_direct_menu; + BOOL has_direct_menu = FALSE; /* These buttons are part of the original MFi spec */ device->button_mask |= (1 << SDL_GAMEPAD_BUTTON_SOUTH); From e761770c2429491814adcdbc5a95b8c7526ceba7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 Nov 2023 15:26:53 -0800 Subject: [PATCH 405/725] No, this wasn't right --- src/joystick/apple/SDL_mfijoystick.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 9e106ce930afb..1b54bf46a2145 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -2102,12 +2102,10 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleOne], elementName); break; case SDL_GAMEPAD_BUTTON_LEFT_PADDLE1: - /* TODO: Is this right? SDL_gamepad.h says P2 is the lower right */ - GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleTwo], elementName); + GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleThree], elementName); break; case SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2: - /* TODO: Is this right? SDL_gamepad.h says P3 is the upper left */ - GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleThree], elementName); + GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleTwo], elementName); break; case SDL_GAMEPAD_BUTTON_LEFT_PADDLE2: GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleFour], elementName); From 94ad1a4ae4a1e25d0139d1868cde41161fc73635 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 22 Nov 2023 01:56:10 +0300 Subject: [PATCH 406/725] SDL_bsdjoystick.c: fix -Wundef warning. --- src/joystick/bsd/SDL_bsdjoystick.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 4b52509c67e65..cb896c4c668b1 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -694,7 +694,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) * calculate the SDL hat value from the 4 separate values. */ switch (usage) { - case HUG_DPAD_UP: + case HUG_DPAD_UP: dpad[0] = (Sint32)hid_get_data(REP_BUF_DATA(rep), &hitem); break; case HUG_DPAD_DOWN: @@ -707,7 +707,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) dpad[3] = (Sint32)hid_get_data(REP_BUF_DATA(rep), &hitem); break; //default: - // no-op + // no-op } SDL_PrivateJoystickHat(joy, 0, (dpad[0] * HAT_UP) | (dpad[1] * HAT_DOWN) | @@ -763,7 +763,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind) #ifdef __DragonFly__ len = hid_report_size(rd, repinfo[repind].kind, r->rid); -#elif __FREEBSD__ +#elif defined __FREEBSD__ #if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) #if (__FreeBSD_kernel_version <= 500111) len = hid_report_size(rd, r->rid, repinfo[repind].kind); From 86d77bbcc5b64c35dce843de93c4f1098f16f2da Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 22 Nov 2023 01:56:10 +0300 Subject: [PATCH 407/725] kmsdrm: restrict KMSDRM_ReleaseVT/KMSDRM_AcquireVT to SDL_INPUT_LINUXEV --- src/video/kmsdrm/SDL_kmsdrmvideo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index f603707131ef9..ac28f6e168479 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1222,6 +1222,7 @@ int KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window) return ret; } +#ifdef SDL_INPUT_LINUXEV static void KMSDRM_ReleaseVT(void *userdata) { SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; @@ -1251,6 +1252,7 @@ static void KMSDRM_AcquireVT(void *userdata) } } } +#endif /* defined SDL_INPUT_LINUXEV */ int KMSDRM_VideoInit(SDL_VideoDevice *_this) { From d1def7f033259cafe5744d49c1cfa2d9351cd18b Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 22 Nov 2023 01:56:10 +0300 Subject: [PATCH 408/725] cmake: add openbsd wscons sources to build, if supported --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5564c756014a5..6eb4b369e1014 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1624,6 +1624,13 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) sdl_sources("${SDL3_SOURCE_DIR}/src/core/freebsd/SDL_evdev_kbd_freebsd.c") endif() + if(HAVE_INPUT_WSCONS) + sdl_sources( + "${SDL3_SOURCE_DIR}/src/core/openbsd/SDL_wscons_kbd.c" + "${SDL3_SOURCE_DIR}/src/core/openbsd/SDL_wscons_mouse.c" + ) + endif() + # Always compiled for Linux, unconditionally: sdl_sources( "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c" From f26a93211fc74658ca63857b4ca75ecdaca4b87f Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 22 Nov 2023 03:31:46 +0100 Subject: [PATCH 409/725] SDL_bsdjoystick: fix -Wundef warning on FreeBSD --- src/joystick/bsd/SDL_bsdjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index cb896c4c668b1..4522289076153 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -69,7 +69,7 @@ #include #endif -#if SDL_HAVE_MACHINE_JOYSTICK_H +#ifdef SDL_HAVE_MACHINE_JOYSTICK_H #include #endif From d6291d4d4209c974751110afdcb040896d791b4f Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 22 Nov 2023 03:27:24 +0100 Subject: [PATCH 410/725] alloca: use alloca from on NetBSD The only generally portable way to do this is to use -std=gnu99, "#include ", and write "alloca". __builtin_alloca does not seem to be available on NetBSD --- include/SDL3/SDL_stdinc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 520c7561a6fc0..50d81825c4ef9 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -41,6 +41,12 @@ # ifndef alloca # ifdef HAVE_ALLOCA_H # include +# elif defined(__NETBSD__) +# if defined(__STRICT_ANSI__) +# define SDL_DISABLE_ALLOCA +# else +# include +# endif # elif defined(__GNUC__) # define alloca __builtin_alloca # elif defined(_MSC_VER) From d2db3f39932f2752b44204e2c3e459e80e1188f8 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 22 Nov 2023 19:22:31 +0100 Subject: [PATCH 411/725] ci: cache android ndk archive --- .github/workflows/android.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 20a09fe48312a..3ae775afdd726 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -23,6 +23,7 @@ jobs: - uses: nttld/setup-ndk@v1 id: setup_ndk with: + local-cache: true ndk-version: r21e - name: Build (Android.mk) if: ${{ matrix.platform.name == 'Android.mk' }} From dbf14df80ffe9edef36ec24505827baf86299148 Mon Sep 17 00:00:00 2001 From: zoey jodon Date: Mon, 20 Nov 2023 13:26:20 -0500 Subject: [PATCH 412/725] Fix joysticks returning invalid device IDs --- src/joystick/haiku/SDL_haikujoystick.cc | 2 +- src/joystick/n3ds/SDL_sysjoystick.c | 2 +- src/joystick/ps2/SDL_sysjoystick.c | 2 +- src/joystick/psp/SDL_sysjoystick.c | 2 +- src/joystick/vita/SDL_sysjoystick.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 49e4d69fefbdf..5c07affb2f0d0 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -113,7 +113,7 @@ extern "C" /* Function to perform the mapping from device index to the instance id for this index */ static SDL_JoystickID HAIKU_JoystickGetDeviceInstanceID(int device_index) { - return device_index; + return device_index + 1; } static void HAIKU_JoystickClose(SDL_Joystick *joystick); diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index 5e17010f0058f..e78d5a735e94f 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -73,7 +73,7 @@ static SDL_JoystickGUID N3DS_JoystickGetDeviceGUID(int device_index) static SDL_JoystickID N3DS_JoystickGetDeviceInstanceID(int device_index) { - return device_index; + return device_index + 1; } static int N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index) diff --git a/src/joystick/ps2/SDL_sysjoystick.c b/src/joystick/ps2/SDL_sysjoystick.c index 45ad16a6e8362..e5f6201cbfbd8 100644 --- a/src/joystick/ps2/SDL_sysjoystick.c +++ b/src/joystick/ps2/SDL_sysjoystick.c @@ -179,7 +179,7 @@ static SDL_JoystickGUID PS2_JoystickGetDeviceGUID(int device_index) /* Function to get the current instance id of the joystick located at device_index */ static SDL_JoystickID PS2_JoystickGetDeviceInstanceID(int device_index) { - return device_index; + return device_index + 1; } /* Function to open a joystick for use. diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index 8db17dcec5574..a3812fd2db378 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -140,7 +140,7 @@ static SDL_JoystickGUID PSP_JoystickGetDeviceGUID(int device_index) /* Function to perform the mapping from device index to the instance id for this index */ static SDL_JoystickID PSP_JoystickGetDeviceInstanceID(int device_index) { - return device_index; + return device_index + 1; } /* Function to open a joystick for use. diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c index cf0585f61a3c8..f426d3aa93708 100644 --- a/src/joystick/vita/SDL_sysjoystick.c +++ b/src/joystick/vita/SDL_sysjoystick.c @@ -151,7 +151,7 @@ void VITA_JoystickDetect() /* Function to perform the mapping from device index to the instance id for this index */ SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index) { - return device_index; + return device_index + 1; } const char *VITA_JoystickGetDeviceName(int index) From 059e550e981e7b2a654b54f548c64a73f5a5fe13 Mon Sep 17 00:00:00 2001 From: zoeyjodon <76182954+zoeyjodon@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:34:01 -0500 Subject: [PATCH 413/725] Fix 3DS Analog Values (#8581) --- src/joystick/n3ds/SDL_sysjoystick.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index e78d5a735e94f..e7a3c43dcf30a 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -31,18 +31,28 @@ #define NB_BUTTONS 23 /* - N3DS sticks values are roughly within +/-160 + N3DS sticks values are roughly within +/-170 which is too small to pass the jitter tolerance. This correction is applied to axis values so they fit better in SDL's value range. */ -#define CORRECT_AXIS_X(X) ((X * SDL_JOYSTICK_AXIS_MAX) / 160) +static inline int Correct_Axis_X(int X) { + if (X > 160) { + return SDL_JOYSTICK_AXIS_MAX; + } + else if (X < -160) { + return -SDL_JOYSTICK_AXIS_MAX; + } + return (X * SDL_JOYSTICK_AXIS_MAX) / 160; +} /* The Y axis needs to be flipped because SDL's "up" is reversed compared to libctru's "up" */ -#define CORRECT_AXIS_Y(Y) CORRECT_AXIS_X(-Y) +static inline int Correct_Axis_Y(int Y) { + return Correct_Axis_X(-Y); +} static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick); static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick); @@ -141,12 +151,12 @@ static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick) if (previous_state.dx != current_state.dx) { SDL_SendJoystickAxis(timestamp, joystick, 0, - CORRECT_AXIS_X(current_state.dx)); + Correct_Axis_X(current_state.dx)); } if (previous_state.dy != current_state.dy) { SDL_SendJoystickAxis(timestamp, joystick, 1, - CORRECT_AXIS_Y(current_state.dy)); + Correct_Axis_Y(current_state.dy)); } previous_state = current_state; } @@ -159,12 +169,12 @@ static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick) if (previous_state.dx != current_state.dx) { SDL_SendJoystickAxis(timestamp, joystick, 2, - CORRECT_AXIS_X(current_state.dx)); + Correct_Axis_X(current_state.dx)); } if (previous_state.dy != current_state.dy) { SDL_SendJoystickAxis(timestamp, joystick, 3, - CORRECT_AXIS_Y(current_state.dy)); + Correct_Axis_Y(current_state.dy)); } previous_state = current_state; } From 45938bbfa532e4c1cdef202a72d899a37a7baf05 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 22 Nov 2023 10:35:15 -0800 Subject: [PATCH 414/725] Corrected comment --- src/joystick/n3ds/SDL_sysjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index e7a3c43dcf30a..5ba1348f71cfc 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -31,7 +31,7 @@ #define NB_BUTTONS 23 /* - N3DS sticks values are roughly within +/-170 + N3DS sticks values are roughly within +/-160 which is too small to pass the jitter tolerance. This correction is applied to axis values so they fit better in SDL's value range. From 81fc7ded7869e86c1277b365b36b6a54ea8e12be Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 22 Nov 2023 11:46:36 -0800 Subject: [PATCH 415/725] Removed the window shape API for SDL 3.0 Fixes https://github.com/libsdl-org/SDL/issues/6654 Fixes https://github.com/libsdl-org/SDL/issues/6897 --- VisualC-GDK/SDL/SDL.vcxproj | 5 - VisualC-GDK/SDL/SDL.vcxproj.filters | 15 -- VisualC-WinRT/SDL-UWP.vcxproj | 3 - VisualC-WinRT/SDL-UWP.vcxproj.filters | 9 - VisualC/SDL/SDL.vcxproj | 5 - VisualC/SDL/SDL.vcxproj.filters | 15 -- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 41 ---- docs/README-migration.md | 4 + include/SDL3/SDL.h | 1 - include/SDL3/SDL_shape.h | 150 ------------- src/dynapi/SDL_dynapi.sym | 4 - src/dynapi/SDL_dynapi_overrides.h | 4 - src/dynapi/SDL_dynapi_procs.h | 4 - src/video/SDL_shape.c | 274 ------------------------ src/video/SDL_shape_internals.h | 59 ----- src/video/SDL_sysvideo.h | 32 --- src/video/cocoa/SDL_cocoashape.h | 38 ---- src/video/cocoa/SDL_cocoashape.m | 115 ---------- src/video/cocoa/SDL_cocoavideo.m | 4 - src/video/cocoa/SDL_cocoawindow.m | 7 - src/video/windows/SDL_windowsevents.c | 1 - src/video/windows/SDL_windowsshape.c | 90 -------- src/video/windows/SDL_windowsshape.h | 38 ---- src/video/windows/SDL_windowsvideo.c | 4 - src/video/windows/SDL_windowswindow.c | 13 -- src/video/x11/SDL_x11shape.c | 98 --------- src/video/x11/SDL_x11shape.h | 37 ---- src/video/x11/SDL_x11video.c | 4 - src/video/x11/SDL_x11window.c | 11 - test/testshape.c | 30 +++ 30 files changed, 34 insertions(+), 1081 deletions(-) delete mode 100644 include/SDL3/SDL_shape.h delete mode 100644 src/video/SDL_shape.c delete mode 100644 src/video/SDL_shape_internals.h delete mode 100644 src/video/cocoa/SDL_cocoashape.h delete mode 100644 src/video/cocoa/SDL_cocoashape.m delete mode 100644 src/video/windows/SDL_windowsshape.c delete mode 100644 src/video/windows/SDL_windowsshape.h delete mode 100644 src/video/x11/SDL_x11shape.c delete mode 100644 src/video/x11/SDL_x11shape.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 3d6451e2fbe6e..6cae7db9582cd 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -342,7 +342,6 @@ - @@ -523,7 +522,6 @@ - @@ -538,7 +536,6 @@ - @@ -774,7 +771,6 @@ - @@ -790,7 +786,6 @@ - diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 2396f04b6ee46..5b5c77da102e2 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -339,9 +339,6 @@ API Headers - - API Headers - API Headers @@ -600,9 +597,6 @@ video - - video - video @@ -660,9 +654,6 @@ video\windows - - video\windows - video\windows @@ -1195,9 +1186,6 @@ video - - video - video @@ -1255,9 +1243,6 @@ video\windows - - video\windows - video\windows diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 2fad76fd31f82..9c2d387d23cfa 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -80,7 +80,6 @@ - @@ -180,7 +179,6 @@ - @@ -520,7 +518,6 @@ - diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 747841ba1b484..586b0d2a5d2a1 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -138,9 +138,6 @@ Header Files - - Header Files - Header Files @@ -405,9 +402,6 @@ Source Files - - Source Files - Source Files @@ -807,9 +801,6 @@ Source Files - - Source Files - Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 0dee2d50069f1..528a3fba58ee5 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -293,7 +293,6 @@ - @@ -451,7 +450,6 @@ - @@ -466,7 +464,6 @@ - @@ -650,7 +647,6 @@ - @@ -667,7 +663,6 @@ - diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index fbaadb802a5c5..8a79f83f0ca79 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -333,9 +333,6 @@ API Headers - - API Headers - API Headers @@ -594,9 +591,6 @@ video - - video - video @@ -654,9 +648,6 @@ video\windows - - video\windows - video\windows @@ -1176,9 +1167,6 @@ video - - video - video @@ -1239,9 +1227,6 @@ video\windows - - video\windows - video\windows diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 66ead99a18f71..6153aa020f9ae 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -43,27 +43,6 @@ 00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; platformFilters = (macos, ); }; 557D0CFA254586CA003913E3 /* CoreHaptics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F37DC5F225350EBC0002E6F7 /* CoreHaptics.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); }; 557D0CFB254586D7003913E3 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A75FDABD23E28B6200529352 /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 63125C002A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; - 63125C012A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; - 63125C022A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; }; - 63125C0A2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C0B2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C0C2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C0D2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C0E2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C0F2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C102A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C112A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C122A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; }; - 63125C142A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C152A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C162A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C172A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C182A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C192A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C1A2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C1B2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; - 63125C1C2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; }; 5616CA4C252BB2A6005D5928 /* SDL_url.c in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA49252BB2A5005D5928 /* SDL_url.c */; }; 5616CA4D252BB2A6005D5928 /* SDL_sysurl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */; }; 5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA4B252BB2A6005D5928 /* SDL_sysurl.m */; }; @@ -136,7 +115,6 @@ A7D8ABF723E2514100DCD162 /* SDL_nullvideo.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A60A23E2513D00DCD162 /* SDL_nullvideo.h */; }; A7D8ABFD23E2514100DCD162 /* SDL_nullevents_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A60B23E2513D00DCD162 /* SDL_nullevents_c.h */; }; A7D8AC0323E2514100DCD162 /* SDL_rect_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A60C23E2513D00DCD162 /* SDL_rect_c.h */; }; - A7D8AC0923E2514100DCD162 /* SDL_shape_internals.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A60D23E2513D00DCD162 /* SDL_shape_internals.h */; }; A7D8AC0F23E2514100DCD162 /* SDL_video.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A60E23E2513D00DCD162 /* SDL_video.c */; }; A7D8AC2D23E2514100DCD162 /* SDL_surface.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A61423E2513D00DCD162 /* SDL_surface.c */; }; A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */; }; @@ -154,7 +132,6 @@ A7D8ADF223E2514100DCD162 /* SDL_blit_A.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A66423E2513E00DCD162 /* SDL_blit_A.c */; }; A7D8AE7623E2514100DCD162 /* SDL_clipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A67B23E2513E00DCD162 /* SDL_clipboard.c */; }; A7D8AE7C23E2514100DCD162 /* SDL_yuv.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A67C23E2513E00DCD162 /* SDL_yuv.c */; }; - A7D8AE8223E2514100DCD162 /* SDL_cocoashape.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A67E23E2513E00DCD162 /* SDL_cocoashape.h */; }; A7D8AE8823E2514100DCD162 /* SDL_cocoaopengl.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A67F23E2513E00DCD162 /* SDL_cocoaopengl.m */; }; A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A68023E2513E00DCD162 /* SDL_cocoakeyboard.h */; }; A7D8AE9423E2514100DCD162 /* SDL_cocoamodes.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A68123E2513E00DCD162 /* SDL_cocoamodes.m */; }; @@ -169,7 +146,6 @@ A7D8AED023E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A68B23E2513E00DCD162 /* SDL_cocoamessagebox.m */; }; A7D8AED623E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A68C23E2513E00DCD162 /* SDL_cocoakeyboard.m */; }; A7D8AEDC23E2514100DCD162 /* SDL_cocoaopengl.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A68D23E2513E00DCD162 /* SDL_cocoaopengl.h */; }; - A7D8AEE223E2514100DCD162 /* SDL_cocoashape.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A68E23E2513E00DCD162 /* SDL_cocoashape.m */; }; A7D8AEE823E2514100DCD162 /* SDL_cocoavulkan.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A68F23E2513E00DCD162 /* SDL_cocoavulkan.h */; }; A7D8AEEE23E2514100DCD162 /* SDL_cocoaopengles.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A69023E2513E00DCD162 /* SDL_cocoaopengles.h */; }; A7D8AEF423E2514100DCD162 /* SDL_cocoamodes.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A69123E2513E00DCD162 /* SDL_cocoamodes.h */; }; @@ -212,7 +188,6 @@ A7D8B39823E2514200DCD162 /* SDL_blit_copy.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76623E2513E00DCD162 /* SDL_blit_copy.h */; }; A7D8B39E23E2514200DCD162 /* SDL_RLEaccel_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */; }; A7D8B3A423E2514200DCD162 /* SDL_fillrect.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */; }; - A7D8B3AA23E2514200DCD162 /* SDL_shape.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A76923E2513E00DCD162 /* SDL_shape.c */; }; A7D8B3B023E2514200DCD162 /* SDL_yuv_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */; }; A7D8B3B623E2514200DCD162 /* SDL_blit.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76B23E2513E00DCD162 /* SDL_blit.h */; }; A7D8B3BF23E2514200DCD162 /* yuv_rgb.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A76E23E2513E00DCD162 /* yuv_rgb.c */; }; @@ -466,7 +441,6 @@ F3F7D9212933074E00816151 /* SDL_log.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8B72933074A00816151 /* SDL_log.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9252933074E00816151 /* SDL_egl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8B82933074A00816151 /* SDL_egl.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8B92933074A00816151 /* SDL_atomic.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3F7D92D2933074E00816151 /* SDL_shape.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BA2933074A00816151 /* SDL_shape.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9312933074E00816151 /* SDL_surface.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BB2933074A00816151 /* SDL_surface.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9352933074E00816151 /* SDL_error.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BC2933074A00816151 /* SDL_error.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9392933074E00816151 /* SDL_opengles2_gl2ext.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8BD2933074A00816151 /* SDL_opengles2_gl2ext.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -632,7 +606,6 @@ A7D8A60A23E2513D00DCD162 /* SDL_nullvideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_nullvideo.h; sourceTree = ""; }; A7D8A60B23E2513D00DCD162 /* SDL_nullevents_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_nullevents_c.h; sourceTree = ""; }; A7D8A60C23E2513D00DCD162 /* SDL_rect_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_c.h; sourceTree = ""; }; - A7D8A60D23E2513D00DCD162 /* SDL_shape_internals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_shape_internals.h; sourceTree = ""; }; A7D8A60E23E2513D00DCD162 /* SDL_video.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video.c; sourceTree = ""; }; A7D8A61423E2513D00DCD162 /* SDL_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_surface.c; sourceTree = ""; }; A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_RLEaccel.c; sourceTree = ""; }; @@ -676,7 +649,6 @@ A7D8A66423E2513E00DCD162 /* SDL_blit_A.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_blit_A.c; sourceTree = ""; }; A7D8A67B23E2513E00DCD162 /* SDL_clipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_clipboard.c; sourceTree = ""; }; A7D8A67C23E2513E00DCD162 /* SDL_yuv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_yuv.c; sourceTree = ""; }; - A7D8A67E23E2513E00DCD162 /* SDL_cocoashape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoashape.h; sourceTree = ""; }; A7D8A67F23E2513E00DCD162 /* SDL_cocoaopengl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoaopengl.m; sourceTree = ""; }; A7D8A68023E2513E00DCD162 /* SDL_cocoakeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoakeyboard.h; sourceTree = ""; }; A7D8A68123E2513E00DCD162 /* SDL_cocoamodes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamodes.m; sourceTree = ""; }; @@ -691,7 +663,6 @@ A7D8A68B23E2513E00DCD162 /* SDL_cocoamessagebox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamessagebox.m; sourceTree = ""; }; A7D8A68C23E2513E00DCD162 /* SDL_cocoakeyboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoakeyboard.m; sourceTree = ""; }; A7D8A68D23E2513E00DCD162 /* SDL_cocoaopengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoaopengl.h; sourceTree = ""; }; - A7D8A68E23E2513E00DCD162 /* SDL_cocoashape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoashape.m; sourceTree = ""; }; A7D8A68F23E2513E00DCD162 /* SDL_cocoavulkan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoavulkan.h; sourceTree = ""; }; A7D8A69023E2513E00DCD162 /* SDL_cocoaopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoaopengles.h; sourceTree = ""; }; A7D8A69123E2513E00DCD162 /* SDL_cocoamodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoamodes.h; sourceTree = ""; }; @@ -734,7 +705,6 @@ A7D8A76623E2513E00DCD162 /* SDL_blit_copy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blit_copy.h; sourceTree = ""; }; A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_RLEaccel_c.h; sourceTree = ""; }; A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_fillrect.c; sourceTree = ""; }; - A7D8A76923E2513E00DCD162 /* SDL_shape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_shape.c; sourceTree = ""; }; A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_yuv_c.h; sourceTree = ""; }; A7D8A76B23E2513E00DCD162 /* SDL_blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blit.h; sourceTree = ""; }; A7D8A76E23E2513E00DCD162 /* yuv_rgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb.c; sourceTree = ""; }; @@ -980,7 +950,6 @@ F3F7D8B72933074A00816151 /* SDL_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_log.h; path = SDL3/SDL_log.h; sourceTree = ""; }; F3F7D8B82933074A00816151 /* SDL_egl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_egl.h; path = SDL3/SDL_egl.h; sourceTree = ""; }; F3F7D8B92933074A00816151 /* SDL_atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_atomic.h; path = SDL3/SDL_atomic.h; sourceTree = ""; }; - F3F7D8BA2933074A00816151 /* SDL_shape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_shape.h; path = SDL3/SDL_shape.h; sourceTree = ""; }; F3F7D8BB2933074A00816151 /* SDL_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_surface.h; path = SDL3/SDL_surface.h; sourceTree = ""; }; F3F7D8BC2933074A00816151 /* SDL_error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_error.h; path = SDL3/SDL_error.h; sourceTree = ""; }; F3F7D8BD2933074A00816151 /* SDL_opengles2_gl2ext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2_gl2ext.h; path = SDL3/SDL_opengles2_gl2ext.h; sourceTree = ""; }; @@ -1133,7 +1102,6 @@ F3F7D8C82933074B00816151 /* SDL_rwops.h */, F3F7D8C12933074B00816151 /* SDL_scancode.h */, F3F7D8C22933074B00816151 /* SDL_sensor.h */, - F3F7D8BA2933074A00816151 /* SDL_shape.h */, F3F7D8AC2933074900816151 /* SDL_stdinc.h */, F3F7D8BB2933074A00816151 /* SDL_surface.h */, F3F7D8E82933074E00816151 /* SDL_system.h */, @@ -1468,8 +1436,6 @@ A7D8A63423E2513D00DCD162 /* SDL_rect.c */, A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */, A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */, - A7D8A60D23E2513D00DCD162 /* SDL_shape_internals.h */, - A7D8A76923E2513E00DCD162 /* SDL_shape.c */, A7D8A60323E2513D00DCD162 /* SDL_stretch.c */, F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */, A7D8A61423E2513D00DCD162 /* SDL_surface.c */, @@ -1574,8 +1540,6 @@ A7D8A67F23E2513E00DCD162 /* SDL_cocoaopengl.m */, A7D8A69023E2513E00DCD162 /* SDL_cocoaopengles.h */, A7D8A68223E2513E00DCD162 /* SDL_cocoaopengles.m */, - A7D8A67E23E2513E00DCD162 /* SDL_cocoashape.h */, - A7D8A68E23E2513E00DCD162 /* SDL_cocoashape.m */, A7D8A69323E2513E00DCD162 /* SDL_cocoavideo.h */, A7D8A68523E2513E00DCD162 /* SDL_cocoavideo.m */, A7D8A68F23E2513E00DCD162 /* SDL_cocoavulkan.h */, @@ -2190,7 +2154,6 @@ A7D8AF1E23E2514100DCD162 /* SDL_cocoamouse.h in Headers */, A7D8AEDC23E2514100DCD162 /* SDL_cocoaopengl.h in Headers */, A7D8AEEE23E2514100DCD162 /* SDL_cocoaopengles.h in Headers */, - A7D8AE8223E2514100DCD162 /* SDL_cocoashape.h in Headers */, A7D8AF0023E2514100DCD162 /* SDL_cocoavideo.h in Headers */, A7D8AEE823E2514100DCD162 /* SDL_cocoavulkan.h in Headers */, A7D8AEFA23E2514100DCD162 /* SDL_cocoawindow.h in Headers */, @@ -2299,8 +2262,6 @@ A7D8B98C23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */, A7D8B99B23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */, A7D8B9A123E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */, - F3F7D92D2933074E00816151 /* SDL_shape.h in Headers */, - A7D8AC0923E2514100DCD162 /* SDL_shape_internals.h in Headers */, F3F7D8F52933074E00816151 /* SDL_stdinc.h in Headers */, A7D8BBC723E2561500DCD162 /* SDL_steamcontroller.h in Headers */, F3F7D9312933074E00816151 /* SDL_surface.h in Headers */, @@ -2536,7 +2497,6 @@ A7D8AE7623E2514100DCD162 /* SDL_clipboard.c in Sources */, A7D8AEC423E2514100DCD162 /* SDL_cocoaevents.m in Sources */, A7D8B86623E2514400DCD162 /* SDL_audiocvt.c in Sources */, - A7D8B3AA23E2514200DCD162 /* SDL_shape.c in Sources */, A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */, F3DDCC5E2AFD42B600B0842B /* SDL_video_capture_v4l2.c in Sources */, A7D8BBE323E2574800DCD162 /* SDL_uikitvideo.m in Sources */, @@ -2606,7 +2566,6 @@ A7D8AED023E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */, F376F6552559B4E300CFC0BC /* SDL_hidapi.c in Sources */, A7D8BA2B23E2514400DCD162 /* SDL_blendfillrect.c in Sources */, - A7D8AEE223E2514100DCD162 /* SDL_cocoashape.m in Sources */, A7D8BBD323E2574800DCD162 /* SDL_uikitappdelegate.m in Sources */, A7D8AEB823E2514100DCD162 /* SDL_cocoamouse.m in Sources */, F32DDAD12AB795A30041EAA5 /* SDL_audioqueue.c in Sources */, diff --git a/docs/README-migration.md b/docs/README-migration.md index 0601988fcfce2..ff1e8f9763ae0 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1084,6 +1084,10 @@ The following functions have been removed: * SDL_SensorGetDeviceType() - replaced with SDL_GetSensorInstanceType() * SDL_UnlockSensors() +## SDL_shape.h + +This header has been removed. You can create a window with the SDL_WINDOW_TRANSPARENT flag and then render using the alpha channel to achieve a similar effect. You can see an example of this in test/testshape.c + ## SDL_stdinc.h The standard C headers like stdio.h and stdlib.h are no longer included, you should include them directly in your project if you use non-SDL C runtime functions. diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index 6db0e69d47e58..422c6cc4a52e7 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -68,7 +68,6 @@ #include #include #include -#include #include #include #include diff --git a/include/SDL3/SDL_shape.h b/include/SDL3/SDL_shape.h deleted file mode 100644 index 92d7db7a5cbb4..0000000000000 --- a/include/SDL3/SDL_shape.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SDL_shape_h_ -#define SDL_shape_h_ - -#include -#include -#include -#include -#include - -#include -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/** \file SDL_shape.h - * - * Header file for the shaped window API. - */ - -#define SDL_NONSHAPEABLE_WINDOW -1 -#define SDL_INVALID_SHAPE_ARGUMENT -2 -#define SDL_WINDOW_LACKS_SHAPE -3 - -/** - * Create a window that can be shaped with the specified dimensions and flags. - * - * \param title The title of the window, in UTF-8 encoding. - * \param w The width of the window. - * \param h The height of the window. - * \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with - * any of the following: ::SDL_WINDOW_OPENGL, - * ::SDL_WINDOW_MOUSE_GRABBED, ::SDL_WINDOW_HIDDEN, - * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED, - * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_BORDERLESS is always set, - * and ::SDL_WINDOW_FULLSCREEN is always unset. - * \returns the window created, or NULL if window creation failed. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_DestroyWindow - */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags); - -/** - * Return whether the given window is a shaped window. - * - * \param window The window to query for being shaped. - * \returns SDL_TRUE if the window is a window that can be shaped, SDL_FALSE - * if the window is unshaped or NULL. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateShapedWindow - */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window); - -/** An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */ -typedef enum { - /** The default mode, a binarized alpha cutoff of 1. */ - ShapeModeDefault, - /** A binarized alpha cutoff with a given integer value. */ - ShapeModeBinarizeAlpha, - /** A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ - ShapeModeReverseBinarizeAlpha, - /** A color key is applied. */ - ShapeModeColorKey -} WindowShapeMode; - -#define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha) - -/** A union containing parameters for shaped windows. */ -typedef union { - /** A cutoff alpha value for binarization of the window shape's alpha channel. */ - Uint8 binarizationCutoff; - SDL_Color colorKey; -} SDL_WindowShapeParams; - -/** A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */ -typedef struct SDL_WindowShapeMode { - /** The mode of these window-shape parameters. */ - WindowShapeMode mode; - /** Window-shape parameters. */ - SDL_WindowShapeParams parameters; -} SDL_WindowShapeMode; - -/** - * Set the shape and parameters of a shaped window. - * - * \param window The shaped window whose parameters should be set. - * \param shape A surface encoding the desired shape for the window. - * \param shape_mode The parameters to set for the shaped window. - * \returns 0 on success, SDL_INVALID_SHAPE_ARGUMENT on an invalid shape - * argument, or SDL_NONSHAPEABLE_WINDOW if the SDL_Window given does - * not reference a valid shaped window. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_WindowShapeMode - * \sa SDL_GetShapedWindowMode - */ -extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode); - -/** - * Get the shape parameters of a shaped window. - * - * \param window The shaped window whose parameters should be retrieved. - * \param shape_mode An empty shape-mode structure to fill, or NULL to check - * whether the window has a shape. - * \returns 0 if the window has a shape and, provided shape_mode was not NULL, - * shape_mode has been filled with the mode data, - * SDL_NONSHAPEABLE_WINDOW if the SDL_Window given is not a shaped - * window, or SDL_WINDOW_LACKS_SHAPE if the SDL_Window given is a - * shapeable window currently lacking a shape. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_WindowShapeMode - * \sa SDL_SetWindowShape - */ -extern DECLSPEC int SDLCALL SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include - -#endif /* SDL_shape_h_ */ diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 14bc32ae91eac..0cb08454f4315 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -57,7 +57,6 @@ SDL3_0.0.0 { SDL_CreateRWLock; SDL_CreateRenderer; SDL_CreateSemaphore; - SDL_CreateShapedWindow; SDL_CreateSoftwareRenderer; SDL_CreateSurface; SDL_CreateSurfaceFrom; @@ -314,7 +313,6 @@ SDL3_0.0.0 { SDL_GetSensorNonPortableType; SDL_GetSensorType; SDL_GetSensors; - SDL_GetShapedWindowMode; SDL_GetSurfaceAlphaMod; SDL_GetSurfaceBlendMode; SDL_GetSurfaceClipRect; @@ -420,7 +418,6 @@ SDL3_0.0.0 { SDL_IsDeXMode; SDL_IsGamepad; SDL_IsJoystickVirtual; - SDL_IsShapedWindow; SDL_IsTablet; SDL_JoystickConnected; SDL_JoystickEventsEnabled; @@ -612,7 +609,6 @@ SDL3_0.0.0 { SDL_SetWindowOpacity; SDL_SetWindowPosition; SDL_SetWindowResizable; - SDL_SetWindowShape; SDL_SetWindowSize; SDL_SetWindowTitle; SDL_SetWindowsMessageHook; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 83ec2ca332f7d..fcd77a293013d 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -81,7 +81,6 @@ #define SDL_CreateRWLock SDL_CreateRWLock_REAL #define SDL_CreateRenderer SDL_CreateRenderer_REAL #define SDL_CreateSemaphore SDL_CreateSemaphore_REAL -#define SDL_CreateShapedWindow SDL_CreateShapedWindow_REAL #define SDL_CreateSoftwareRenderer SDL_CreateSoftwareRenderer_REAL #define SDL_CreateSurface SDL_CreateSurface_REAL #define SDL_CreateSurfaceFrom SDL_CreateSurfaceFrom_REAL @@ -338,7 +337,6 @@ #define SDL_GetSensorNonPortableType SDL_GetSensorNonPortableType_REAL #define SDL_GetSensorType SDL_GetSensorType_REAL #define SDL_GetSensors SDL_GetSensors_REAL -#define SDL_GetShapedWindowMode SDL_GetShapedWindowMode_REAL #define SDL_GetSurfaceAlphaMod SDL_GetSurfaceAlphaMod_REAL #define SDL_GetSurfaceBlendMode SDL_GetSurfaceBlendMode_REAL #define SDL_GetSurfaceClipRect SDL_GetSurfaceClipRect_REAL @@ -444,7 +442,6 @@ #define SDL_IsDeXMode SDL_IsDeXMode_REAL #define SDL_IsGamepad SDL_IsGamepad_REAL #define SDL_IsJoystickVirtual SDL_IsJoystickVirtual_REAL -#define SDL_IsShapedWindow SDL_IsShapedWindow_REAL #define SDL_IsTablet SDL_IsTablet_REAL #define SDL_JoystickConnected SDL_JoystickConnected_REAL #define SDL_JoystickEventsEnabled SDL_JoystickEventsEnabled_REAL @@ -635,7 +632,6 @@ #define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL #define SDL_SetWindowPosition SDL_SetWindowPosition_REAL #define SDL_SetWindowResizable SDL_SetWindowResizable_REAL -#define SDL_SetWindowShape SDL_SetWindowShape_REAL #define SDL_SetWindowSize SDL_SetWindowSize_REAL #define SDL_SetWindowTitle SDL_SetWindowTitle_REAL #define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 7ddba0e8c8c2a..4149b05cd805b 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -147,7 +147,6 @@ SDL_DYNAPI_PROC(SDL_RWops*,SDL_CreateRW,(void),(),return) SDL_DYNAPI_PROC(SDL_RWLock*,SDL_CreateRWLock,(void),(),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRenderer,(SDL_Window *a, const char *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Semaphore*,SDL_CreateSemaphore,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateShapedWindow,(const char *a, int b, int c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateSoftwareRenderer,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurface,(int a, int b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurfaceFrom,(void *a, int b, int c, int d, Uint32 e),(a,b,c,d,e),return) @@ -397,7 +396,6 @@ SDL_DYNAPI_PROC(const char*,SDL_GetSensorName,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetSensorNonPortableType,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorType,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(SDL_SensorID*,SDL_GetSensors,(int *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetShapedWindowMode,(SDL_Window *a, SDL_WindowShapeMode *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetSurfaceAlphaMod,(SDL_Surface *a, Uint8 *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetSurfaceClipRect,(SDL_Surface *a, SDL_Rect *b),(a,b),return) @@ -500,7 +498,6 @@ SDL_DYNAPI_PROC(int,SDL_Init,(Uint32 a),(a),return) SDL_DYNAPI_PROC(int,SDL_InitSubSystem,(Uint32 a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsGamepad,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickVirtual,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsShapedWindow,(const SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickConnected,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickEventsEnabled,(void),(),return) @@ -678,7 +675,6 @@ SDL_DYNAPI_PROC(int,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a SDL_DYNAPI_PROC(int,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetWindowPosition,(SDL_Window *a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowShape,(SDL_Window *a, SDL_Surface *b, SDL_WindowShapeMode *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetWindowSize,(SDL_Window *a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetWindowTitle,(SDL_Window *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_SetYUVConversionMode,(SDL_YUV_CONVERSION_MODE a),(a),) diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c deleted file mode 100644 index 2362ed7f7f380..0000000000000 --- a/src/video/SDL_shape.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#include "SDL_sysvideo.h" -#include "SDL_shape_internals.h" -#include "SDL_video_c.h" - -SDL_Window *SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags) -{ - SDL_Window *result = NULL; - result = SDL_CreateWindow(title, w, h, (flags | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE)); - if (result) { - if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) { - SDL_DestroyWindow(result); - return NULL; - } - result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result); - if (result->shaper) { - result->shaper->mode.mode = ShapeModeDefault; - result->shaper->mode.parameters.binarizationCutoff = 1; - result->shaper->hasshape = SDL_FALSE; - return result; - } else { - SDL_DestroyWindow(result); - return NULL; - } - } - return NULL; -} - -SDL_bool SDL_IsShapedWindow(const SDL_Window *window) -{ - if (window == NULL) { - return SDL_FALSE; - } - return (window->shaper != NULL); -} - -/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */ -void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb) -{ - int x = 0; - int y = 0; - Uint8 r = 0, g = 0, b = 0, alpha = 0; - Uint32 mask_value = 0; - size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb; - Uint8 *bitmap_scanline; - SDL_Color key; - - if (SDL_MUSTLOCK(shape)) { - SDL_LockSurface(shape); - } - - SDL_memset(bitmap, 0, shape->h * bytes_per_scanline); - - for (y = 0; y < shape->h; y++) { - bitmap_scanline = bitmap + y * bytes_per_scanline; - for (x = 0; x < shape->w; x++) { - if (SDL_ReadSurfacePixel(shape, x, y, &r, &g, &b, &alpha) != 0) { - continue; - } - - switch (mode.mode) { - case (ShapeModeDefault): - mask_value = (alpha >= 1 ? 1 : 0); - break; - case (ShapeModeBinarizeAlpha): - mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0); - break; - case (ShapeModeReverseBinarizeAlpha): - mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0); - break; - case (ShapeModeColorKey): - key = mode.parameters.colorKey; - mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0); - break; - } - bitmap_scanline[x / ppb] |= mask_value << (x % ppb); - } - } - - if (SDL_MUSTLOCK(shape)) { - SDL_UnlockSurface(shape); - } -} - -static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions) -{ - int x = 0, y = 0; - Uint8 r = 0, g = 0, b = 0, a = 0; - SDL_bool pixel_opaque = SDL_FALSE; - int last_opaque = -1; - SDL_Color key; - SDL_ShapeTree *result = (SDL_ShapeTree *)SDL_malloc(sizeof(SDL_ShapeTree)); - SDL_Rect next = { 0, 0, 0, 0 }; - - if (!result) { - SDL_OutOfMemory(); - return NULL; - } - - for (y = dimensions.y; y < dimensions.y + dimensions.h; y++) { - for (x = dimensions.x; x < dimensions.x + dimensions.w; x++) { - if (SDL_ReadSurfacePixel(mask, x, y, &r, &g, &b, &a) != 0) { - continue; - } - switch (mode.mode) { - case (ShapeModeDefault): - pixel_opaque = (a >= 1); - break; - case (ShapeModeBinarizeAlpha): - pixel_opaque = (a >= mode.parameters.binarizationCutoff); - break; - case (ShapeModeReverseBinarizeAlpha): - pixel_opaque = (a <= mode.parameters.binarizationCutoff); - break; - case (ShapeModeColorKey): - key = mode.parameters.colorKey; - pixel_opaque = (key.r != r || key.g != g || key.b != b); - break; - } - if (last_opaque == -1) { - last_opaque = pixel_opaque; - } - if (last_opaque != pixel_opaque) { - const int halfwidth = dimensions.w / 2; - const int halfheight = dimensions.h / 2; - - result->kind = QuadShape; - - next.x = dimensions.x; - next.y = dimensions.y; - next.w = halfwidth; - next.h = halfheight; - result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next); - - next.x = dimensions.x + halfwidth; - next.w = dimensions.w - halfwidth; - result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next); - - next.x = dimensions.x; - next.w = halfwidth; - next.y = dimensions.y + halfheight; - next.h = dimensions.h - halfheight; - result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next); - - next.x = dimensions.x + halfwidth; - next.w = dimensions.w - halfwidth; - result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next); - - return result; - } - } - } - - /* If we never recursed, all the pixels in this quadrant have the same "value". */ - result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape); - result->data.shape = dimensions; - return result; -} - -SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape) -{ - SDL_Rect dimensions; - SDL_ShapeTree *result = NULL; - - dimensions.x = 0; - dimensions.y = 0; - dimensions.w = shape->w; - dimensions.h = shape->h; - - if (SDL_MUSTLOCK(shape)) { - SDL_LockSurface(shape); - } - result = RecursivelyCalculateShapeTree(mode, shape, dimensions); - if (SDL_MUSTLOCK(shape)) { - SDL_UnlockSurface(shape); - } - return result; -} - -void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure) -{ - SDL_assert(tree != NULL); - if (tree->kind == QuadShape) { - SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft, function, closure); - SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright, function, closure); - SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft, function, closure); - SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright, function, closure); - } else { - function(tree, closure); - } -} - -void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree) -{ - if ((*shape_tree)->kind == QuadShape) { - SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upleft); - SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upright); - SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downleft); - SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downright); - } - SDL_free(*shape_tree); - *shape_tree = NULL; -} - -int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - int result; - - if (!window || !SDL_IsShapedWindow(window)) { - /* The window given was not a shapeable window. */ - return SDL_NONSHAPEABLE_WINDOW; - } - if (!shape) { - /* Invalid shape argument. */ - return SDL_INVALID_SHAPE_ARGUMENT; - } - - if (shape_mode) { - window->shaper->mode = *shape_mode; - } - result = _this->shape_driver.SetWindowShape(window->shaper, shape, shape_mode); - if (result == 0) { - window->shaper->hasshape = SDL_TRUE; - SDL_ShowWindow(window); - } - return result; -} - -static SDL_bool SDL_WindowHasAShape(SDL_Window *window) -{ - if (!window || !SDL_IsShapedWindow(window)) { - return SDL_FALSE; - } - return window->shaper->hasshape; -} - -int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode) -{ - if (window && SDL_IsShapedWindow(window)) { - if (!shape_mode) { - if (SDL_WindowHasAShape(window)) { - return 0; /* The window given has a shape. */ - } else { - return SDL_WINDOW_LACKS_SHAPE; /* The window given is shapeable but lacks a shape. */ - } - } else { - *shape_mode = window->shaper->mode; - return 0; - } - } - return SDL_NONSHAPEABLE_WINDOW; /* The window given is not a valid shapeable window. */ -} diff --git a/src/video/SDL_shape_internals.h b/src/video/SDL_shape_internals.h deleted file mode 100644 index fa8e90adbf890..0000000000000 --- a/src/video/SDL_shape_internals.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifndef SDL_shape_internals_h_ -#define SDL_shape_internals_h_ - -struct SDL_ShapeTree; - -typedef struct -{ - struct SDL_ShapeTree *upleft, *upright, *downleft, *downright; -} SDL_QuadTreeChildren; - -typedef union -{ - SDL_QuadTreeChildren children; - SDL_Rect shape; -} SDL_ShapeUnion; - -typedef enum -{ - QuadShape, - TransparentShape, - OpaqueShape -} SDL_ShapeKind; - -typedef struct SDL_ShapeTree -{ - SDL_ShapeKind kind; - SDL_ShapeUnion data; -} SDL_ShapeTree; - -typedef void (*SDL_TraversalFunction)(SDL_ShapeTree *, void *); - -extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb); -extern SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape); -extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure); -extern void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree); - -#endif /* SDL_shape_internals_h_ */ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 2dccb30d2b797..df986bdf87e16 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -27,8 +27,6 @@ /* The SDL video driver */ -typedef struct SDL_WindowShaper SDL_WindowShaper; -typedef struct SDL_ShapeDriver SDL_ShapeDriver; typedef struct SDL_VideoDisplay SDL_VideoDisplay; typedef struct SDL_VideoDevice SDL_VideoDevice; typedef struct SDL_VideoData SDL_VideoData; @@ -36,28 +34,6 @@ typedef struct SDL_DisplayData SDL_DisplayData; typedef struct SDL_DisplayModeData SDL_DisplayModeData; typedef struct SDL_WindowData SDL_WindowData; -/* Define the SDL window-shaper structure */ -struct SDL_WindowShaper -{ - /* The window associated with the shaper */ - SDL_Window *window; - - /* The parameters for shape calculation. */ - SDL_WindowShapeMode mode; - - /* Has this window been assigned a shape? */ - SDL_bool hasshape; - - void *driverdata; -}; - -/* Define the SDL shape driver structure */ -struct SDL_ShapeDriver -{ - SDL_WindowShaper *(*CreateShaper)(SDL_Window *window); - int (*SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode); -}; - /* Define the SDL window structure, corresponding to toplevel windows */ struct SDL_Window { @@ -99,8 +75,6 @@ struct SDL_Window SDL_Rect mouse_rect; - SDL_WindowShaper *shaper; - SDL_HitTest hit_test; void *hit_test_data; @@ -257,12 +231,6 @@ struct SDL_VideoDevice int (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); int (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); - /* * * */ - /* - * Shaped-window functions - */ - SDL_ShapeDriver shape_driver; - /* * * */ /* * OpenGL support diff --git a/src/video/cocoa/SDL_cocoashape.h b/src/video/cocoa/SDL_cocoashape.h deleted file mode 100644 index a7c6d14a5a8a8..0000000000000 --- a/src/video/cocoa/SDL_cocoashape.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifndef SDL_cocoashape_h_ -#define SDL_cocoashape_h_ - -#include "../SDL_shape_internals.h" - -@interface SDL_ShapeData : NSObject -@property(nonatomic) NSGraphicsContext *context; -@property(nonatomic) SDL_bool saved; -@property(nonatomic) SDL_ShapeTree *shape; -@end - -extern SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window); -extern int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode); - -#endif /* SDL_cocoashape_h_ */ diff --git a/src/video/cocoa/SDL_cocoashape.m b/src/video/cocoa/SDL_cocoashape.m deleted file mode 100644 index 2e16741b7e849..0000000000000 --- a/src/video/cocoa/SDL_cocoashape.m +++ /dev/null @@ -1,115 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_COCOA - -#include "SDL_cocoavideo.h" -#include "SDL_cocoashape.h" -#include "../SDL_sysvideo.h" - -@implementation SDL_ShapeData -@end - -@interface SDL_CocoaClosure : NSObject -@property(nonatomic) NSView *view; -@property(nonatomic) NSBezierPath *path; -@property(nonatomic) SDL_Window *window; -@end - -@implementation SDL_CocoaClosure -@end - -SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window) -{ - @autoreleasepool { - SDL_WindowShaper *result; - SDL_ShapeData *data; - SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata; - - result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper)); - if (!result) { - SDL_OutOfMemory(); - return NULL; - } - - [windata.nswindow setOpaque:NO]; - - [windata.nswindow setStyleMask:NSWindowStyleMaskBorderless]; - - result->window = window; - result->mode.mode = ShapeModeDefault; - result->mode.parameters.binarizationCutoff = 1; - window->shaper = result; - - data = [[SDL_ShapeData alloc] init]; - data.context = [windata.nswindow graphicsContext]; - data.saved = SDL_FALSE; - data.shape = NULL; - - /* TODO: There's no place to release this... */ - result->driverdata = (void *)CFBridgingRetain(data); - - return result; - } -} - -void ConvertRects(SDL_ShapeTree *tree, void *closure) -{ - SDL_CocoaClosure *data = (__bridge SDL_CocoaClosure *)closure; - if (tree->kind == OpaqueShape) { - NSRect rect = NSMakeRect(tree->data.shape.x, data.window->h - tree->data.shape.y, tree->data.shape.w, tree->data.shape.h); - [data.path appendBezierPathWithRect:[data.view convertRect:rect toView:nil]]; - } -} - -int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode) -{ - @autoreleasepool { - SDL_ShapeData *data = (__bridge SDL_ShapeData *)shaper->driverdata; - SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)shaper->window->driverdata; - SDL_CocoaClosure *closure; - if (data.saved == SDL_TRUE) { - [data.context restoreGraphicsState]; - data.saved = SDL_FALSE; - } - - /*[data.context saveGraphicsState];*/ - /*data.saved = SDL_TRUE;*/ - [NSGraphicsContext setCurrentContext:data.context]; - - [[NSColor clearColor] set]; - NSRectFill([windata.sdlContentView frame]); - data.shape = SDL_CalculateShapeTree(*shape_mode, shape); - - closure = [[SDL_CocoaClosure alloc] init]; - - closure.view = windata.sdlContentView; - closure.path = [NSBezierPath bezierPath]; - closure.window = shaper->window; - SDL_TraverseShapeTree(data.shape, &ConvertRects, (__bridge void *)closure); - [closure.path addClip]; - - return 0; - } -} - -#endif /* SDL_VIDEO_DRIVER_COCOA */ diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 1153b26350d2e..0d93a5ef0649a 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -27,7 +27,6 @@ #endif #include "SDL_cocoavideo.h" -#include "SDL_cocoashape.h" #include "SDL_cocoavulkan.h" #include "SDL_cocoametalview.h" #include "SDL_cocoaopengles.h" @@ -119,9 +118,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) device->FlashWindow = Cocoa_FlashWindow; device->SetWindowFocusable = Cocoa_SetWindowFocusable; - device->shape_driver.CreateShaper = Cocoa_CreateShaper; - device->shape_driver.SetWindowShape = Cocoa_SetWindowShape; - #ifdef SDL_VIDEO_OPENGL_CGL device->GL_LoadLibrary = Cocoa_GL_LoadLibrary; device->GL_GetProcAddress = Cocoa_GL_GetProcAddress; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index b4c0bf7d2a898..964cfa0e67427 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -36,7 +36,6 @@ #include "../../events/SDL_dropevents_c.h" #include "SDL_cocoavideo.h" -#include "SDL_cocoashape.h" #include "SDL_cocoamouse.h" #include "SDL_cocoaopengl.h" #include "SDL_cocoaopengles.h" @@ -2563,12 +2562,6 @@ void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } #endif /* SDL_VIDEO_OPENGL */ - - if (window->shaper) { - CFBridgingRelease(window->shaper->driverdata); - SDL_free(window->shaper); - window->shaper = NULL; - } } window->driverdata = NULL; } diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index ef6b3d655c3b9..5202955bf0543 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -23,7 +23,6 @@ #ifdef SDL_VIDEO_DRIVER_WINDOWS #include "SDL_windowsvideo.h" -#include "SDL_windowsshape.h" #include "SDL_vkeys.h" #include "../../events/SDL_events_c.h" #include "../../events/SDL_touch_c.h" diff --git a/src/video/windows/SDL_windowsshape.c b/src/video/windows/SDL_windowsshape.c deleted file mode 100644 index 74026601f5585..0000000000000 --- a/src/video/windows/SDL_windowsshape.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#if defined(SDL_VIDEO_DRIVER_WINDOWS) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) - -#include "SDL_windowsshape.h" -#include "SDL_windowsvideo.h" - -SDL_WindowShaper *Win32_CreateShaper(SDL_Window *window) -{ - SDL_WindowShaper *result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper)); - if (!result) { - SDL_OutOfMemory(); - return NULL; - } - result->window = window; - result->mode.mode = ShapeModeDefault; - result->mode.parameters.binarizationCutoff = 1; - result->hasshape = SDL_FALSE; - result->driverdata = (SDL_ShapeData *)SDL_calloc(1, sizeof(SDL_ShapeData)); - if (!result->driverdata) { - SDL_free(result); - SDL_OutOfMemory(); - return NULL; - } - window->shaper = result; - - return result; -} - -static void CombineRectRegions(SDL_ShapeTree *node, void *closure) -{ - HRGN mask_region = *((HRGN *)closure), temp_region = NULL; - if (node->kind == OpaqueShape) { - /* Win32 API regions exclude their outline, so we widen the region by one pixel in each direction to include the real outline. */ - temp_region = CreateRectRgn(node->data.shape.x, node->data.shape.y, node->data.shape.x + node->data.shape.w + 1, node->data.shape.y + node->data.shape.h + 1); - if (mask_region != NULL) { - CombineRgn(mask_region, mask_region, temp_region, RGN_OR); - DeleteObject(temp_region); - } else { - *((HRGN *)closure) = temp_region; - } - } -} - -int Win32_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode) -{ - SDL_ShapeData *data; - HRGN mask_region = NULL; - - if ((!shaper) || - (!shape) || - ((shape->format->Amask == 0) && (shape_mode->mode != ShapeModeColorKey))) { - return SDL_INVALID_SHAPE_ARGUMENT; - } - - data = (SDL_ShapeData *)shaper->driverdata; - if (data->mask_tree) { - SDL_FreeShapeTree(&data->mask_tree); - } - data->mask_tree = SDL_CalculateShapeTree(*shape_mode, shape); - - SDL_TraverseShapeTree(data->mask_tree, &CombineRectRegions, &mask_region); - SDL_assert(mask_region != NULL); - - SetWindowRgn(shaper->window->driverdata->hwnd, mask_region, TRUE); - - return 0; -} - -#endif /* SDL_VIDEO_DRIVER_WINDOWS */ diff --git a/src/video/windows/SDL_windowsshape.h b/src/video/windows/SDL_windowsshape.h deleted file mode 100644 index 074f7edf4fb63..0000000000000 --- a/src/video/windows/SDL_windowsshape.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifndef SDL_windowsshape_h_ -#define SDL_windowsshape_h_ - -#include "../SDL_sysvideo.h" -#include "../SDL_shape_internals.h" - -typedef struct -{ - SDL_ShapeTree *mask_tree; -} SDL_ShapeData; - -extern SDL_WindowShaper *Win32_CreateShaper(SDL_Window *window); -extern int Win32_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode); - -#endif /* SDL_windowsshape_h_ */ diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 15ef5a8fee05d..6cfbc35d2f29c 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -31,7 +31,6 @@ #include "SDL_windowsvideo.h" #include "SDL_windowsframebuffer.h" -#include "SDL_windowsshape.h" #include "SDL_windowsvulkan.h" #ifdef SDL_GDK_TEXTINPUT @@ -210,9 +209,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) device->FlashWindow = WIN_FlashWindow; device->ShowWindowSystemMenu = WIN_ShowWindowSystemMenu; device->SetWindowFocusable = WIN_SetWindowFocusable; - - device->shape_driver.CreateShaper = Win32_CreateShaper; - device->shape_driver.SetWindowShape = Win32_SetWindowShape; #endif #ifdef SDL_VIDEO_OPENGL_WGL diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 2665a21ae91a3..55e2d700ed09f 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -33,7 +33,6 @@ #include "SDL_windowsvideo.h" #include "SDL_windowswindow.h" -#include "SDL_windowsshape.h" /* Dropfile support */ #include @@ -1230,18 +1229,6 @@ void WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_b void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) { - if (window->shaper) { - SDL_ShapeData *shapedata = (SDL_ShapeData *)window->shaper->driverdata; - if (shapedata) { - if (shapedata->mask_tree) { - SDL_FreeShapeTree(&shapedata->mask_tree); - } - SDL_free(shapedata); - } - SDL_free(window->shaper); - window->shaper = NULL; - } - CleanupWindowData(_this, window); } diff --git a/src/video/x11/SDL_x11shape.c b/src/video/x11/SDL_x11shape.c deleted file mode 100644 index 373d6eba1ae4b..0000000000000 --- a/src/video/x11/SDL_x11shape.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11shape.h" -#include "SDL_x11window.h" -#include "../SDL_shape_internals.h" - -SDL_WindowShaper *X11_CreateShaper(SDL_Window *window) -{ - SDL_WindowShaper *result = NULL; - -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE - SDL_ShapeData *data = NULL; - - if (SDL_X11_HAVE_XSHAPE) { /* Make sure X server supports it. */ - result = SDL_malloc(sizeof(SDL_WindowShaper)); - if (!result) { - SDL_OutOfMemory(); - return NULL; - } - result->window = window; - result->mode.mode = ShapeModeDefault; - result->mode.parameters.binarizationCutoff = 1; - data = SDL_malloc(sizeof(SDL_ShapeData)); - if (!data) { - SDL_free(result); - SDL_OutOfMemory(); - return NULL; - } - result->driverdata = data; - data->bitmapsize = 0; - data->bitmap = NULL; - window->shaper = result; - } -#endif - - return result; -} - -int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE - SDL_ShapeData *data = NULL; - SDL_WindowData *windowdata = NULL; - Pixmap shapemask; -#endif - - if (!shaper || !shape || !shaper->driverdata) { - return -1; - } - -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE - if (shape->format->Amask == 0 && SDL_SHAPEMODEALPHA(shape_mode->mode)) { - return -2; - } - if (shape->w != shaper->window->w || shape->h != shaper->window->h) { - return -3; - } - data = shaper->driverdata; - - /* Assume that shaper->alphacutoff already has a value, because SDL_SetWindowShape() should have given it one. */ - SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8); - - windowdata = shaper->window->driverdata; - shapemask = X11_XCreateBitmapFromData(windowdata->videodata->display, windowdata->xwindow, data->bitmap, shaper->window->w, shaper->window->h); - - X11_XShapeCombineMask(windowdata->videodata->display, windowdata->xwindow, ShapeBounding, 0, 0, shapemask, ShapeSet); - X11_XSync(windowdata->videodata->display, False); - - X11_XFreePixmap(windowdata->videodata->display, shapemask); -#endif - - return 0; -} - -#endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/src/video/x11/SDL_x11shape.h b/src/video/x11/SDL_x11shape.h deleted file mode 100644 index 96ec12184fc09..0000000000000 --- a/src/video/x11/SDL_x11shape.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifndef SDL_x11shape_h_ -#define SDL_x11shape_h_ - -#include "../SDL_sysvideo.h" - -typedef struct -{ - void *bitmap; - Uint32 bitmapsize; -} SDL_ShapeData; - -extern SDL_WindowShaper *X11_CreateShaper(SDL_Window *window); -extern int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode); - -#endif /* SDL_x11shape_h_ */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 8e9b91d2a963d..32a28ee1ac01b 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -30,7 +30,6 @@ #include "SDL_x11framebuffer.h" #include "SDL_x11pen.h" -#include "SDL_x11shape.h" #include "SDL_x11touch.h" #include "SDL_x11video.h" #include "SDL_x11xfixes.h" @@ -217,9 +216,6 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->SetWindowMouseRect = X11_SetWindowMouseRect; #endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ - device->shape_driver.CreateShaper = X11_CreateShaper; - device->shape_driver.SetWindowShape = X11_SetWindowShape; - #ifdef SDL_VIDEO_OPENGL_GLX device->GL_LoadLibrary = X11_GL_LoadLibrary; device->GL_GetProcAddress = X11_GL_GetProcAddress; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index c750ea76090a2..5d8000d21579a 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -31,7 +31,6 @@ #include "SDL_x11video.h" #include "SDL_x11mouse.h" -#include "SDL_x11shape.h" #include "SDL_x11xinput2.h" #include "SDL_x11xfixes.h" @@ -1821,16 +1820,6 @@ void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->driverdata; - if (window->shaper) { - SDL_ShapeData *shapedata = (SDL_ShapeData *)window->shaper->driverdata; - if (shapedata) { - SDL_free(shapedata->bitmap); - SDL_free(shapedata); - } - SDL_free(window->shaper); - window->shaper = NULL; - } - if (data) { SDL_VideoData *videodata = data->videodata; Display *display = videodata->display; diff --git a/test/testshape.c b/test/testshape.c index c5950b3f7be54..459badabee030 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -17,6 +17,36 @@ #define SHAPED_WINDOW_DIMENSION 640 +/** An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */ +typedef enum +{ + /** The default mode, a binarized alpha cutoff of 1. */ + ShapeModeDefault, + /** A binarized alpha cutoff with a given integer value. */ + ShapeModeBinarizeAlpha, + /** A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ + ShapeModeReverseBinarizeAlpha, + /** A color key is applied. */ + ShapeModeColorKey +} WindowShapeMode; + +/** A union containing parameters for shaped windows. */ +typedef union +{ + /** A cutoff alpha value for binarization of the window shape's alpha channel. */ + Uint8 binarizationCutoff; + SDL_Color colorKey; +} SDL_WindowShapeParams; + +/** A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */ +typedef struct SDL_WindowShapeMode +{ + /** The mode of these window-shape parameters. */ + WindowShapeMode mode; + /** Window-shape parameters. */ + SDL_WindowShapeParams parameters; +} SDL_WindowShapeMode; + typedef struct LoadedPicture { SDL_Surface *surface; From eca79e38db10dee2a8fb4ec58e4188bfd81dcd46 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 22 Nov 2023 12:22:45 -0800 Subject: [PATCH 416/725] Removed test shape images --- test/shapes/p01_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p01_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p01_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p02_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p02_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p02_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p03_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p03_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p04_shape1.bmp | Bin 51346 -> 0 bytes test/shapes/p04_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p04_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p04_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p05_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p06_shape1alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p06_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p06_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p06_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p07_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p07_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p07_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p08_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p08_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p08_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p09_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p09_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p09_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p10_shape1.bmp | Bin 51346 -> 0 bytes test/shapes/p10_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p10_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p10_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p11_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p11_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p11_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p12_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p12_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p13_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p13_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p13_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p14_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p14_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p15_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p15_shape32alpha.bmp | Bin 1638538 -> 0 bytes test/shapes/p15_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/p16_shape1.bmp | Bin 51346 -> 0 bytes test/shapes/p16_shape24.bmp | Bin 1228938 -> 0 bytes test/shapes/p16_shape8.bmp | Bin 410678 -> 0 bytes test/shapes/trollface_24.bmp | Bin 196662 -> 0 bytes test/shapes/trollface_32alpha.bmp | Bin 262198 -> 0 bytes 48 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/shapes/p01_shape24.bmp delete mode 100644 test/shapes/p01_shape32alpha.bmp delete mode 100644 test/shapes/p01_shape8.bmp delete mode 100644 test/shapes/p02_shape24.bmp delete mode 100644 test/shapes/p02_shape32alpha.bmp delete mode 100644 test/shapes/p02_shape8.bmp delete mode 100644 test/shapes/p03_shape24.bmp delete mode 100644 test/shapes/p03_shape8.bmp delete mode 100644 test/shapes/p04_shape1.bmp delete mode 100644 test/shapes/p04_shape24.bmp delete mode 100644 test/shapes/p04_shape32alpha.bmp delete mode 100644 test/shapes/p04_shape8.bmp delete mode 100644 test/shapes/p05_shape8.bmp delete mode 100644 test/shapes/p06_shape1alpha.bmp delete mode 100644 test/shapes/p06_shape24.bmp delete mode 100644 test/shapes/p06_shape32alpha.bmp delete mode 100644 test/shapes/p06_shape8.bmp delete mode 100644 test/shapes/p07_shape24.bmp delete mode 100644 test/shapes/p07_shape32alpha.bmp delete mode 100644 test/shapes/p07_shape8.bmp delete mode 100644 test/shapes/p08_shape24.bmp delete mode 100644 test/shapes/p08_shape32alpha.bmp delete mode 100644 test/shapes/p08_shape8.bmp delete mode 100644 test/shapes/p09_shape24.bmp delete mode 100644 test/shapes/p09_shape32alpha.bmp delete mode 100644 test/shapes/p09_shape8.bmp delete mode 100644 test/shapes/p10_shape1.bmp delete mode 100644 test/shapes/p10_shape24.bmp delete mode 100644 test/shapes/p10_shape32alpha.bmp delete mode 100644 test/shapes/p10_shape8.bmp delete mode 100644 test/shapes/p11_shape24.bmp delete mode 100644 test/shapes/p11_shape32alpha.bmp delete mode 100644 test/shapes/p11_shape8.bmp delete mode 100644 test/shapes/p12_shape24.bmp delete mode 100644 test/shapes/p12_shape8.bmp delete mode 100644 test/shapes/p13_shape24.bmp delete mode 100644 test/shapes/p13_shape32alpha.bmp delete mode 100644 test/shapes/p13_shape8.bmp delete mode 100644 test/shapes/p14_shape24.bmp delete mode 100644 test/shapes/p14_shape8.bmp delete mode 100644 test/shapes/p15_shape24.bmp delete mode 100644 test/shapes/p15_shape32alpha.bmp delete mode 100644 test/shapes/p15_shape8.bmp delete mode 100644 test/shapes/p16_shape1.bmp delete mode 100644 test/shapes/p16_shape24.bmp delete mode 100644 test/shapes/p16_shape8.bmp delete mode 100644 test/shapes/trollface_24.bmp delete mode 100644 test/shapes/trollface_32alpha.bmp diff --git a/test/shapes/p01_shape24.bmp b/test/shapes/p01_shape24.bmp deleted file mode 100644 index 290e93d9c756f17c22eb86a3b1dda89287f6443a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 F@P7^ZPXPb` diff --git a/test/shapes/p01_shape8.bmp b/test/shapes/p01_shape8.bmp deleted file mode 100644 index 5adca298f715c601d0290c5210760c8614781cc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 zcmeI51(@^35r*f|G)+@TnHf{&l$$n9xhXRBg;Pf>?21x%28zBefO249`&fQ-+uea(T;XBIr`C$ zF2^{=G31!XJf`fw|Ne5UV;xJ5ee7e)agK8wIqq?fE5|$D@#Of&Kfavc1SgOap74Zn zq7$7+PJH4M%Sldh5;^HfPbw!n*~#SOCqKEI;uNQlQ=amaa;j6EN=|+1Q_E>ia~e7A zX-_MsJKgEz^rt_)oZ$>-kTag~jB>yM2gsSubS63Tna?a|Im=n(tY~fBCoI}oe&U4DS&UG$1_qoq4=Q+=L@r7ta)xy)tcvX{NAT<&t0lgnTJ@^XbMTtTjQ#Vg98haM_dy3&>8%2&R!T;(cP zk*i+ys&cifT}`fj^{dM@u5k^y<~6S=*SglVs?Q-fBoyr z4Q_A)x#10OC^x#%jpW8RzOmfoCO46r-t?w&vzy&aZhrHd%Pnqk3%TVjZz;FB)ve^# zx4yO9<~FyH+uruJa=Y8zPHunu+shs9a0j{L9q%Z2y3?KH&Ue1E+~qEJk-OgYu5!1# z-A(R(_q)qI?r{&f=RNN!_qx};AgXUlV*^Bj5ZbDt~Ed*1Wp`Okm8yx;{dkQcu2 zh4P{oy+~gC;up(HUh)!o=}TWKFMHX`*V#Xf4#in4R4S)zVVInrZ>Gw-u&h_%Uj;^7J2Ji-zsl=+uP*rZ-2YI z;~npicfRwT@~(HiOWytNcguU;^B#Hcd*3VXd*A!y{qKLjeBc8gkPm+FgYuydeMmn1 z;SbA4KJpRy=tn;)AN$zHZ_9VS^Bwu_cfTv&``-8D```b*{NM*akRSf=hw`Hz{YZZN;~&dUe)1Ff z=}&(uKl|Cw;%D?{g zFZuVs|1JOd&wu2<|NXE0?|=W3-Q8W;vuDq05nvAj5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fIx}BPHDek*VCt91ii-f7kNuWUq$xbRZ3fyC1C4sQfEWt0hccVC5LIdk^2CotDk?-#YhNOh5B_RuL{L0}k}3@~fu1wsQY z5SZ$u(%2fq0BY(s81eVjH{&>Vz`z`v zz&PZ#S!Ha_#H%B)*_ZKH>Udy_Nnku$tFJUBYhqOi)c0gu)+!T@ha|9e&tY6bb5&c$ zy@scJg8kkJxcV_Zd+%tOa4UiFsjR8ut+;ULl|WN3#(Az+yiC?iV4MY(vfYIszqt>~9yoSi`|DnC-fs9%;Yk)ZF9HiS6>!HYF8{i{sN&>Jz@I#xeDw2{Re&S9@+J^K z6<2Qp-uTDv=uH&IAOd68m1q4yOmPk%;Msr?yK&nuKu+PV+z4!ZZB1_vghOS7KYVlfabkl2aGhjIAdygX_dU_7ep&Bv_E> zb-TnmcAeGMKgPe|)~mb%CgU2UMuGwSaP3H-2LH%SI~|EKJcs}{VXCjUAbdD?Bv7S4 z`s0o~86HSr^nzOl5J(UA&IH!^kNl`JO(qB?FmlP2%jd3huzI=Ll2!ypExdX0t++9$Cjz4vU{4&GrX_)q3vfYg`DjK< ziVO=TP#_<*04LN64#5B!(4D{({)h#*P#+TPuA~+-%&<@XH(CL*__a_?-$TYLz`jW` zUt0pBTmjp{VqBjD=AV7WD8L!TdHH<;Wv(Csqtzc5zCk(}*m-md;J`eYK9Io31QT6nx_m7>NMm0VPrx0mA}Z z{la}161-y)SPF2}uBFM!PE4M}3L{`eV-0nL0l_;ifriG}I5ovNx$VcDzqq>E8m;Jw z4V5{oKzLh~kknz<_S2|I*%I7~fOG9IaKZ}!PDu$EkeRE5q+AK^Nx;>;?Co51cq$;R z+ivzkt1loeRigV7u=)Mu{`KRTmO%abk-0T3Qlf_t$Xsf5>4%h$Z)yT{9n8~K{3JUy zQR0UXSZJ+iUY^n`XB|>JzUc{+duL%kJy9|UAz(psr5Zv?$5#V^QuFfPT>|A6^b&>6 zomGSKSKX=tovg{KiNLCRdGAfGp>|iVs-}uLr-*=|C$SV!C6xdIR(=c@P%^HH2;}{~ zyUbn@QBnyauxw$@J3$rWtcpOsx?BC^Mio$!2_mr6->RKUQzkn>_2R6IKqewC-Kn6mqNpVMZ6tX0x76c}(tZA@v(qx16?Yx2|E6XV)DK)@{~Bk!-pU(5SgVhmmtuspP>iCgR zM*>QP=18k!u?$y7z|m->W_9>Ts3QTTLaR@!W33EVNT9ycI;{%vky1wjI+a$NRmVyh zu984)t5q7g`KMAqU6RV_7GRe;8LO9o%C)X0DZK>AtP6pfRx32|*nO8Cs~(%j(+8>% zl3WJ@3Rk<$lseSMP~`+RyRFZn93km-AfQien;G$C_Z=FndgyKrf0=qtkUzMfT1nx_ zEgHJH+-S3em&S;E2xwE=WUhCWP)H_2%FqG(eLWAY=gXtz2Y z=0}o@+YnGEyhTE7YGF)%1eEG8KagbHj(|!5a`oG;nHi4Kc?FyyNK$S^K;`<^suBie zNkE?fcewkKrIOkut?&66h`b4C5+FC9^VU+E>~-CO zZc_ncawec?{hK@vkuynhZ$n`I$h!g+^5lJ+_T@ijB0VL~VeLq9Rh~apD)1z*t3`d& zCD=1(+zb&=@YY+TV2CQEcoQhPpML9|GLD7_q}N@Mfgz}r;!U9Fe)_F<$~YP#kY0C- z3=A=)lmG%+1Q?Jqu7(JpKSRyTuoU!{VbctytVDl?h*C-r0UZM57vF-KX2p5(GgmG8 zvx1a5!U(9)-z;SwKnUwx_TKY`YY<@eC@G*d0rb}z9RqtHphbVY{r1qzyr!77T!sD+ zUtY@TE!$lc7r?!h!$jE;P_X`G$Bcw~B#>T!Jr=`M*%3g0*|p46!bPB#e(i0_pX~(q~Xsz9sFZ*Pm~y_*o>7Tz?j!QjH>Ja?gl1{yEy{UKJirp z?My!cn!`y!fdnQZm?@zuk0{51x#Dh+Kop@lf*8a}Nr40$(uiUXOci&71fmGd5yT)) zN(v<4kVX`9V5+zqBoIYtjvxkcQc@rRhcu#?15?G_Ab}`Ca|AJnlac}nIHVE99GEKZ z1_?wFnj?rooRkzuz#)w&=D<{OH%K6g&>TSw;-sWN0uE_JF$boKyFmg`gyslh5GN%C z5^zW(ia9V<+zk?lA~Z)3gE%QEkbpxPQOtp<;%<;Y6rnkS7{p0Qfdm}Vh++;*6?cOK zq6p0q#2`*e3MAl=Mig^ks<;~@5JhN?AO>+#QXm0`G$NRH_VDH7fz7h#zPl&-cfZV} z&2RtO(^9*NCUQt4!O3r*vjDd1nVC@&0YrGGb%ZcOkwQ8UaEK#SJm zAf%8E1RUasVD6AKL(LF~AT&n^u0PC(sBIz1u0Oc{(za#R#!VKdH1}V)|7=Z4E$T^i z|9SS7+#+9w7$e~LY!=0A3?=2XAP_}pjvy`4Wr#5X4rxR&8$(GsEeJ#rnj=VybQxld zfI}Kl%*IesP74B2gysm+B3*_UBjAum6tgjul+%Jh6rnkSv`CjB#t1m15yfl_CFQgr z5JhN?AT82mh%o{VX+$v_LrFO;2t*N@BS?#M8DflpLmE-c#!ymD3j$Gu<_OXvU4|GV z;E+ZXvoVyE(}F-0p*e!INS7hT2soq>#cT{E<+LCWMQDy7Ez)I(F#-;0L@^sfNjWVD zL=l=JNQ-nCVvK-88d1!~P*P3{0#Srk6J&?q0B+GOb3-P|m?@z~ArVaGa8ghpfe0dV zg_taWfyv@-jzFp}KbVSg2mP7TQ)oe{zI$W7D28T>zcm7L9Yp^Em_BAhzzR@q&`Y*&KnCm%mdjngdEfK?JJnQS9TOWN|h} zU?}fKpHpfkFqVwn53_Y>q%G-7VvqBT7L51eP*Lw!>e53uu=$*WF~YTL!j< zlzKu4EM<^vXO=CCU`W$U_|99NOm@q_CSX!TO9D$7B-?43IKxa3NG7{wU=tWAq9uW) z4ASki%$#8c2&7ZpD)JsKJ`541ut6Z9=t`lv{IH>>z$zvyU`YfC zcLVdr-3)<*qAQ0s!;?aS2$VIDaz7|(oXrqOskw4&Ge9XMh(K8bDffet#@P&kl$u+M zZH6d?1Q1x0K+=PNq;WMvAgScmf}24~Apr!|B#`tVAZc995J)Py_26chQiwN!bp@n6 z+7TW<@NSzG$KAwV{IV4M^qT;!K&1|U0+Y5EUjn(*LYkdP8vbeHX@h_o_02SIgDF+` z6G*ev)ko#;F!=Y)il>%0-?<{KP^AuE0`)6VGOKUe_}L(kOlXe43##0Ru^}&K6-9#` zGDv22Cd>(w1d<8O71$(YigFNesUV%*ktk-91k&lu6?uZW_-tU3I7Jl%rfqhqAf3I) zj_nu-q|=!rGPj_|AiJVQT{oZSk}Ps#YoCB)5lU;ekDUtV1k&ov5q*d5jD>)b=dLP3 z91DHwtTbNBA&nUa0WEr~<}nWXR9Wr2hGU+>ACE34dgBw|c-pP4QVq*pZ4O)kYm>?# z`RH8xW{Mo7UM5vVpmym|VpIi+WCkIiL~6BZ3{o(Ysv=O^cr8X%q)27}0$P+-pT__N zGo>m5^?lc3RfURV1|XnCX^uPwsF*1g5pc9Uxw*J0qzDzM3_xHZw4&X~b+?hg05vnE z8Uh>bR%cLyibMt=piXWZ3C)Y` z!~{0GtdNCJu_x1Jhbg*BuMlFU81skYu@%|}TH5p-YzniW^cZD0~ipMXH6#i|bz;34F| z1XK&In%uxFm_9mzYKL_nN5@0JfeGl=TQ$3ZVK9Ak0@V&HKaS3afP)fHF1L;JxCJ<< z9O6!%)y=^%TRhc`pA$c%& zTmtScD?Y;|NL-N&6fMV#kJ+nYARbH`oq*y+&Y9ZelWKHM1RR8b)~|bZYHxaCM|co_ z5H-Y~bkfSkR;xW39~BY%C!khdTNCS_1vADcu(i!<9pbYhV*dox%4>UK{lj3!*aWtB zS+PfKSj6j_fMRiZq}DeL=8H|hqsf|GV&fuSzXUXE%PY5jaWGq40$wdv?G%?6(fTEz zT3SuXt?roj3xwHX5?FS4)y}0Umz|irh}AEFTr}30XTM08Egpf!w&rs(9xx*HNgyAE zHD}r<6XuFXAlJuU*3~%q=*m~(#}iFok#;lszO{A1)g1K&g?Zu;sA*%irX@B0Hpmi% z&Ye|*vK3oh;yPiIm773a7c;iG3+0SP0vSuKHg%1R$;nNiwuw0!i=W)MOXZ9{0t=-T z&C5}Em7Mi4CL=e2O7konx{KwEHUbv(wo!vN$mHW9u+cgb23NJ%wGpuKgSU+r&FbE! zHsIt_B9O&jncfhWkD*i~yJ`vebTU&PwaiIuNgz{cd8NH9k{z`Kyc(IS(;hwpsukWe zF;h=n)xAjOMIu9ODx9nfv!$V~XQpi0z>`mzfGMff7gH{meO(0VJ7&SU`boAf;$%}M zuvFTrT}zXhopQnKYa(DqV$FqULQXC#0?l1BbaquTdwK{M641%5(3V4&k8iB1Xv*oZ>I|s=L*ix5AHT(!Jx#mgAA7M1DKG0}rFMnpus0zj)VIOF^o5G^03X+Y5mu)~9k%NF?@pLY2dRM@K4RbF9CV;v1(xB4` zoL)FHNi6}?*Py-PR4qA-JrF1evuz~M18JtHA>@amEu;R+IqX27V9M5)05<|V$gMh* z+kU>XEBtn*x9O`GIc`T_DnH(N3u%RH+wo>pnLr3{dR2Znv})miMqSZT8m*ctgaoJ%KXv<+tjTjbqwh1JIr+BLfKVC2cjYu!#@@5aQa2 zKn?%Vn>qnya2SEnt8D{77(cwb64+?Ks103dGCrKZs0FuHd^kHsv?Q>0e`~D?qdh2- zT*Fg7!Tt~gMyt6};X`m`PG170MvQXTmlJ+N5g4WH7DW%mlzBr4j8%aljPM21B1)MSb8Nnp}8Q*Xo5 zVmwR7O#^|Q^@StH$jUp1NxSmb+^Pb;Mbf+Ti5=J0iB$u0-YXMbE3bTleFX$I z|I9_sx|`=-!Ma&u#eqX*1g34=xER?ms1xceLuDvQrxgKp+HxgSc~!J3mO%;$%o|>5 zuS*4~?Ta)OVkD*Z1X8OiEPnes8L5^)m;};!s|846oe88aizIF`b#jO>kwz!nAcExu;5TasxW%vr+(y6Vs{8cK^vAWVoc zGb7e02rS+sn{_xR!Q1I56cNA3xv(7aYCIV~S0X|H0uX=z1S}D7y!%c|Y&d0!0JWqc z;3+Rpw=^{n6#@`|00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z x1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uV??;QuR%Qz8HW diff --git a/test/shapes/p02_shape24.bmp b/test/shapes/p02_shape24.bmp deleted file mode 100644 index 61e411bb774ee38e755e08b7bb598d728cf1adc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 I1mX+)KN!N^pa1{> diff --git a/test/shapes/p02_shape32alpha.bmp b/test/shapes/p02_shape32alpha.bmp deleted file mode 100644 index 6497a7b0d82aa7004b8c3fc5fffa9c0da5a05c16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 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≪sB=ibc%=ljMh;uzaps_2okKh> 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 diff --git a/test/shapes/p04_shape24.bmp b/test/shapes/p04_shape24.bmp deleted file mode 100644 index 8cf61298637606882c94a3f38a71755a44d6ae12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 diff --git a/test/shapes/p04_shape32alpha.bmp b/test/shapes/p04_shape32alpha.bmp deleted file mode 100644 index 771ebc05337fb29d5d1b94a89d15767d3b54d428..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 zcmeI)JCY<(avjhHAyT49g$5DppiYfzm{mZaj1^%4*b+6G4W_19=<4eH#OHneo-qu& zGBe_Z`$_kkW;7W7=l}ZGAOHQw$AA9yZ~y(5zy0_B{Fk5q{f8g_^y42tKKR?`|Lwp2 z`1^nV{_^kt&tHH1`1wB{um1WEzdrc!zyIxj{J+nafBDN_{`2pD|G)qIw>y6Q=j%Pc z-t`v&0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+z-j`2^&bKR2>gG6)$&O_1PBly&|big9svRb zz6-QZ8YdDUK!CtX0^f7rYXSratdvn|AwYltfwlsE

ZU@Jyg>+Bl5>0RjY85qOsS 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 diff --git a/test/shapes/p06_shape24.bmp b/test/shapes/p06_shape24.bmp deleted file mode 100644 index 4cc257688f17aad0131b6cc65979184feaddcdef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 zcmeIzy^<`=Q3l{oxL9CeVRIe$cwB?70s~uDBol*M!XrYgH0WsK%RCYek_S?tz|M2&}{pG*M z2Y>$mfBNhH{pBCO``Z`4{reyP`G5cV&)@(4_dovr@BjIik01T*f1iKzw@>{=fB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBo5C-5i#D<#k`fjS~U zfIt<2QrCrIqXnvDUY!I85V%et`j}SSc!BGZZ)E}m2wWsE{^SNQNZ_I&vMd1t1hxna zI&HN|;HAKpdGQPZ0t9voygY$?Nr1rr3+x^-KO{haz=wdtlmLOV1RN;@2oQK7aMn>{ z9RdVi3%nRZUlAZMLE!Zf;adU()(A{EZS+WBxWJmj#9IguI3h6on9@FhP69`c0>33d z;4Xnqr;uIAXZ@gXnP|80#yWJ4=#lf zs4Gxq{MAW-K!QNsvrgp%LIe^9Sq%gT)D;Lh%9KH%ia_0AS2+O!nF3W#KXnqgQ6O`8 zRYib6b%7g?HLoTRE>L~C)lYyxzCidfs5}CT1@dQBg#-w65?Fl1c^!dFflfoM7Xk#T z2xOjzsv@vPpvs)8lK_FP0&C7XZy^vR&~=>kMSwspfvAH~F$69Zs5P6aB|u<;z@>+t z#R((`Oc-Q65+G1fAmM~m1A!|9D$b*t2@sejaK-6oO#*ibOq*Z*5+G1r;I7lsdkLH< zP<;&5Pk_KoffJ8GOA%NsFmq;gO@KfrfyKwB*AX}_&}jhmLV&mm^`O? zCqSU9z?$>ZTL|nE=sI`$B0zw^Ltx+8=vM?T6)>Iz2oRVcaOpv6aRP4%Oqe)55+Fd} zv%p)2q=yMyA@Dhn{w6?xz#M@qPE>0W*eEb(&~!?G0D)(LjYp-&2%IkPoJOAzAV6S_ z!0Cso1qo~sm@{HJB|w0{cLG~ZOV1EEQQ*5M`kVj(0@DOeJX$S9;I+WC;nFVw0t8+Q zygoC1OW+iN*CF&R0RjYO3Y>DlT7;0?z`I2TJb*2oTsV@O*yyguoGj?b-7r0RjXj3miFV{g%K_0+UBc?*s@Ccvs-3 zBh)_$>=Sr5c%COffB=Dg=dE86_#t432oNAZV4uK`gVY}c-WAvvIlm%6fB=Dqz`Lie z=LviW7#{)z2oN|f;6fqrmca4IS%Cln0t6lcZymoLo-ANw2oNAZ;9P;pcZ%M(3!Ixe zs}UeTfWY<>*pp)gj0ph(1PELqF!ox}_!faHB49s&di z5O@fIROF$2xJQMzI}9;nL1SwAV7eC8>+E@coQH%fIzZ9;|pkbYsslo8vz0Y z2n@fZy0$Oa1PBlykT1~n4w~Foe(F?6fB*pklkcgPy^Ayf0t5(D5omc0jcuw*>eNYq z009DHud05H3o`)%1PIg;=ywy%?5I}iR7-#W0Rl5`t7ct`F#!Su2vihkb{P$9r(){V zOn?9Z0s}9sPAv;C0RjXF)D`G-A5H6}Zt7G{fB*pk)9$QJ{YozZ0t5)u73g#yP3xs@ z>QqjE009Ei?yNTbiY@^H1PD|YXmcfvYNUGV)K7o_0Rp40tv1cdEdc@q2viqnb0v*x zqv$UL7TElfB*pkodgZjt_fDPe2oNAZp!Y3Sw>!xsK!5;&-U4-RsNR+LPMz)u5FkLH z_bpbmJFz4{fB=CB0!1&W#$``PogN7gAV8q;MOL&mnIu4f0D%btMK7twWlu<*9tjX2 zK%ntOR*q1aCAV7e?9D$1WRM(p4 zq)w*<2oNC9^)9Q}moyR}K!Cs;fr|H3*P7>~PNxJ25FpU?F00s=G!h6As5m~`YYstH z27&FN_2i`jqDWwYz@-^(w)leW@CpLWrlx2+a!BA5fui{@SN18JWf219lHammIV7-A zpk@A>HMMaoJw~8e@{6`3hXh^-6iv0VKLlQEtFH){kpuxbB=Ds`LO9iMT;R*i^&x@d z(XzsE0XZb_S>Sl0tdJ@2d6)f7ATy=Ys**zj4}odPpV_ap6EN>NvoDRq1#+UOl9d9( zW3T;{Ve_sp1%z<2z?YHm;V6O0`PciXs0TJHfdd5sbEu@-1qKd+mTynp@B$=ol)&(` zYyX!5qsBqAzs!RNE)|f#2?Cc!$l@&pCd`E%TSm7~Qxe!)pimT*8Ys|vI&>Epxltua zU`v5f8P@CqftF*UsRhaLiWdSB*i7KXUi*r`L4jt&qMd_z@biNL64*)LU>N+Iz%Kyj(1HK=rlEYnVjT%dzZa7 z0`~^V+ouV%861sFi*8Q8ve!c(Cs8VyBhX`ZbTKEfX`RYm1A(+qsb`KrgYnVAoVccS zDtiqC(n6)4IRXvFM+jK=$eitjvjb5qK?7caBv4dS`umoq+5W6}T=E zRwl4dpy((md*62Z)o}sYt0-`M->pF43W18#q~zq zMP>MV1+SvO@X%^MT%h7isX07UEz6U-asn-LsHtWG<;F_E%@SCm9jU7&P$E={B=8|n zYqC@;wCe?=u8_d`cz7d$BLannOQ}aT+Hdy>NL?X;eOv5T1nv?jG+au(DRa2BB!I70^x(EyqU4Qw`-|O7PvPX-cI0Lf#g|J z+qrvfwJictmn^Vl2R%ceia_$LsjW(iI@Kw4$pW2{rWXRqv!*urTrVJX$pY*1;Ee>X z6G)ylwOzOGR{l~zZptf~tDX!oYmMrkg?ehSEastT{r?zr&DqXO=#R`Z?OWW z@3jR9gb2hAox(yAGNcT7ixn7>Ky3~bh#fkG4NT*WEz4W1z>TT!Y66!E#15UpF5P#F z|0E!9u>wEslz$RvBM>`u3TukU4j%8XL%48ke_Bfm_1hr397{ z@|Gs>?hbmMKwW{f=~GYLELE&r-qHjrrbx{M_6ej-pL+J~qhIY4khe5}ef#KF1S$%o zO`m!yrl@Ys@|Gr0H%lrf@UB4G^r`3F9rXMW0eMRkII^35OQ4oO+VrWXR(`5iD{pB6 z)f1(D0^0@BrcXWF_s)~Y1>`MC;P{4Gfj}*Rr~y<=t?*Q@R^Flns>ezF1l|>h8bHOo zyM3NNA|P*30!OyeZwXWsh#Ek}RE$vFn&mA@pl*;{qW&%e9q6SbgN4C;$-xZLzD1mpk&+`PT3q%c|Vyeff zR{io8B~U9oswHq-AZh>=b9_Usuw6jjq6D^YoF@tN5QrK;#qEt^Zj--f{#!?~A_)%n`_$L6yu&T|%ewmLrgm z2Q?5_FOV~XDp|k#liw(BIRcY&sQ1YNIWwq|$vIr#yS(KHtlxcaB#FPU>_@;Ilx^465YwzWDoU0eQ<2xO%UxPasnuX9iW0nUJnk$y<&<*No|lz-xh= z8C1#Zo$~Fu0`it4aPH1pjX)KFoEcO}mCW?0Q{Hj}dL&901l|?MnL(AjyLX;HA|P)$ z0!Q}IZwb^D$eBTv)J;*v%H=IbpkjX1OyIac&J3#L_-6EMdUgRxDAU`cCByfd5&J3#Liv6|bcLMU3Bk_U%GTeV2eP`460 zL!g#G&J3!gR&uIWD{nah)w8620{aAVW>6*jcF?c(3CLTHz`h;yD+1L8a%NB^)w5Kq zetF9gsFfVm5;#jBX9iVr)}C5ti-5f42yEFe&k*P*kTZiS>6fnLj^r&zAUP*$BXFHS z&J3#Lx?Q&Nvw*zi2t4nOPY6s9$eBTvOvqbKkMfoykdq3P5LhXYGlMEwx$oX3Z#e?e zNMNQw&J3z#W&-c(THbO5?#h7o61Z0&X9iVrZxW`xUEXp8re#mR1Rer8GpG`oTqz)L zIRY#9-Ma|n2;|J5N^(*$p%Qt^5txuSJrZ~p$eBTvJnxQAt`m^A9D(b0*~$cx1#)Ik zCCNGISDU=$2=q&rjtFcK$eBTvY}qf*oFyP{IRaueE_w;X{j`{fw|{RDDmP$m7+mE4iM6gGmAZG?uB9kixF<-U6tfgFLH8B|G5DkfAS zZ#e=J@}@@u&jL9!sFLU1@yT@p@|GiT-7Z_1K(av245}nKC;e)Zw;X|f>CzE_Edn_+ zsFE%F<(abt=VeDL6z*=LBHB3Aa6MW z`*zT;2virynL(9Q&r+@W=PAXJF zV5LCL460=1zI&Iv3q5y(k}N(ihJ$eBTvtlW3+lD8ZIX(TXH zAZG?uGBbg9buDi>0(WJ=dkNetkTZiSxi<;Z-Y#!Z0@LEBUjk7Bs2G7ATm=ipm5_kwi4WMGga;1R0MG36jdha5TAP_Zxib;sXoEqdU zN?=a#bV}eM5H)~`5zCbV@)jkqa_hZ|K!QNj04gRS5_4*hwSxQ3I%$ghfQm_o#GD%BElOZc@N`Px zArLiyiV@3|0`e9muyX6Yi$H=v)Bq|bArfUXk0+VrVsavIn7E^lc9>oeeu1nv?@n?Cj2m4un^ zmA5p3nK{(;Oo6oNQ_svC-qp3dr3u`X1n(uVULbAy)U!SVliw(BX#$hesP}0CY15~k zX$icyUwKOtxHk{pPGF@#+VrVslb!1Ffwgg`%mz|m7uznCR=ByWKN$$?QDfwKexM^8y-ZLW2;2*_KY zz?O~k41wwbfupCS>Y=Jtzr1A%)Jl zvuR|~`rox-l(dh34{khfTY&)ej00-Xe6hfZOgVwT^F zyu}LShew43_6fueox=8Qs9)_9khfTYeH-dm1o8!9hfZPn;ptSNyu}K1ikV&rd=`iu zI)#1SCVyWoAaAh(S8u)b3EU+RJ9G-WD-tu`D{sjHGc&2{-U7)Jr?%eNOY2VFk_FPz zq8guK6;Ws6@lc5Q(Ki3^{7+ck_CEXOcw+`3nWjR+CJ}; zzpoaMw`75Ti{wg`a`f#g|JTS!Pol_7P>0;8g++4cg-v!=H8@e6EF>XHQl z1EVAYy9JVGO>Mik)emcRzvMz z*r3$q3k1eSNd(>!$e%J5zO|tqK1D$4N(h{?*A^jgi$IAHQ{*k#82(bJt0FKwsM;?o zP-VW#c5Kr+}_)ehc zC@K594fXle0xfewe143*Fa$Vc6*Y*xdIKwM+@gh!fM+EWUq(7_8s>mfwKg9%#JS3%7b;@ z6_C9)0`G3U=LsAUXfrq(IT8cEJt81`odk{~!EXs{7w9xKdfC43o;+7T_Bsiin+>ZG z_)ehH)ad2AUH16`0rBf3uplsAFKmsQSe7W^LB=ACD!d&R_ zMF4!YKtKXV2`osISCkeQH4d6Boz(`#OW;6(2D#P3=>h`>LCdG7$bxSPNZ@3Fx1!?V zmI9OWulJUbuGN$f4i~5uSJj>+Fg*6!KPyPqIU*p31RerMQslQ)1f-pSdC!?vX(aGj zASanBIalEGF8iCnx#_anJ^?u-@TI`MIQdnYz?YlrLjq|*omr0@5_lmnb0~Ur{bE~v zMW9E>t9K!X1U3p(kNSlAH*TfJ2uv7<{2t|yz$pUxQSVXVDVt>x0zJl|dKYp?V1YpO zF>1R6|Jn--*z009C7<_NU8yc#qzCv`d{ zK!5;&2G>@b7Nn5?0RjZ(2(-Dp8Z%st0tDs=w7I+*G%_c3 zIwe4W0D%VAR+|>2kpKY#1m*~|xx9KbGADRCB|w0{WPu)cR;Ml|r%~?&2oRVf(COyt z(aW6d>68Eg0+R)L+*zHvn4Ctv6CglfjzFiIt4A+$vZqr51PDwP=y7Lt>SA&l^-h2Q zfjI)5Zmu4^%*mck2@oJKS)j+A)vSxjfz&$z0t6-qG`qIiv@;=ldL%%Az+{0o7gn=I zCTCLb1PBnAAkggEYSYey?CFsJ0Roc++FV%u8krnRy%QinptnH3JF8Piy|bq~0t5(5 z7U*G#H0RjZN3beeinl;rm zd-@_kfWTydW>;0qb|&Xj?*s@C=qk|i!fMu3*X-$w009D%1)5z|E!&x#PrVZ$K%lEY z%L}VtQ(fbyF9HMz%oON%Pj&5RWAV8q2K;x^bYinJjs4oHp2+R@adPDW@Yfe6ON`L@?t^&R9sjl61O{2aD z5Fju|pz96QyRSL<)F}Z11iA|JzNfl&*ENm$B0zw^9D%MkRQtZ>L{z5)2oUHe(EgHY z++e>n>WBaV0&@f!Ur+5@o0C$V5+FdJpFsOds&Rw;(x@W>1PII#XnZ|QXl+hVbxME$ zfldMwZm8Zpc1ojO2oNAJN1*rJG^D#Zan&gS0t9*p47r}#x7j0&x*$M+z#M`07t@>u z=Y&?L1PBnQE->eAn$T(WG^(Ef0RnRbCfrJ+dYltoof05Gpsv8Ei)l!+b1*bfOSfM0D+1E({80X{Z>q)nh6jfFh^j{eKfGsIWg8L0RjYS2@JfFMzvfk zjjAO;fWRDqQJ2xcX6GbXrvwNPs3kD)N}ASktw5@l009CM1g70YGy9#8WIYlfK%kbu z%=>6y*R^7)S^@+J^cEO+4UKKNcan8SfB=D70%I?unT^*9r)mihAkbA{<{dP->#j-G z7XbnUY6(ofiN^L`E263;K!89$fw33R@W%TkSw{p25U3?E{2H3veyyOYmH+_)odhP| zK6>wzWW5j|K%ka@J7~B-t+=X|009C$1cqNd+W!#fkz`#EAV8p&fD4E~t;DL9009C$ z1l&FZJ_LG%Sr-Hd5U3*H>LKtDsFGN95+FdJhk)CMzz=~Qk=6wP0tE5}ejL31An*{# z53LFb5Fk)pz>P!TOM&XaRzCp(1d;{5Ja~Ob;31G4U9}M)K%lOGTZX_d1?t9IoEckfwTathX4Tr6$RWW z1a=5ijJlc$5Fn5vu;bwM69Nx`oEWQw009EE1l%J84hqx?ylM#$Adnz%@Zj}x0uODyWD2+u2;3r&IS#5KK!Cs+fm;q=t`52N2@oKVCgA)hkRy;b9qJ)K zfWQ?3Ij62l2>cMZBI?#8K!8Awz>nk39|QsgawbJ31PBl~OCa#DRT6XSvC?~LHg1m(Q0Rry|lsirpOyFICcZb6B1PBng zTHxJt%<}~53S2!+)+a!Kz!rhJr>M#a>=xKE8lE9QfWUPEyN@qFB+x+My2-LK0RjZR z6KHUFYJtFUf$s*y=L854xI*CgsbvKModm9!GHVhbK;W}Lr!!M81kM%sJSqMrK!Ctm z0_UDoRwK|-;H+`84gmrL9s(_oN=*^CPQcMYfB=Cb0@s~RRwgh+;K%^_Edc`41cn@p z+9a@2VA?UFUjhWS3#>egyoSAz;=OY$CrKyR20}g(Viqgpr}B_qe;yK`Uw<0K$J~@z*z$Qjx`+- z$P_qhX01bjKudwlgG*HeDhjkbA~Z#Sz%qe~=boAgtQS}|l3qlBz)XSl$C@`1$P}1) z0_d6mfe?YrgHcrkt`Gk#NVBl;ph zfIz;0JE)dGexg)JfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk K1PBn=C-8rtukKL* diff --git a/test/shapes/p06_shape32alpha.bmp b/test/shapes/p06_shape32alpha.bmp deleted file mode 100644 index 04afd793cdda60d227071d8022e15d1fa5c590ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 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 z5Xd0V<9lTc0tCte8O|6r5+Fc;z&--yubEZ?IR*CF*(xDGfB*pk;{|fwCRANZV0?nj zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ P009C72oNAJx4{1aXoNQV diff --git a/test/shapes/p06_shape8.bmp b/test/shapes/p06_shape8.bmp deleted file mode 100644 index 017c1ed776f8251cb53531f72886485ca40b91f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 K1V|uy0{;hh#my@K diff --git a/test/shapes/p07_shape24.bmp b/test/shapes/p07_shape24.bmp deleted file mode 100644 index fa8012cae8c048e538f84f559f5da1e5bb05ca9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly 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 DW$&PM diff --git a/test/shapes/p08_shape32alpha.bmp b/test/shapes/p08_shape32alpha.bmp deleted file mode 100644 index 4d1d25e9ff436183f32abf468cc48667ee16887c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 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 diff --git a/test/shapes/p08_shape8.bmp b/test/shapes/p08_shape8.bmp deleted file mode 100644 index 920f9070ee08a5355fe5872e097f8b6d03107ecf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 zcmeI51-$J>5yt11Qc98H?poZ7Qz*qL?(XjH6pFjMySux)ySr;~zmIH^O?GoOIgy#& zN%FlPG|48JneRVeHpzMS+;{My2OhEynLh{aO>{uEJZ!Jx|2wpAK5qVV#D2y9X{Q>Z zot+)pYp=cNNJlyn?Y;NjbmSu+nfBRdA3DlWjzatHyDuH}s7Iy!_S=t+cC@3>(T{#~ zI>s@MLB~AiF=_w(_orhW>sWN`V;`H2bDZPQagTdkI^OY)N5?<@@#zF7I02pTgeRmE zo#;e#;uD{kPI8iy&`D2vQaahmPDUp``N`=Nr#J&w0*6=RNOv>3ruqA02q$fpq@!pPw#pfeX+DFL*(^ z(1k8U7ryX?=^_`o2wn7|7p03`>|%7#K?l*rFMe^l#3e342OoSeUGkEbq(crlgf4Zd zOVOn-eQCPPWiCUPz3gS_a+kXtUH3H3UtLQUXczx^iaCem99irzVemnDp$D* zUG=J0rK?@-YIOChU!AUTjcd>~uX#tCO4 zaDyAr4R3fuy3vhpL^r=@E~31U>SRkEBOE>QVIQ zM?ab#^O(obV;}oidfek4M~{E}i9`qSwd&v*ts^O?`2XFcm#^z3Ipo1XKW=g@PX`&@e7^PWe~fBy671uu93z3_!E zq!+#DMfBnqznEU~l9$j+U;0vd*~?x=FMs*V=@qYd1-ucTMK>Q(gWSHGHG^P1Pt zYhU|Xdfn?@N3VbV>*)<|cmuuhjc=qkz3EN#<~P5Y-tv~W&|Ba7R(jjp-bQbK``hUq z?|28j^PTUccfIRf^zL`Ro8I%D_t1Oa`(AqA``$QnUTPk)*|^O?`kXFvN{`rPL} zN1y-v=jjVy_yT?Li(jNKed$Z|R0sZU;mnZ^PAt$Z-4t+`rYq-N5B95@97VJ z_yhg%kAI{ijyQt;^rt`3pa1-4`paMbLVx}1U+Hgu`y2iJ?|-L%{No?=&wu`t{`Iea z(ZB!wZ~D)F{zL!$?|sG8A!EG0s;H&mSgJ# z0@YCo1pMa?MXd$N)MIij@2$Zk4ZH5bsuMQCe zOB2|kfX}*yqzgj)H4(_>z%H|e_pJ#Kv`P~Qdu-ciSrtB_mTu3I*(05SVL5R$ z2vGT@H*2QpOB=Dt7GJMx62W#&V7l*|2z6Mjfj}Puj(M0?-K=;sc4=UJlK_+HiZIm! z;btC;fIx@IhZxy8xQ_)7=CV}3a zTik(764*{aU~#V6BFMcFXNM*rj+7OF?D=O)yH>EfqJfnJ1Xf_MtrGEj2NM{tOu4l= zt2v+qf_LJmW?YTE`UtJa!-N$I;T8X*u|7>&_%S)}%zv<;u=9%VMJ(J+gXCrJ#>MNg zGDx0;->-A-UUWt`bYpq)1Mga{NIG5@vsY2bJWF~&j! zoR<@au`wdd=l~hG8X}Fc?F0s5#^Eglwv)yY_Af=6Bn(o_eJ#f7IoxE5?N$QL4Y)q0 zCuSVhLZBu&<2B=qpgW>yY9Wi^J_Mq4C{_}9uuscX9TUqM;(2oKB{E=}6hlMdaj>l^p>ccR4yCN%ct=j~ZWpCQ`w!AJlVx0;`mowcpb2gk+pTJvJ5sA@ z*5hmkuNi0mYF1PCXkdQRmqEQ77@z%cYoxsBL6zGx7rtaCE*Wq{FC@$989T2U-fL-I z%D=zr*+6?(p}=&qXE)7ZDfLwk*e?5?wY#S*cRhn)yQ_XVrVEPnjVXT>=cqScQQ+ua zDAG4t!(vY?Zc&O_)K<#K4ye;NQpXZcEB}b4>T@$(M z5aCrZQPILq_t5Cum`q!rBva93S<4Bavq5E544BpGW6-vU5Gg+=+hPtDzWViY=q*tb#(i6@4s!ykl(kUVra&FadT`O#Kb;$};!=`kGfy_h^K$3oliKSY74Z=)v zXBbB3Etn6aDt+F)*I3XU==;~(d~CEtYFvzoH?y8FgGnrCKze53a|t(qP>e&_vE@a( zb4?5tBXjuT%>%>={)}WLbD98enL@>)3J_2p(ti{Y1KTIC2&q1absbY+SoZv9)oFT2 z=d_>Im&Md&uC8k8=L8ppk>bd4cP(SR3rWmptT{>z~UO(=v#RoEn!Yb2Gq(6ia2k!OaRs=OjnOz_H! z+bI!U=JusP8w1G#&r)y33O7Bw_K|P^_q50+XQcYdp`Zk`>P^OBp=z<5IFOpgXuqV;g^IaUZ)%CKp<3o1`5OfI`1vLvCs zA4-$M7L1$;mb;w)gnr}ygaC!&`<{7I5aq$*b0>dmBaC*YO~!VQ>{ zysSrLqL&Vc_!eB=G%`6mBKEUEIXgR_STZh=kD3#<&l53li%W_jLT3(fw5$p23>cXu ztA|fW~ZMJ0sO{r6|v5Ooi2{&PlNi@YzTK$#1i&N~Hc9Za}$ERj8^3@-VltxsdtT}<1 zxvuJ3N@i6N>??^>#ZPO=<@TGQ2jdefGg@#W%VeseChkBt7biyLNic`@EmuirZ31WwKV4ZIjKcVc}~xn84VBT z)WW^$O&!B4({e^W{}pVCFRL!dg9;dPyRM3-KpRg9m7?XX@Bo?=MGUI@;54biq$i8v z(GWN(*)q8p2MyvT)R5hFm+^wz-rxyz7*B1lZ_*yd3ZsUyue+1P&*J2$Slg2cu`&s5 zFWZyr+#`fUS6D6Rh3+z1u_De;<&{ zszq&I<7CPh%d}^E@jZ@Utcg2RkLnkH2scx{cs#dYzIu2gg^iWpgV!_>@B0uHEu;fHe26pb;Fzi4gaf=^VmsME(0jC$52-cc*qg|N39BYFL2$&Y{aBof!g~FP0Go5a-UjPcnl+9 z$xvnr8Py%hqWZ@kRr(rE>W?t>k>hT`sjJTN*EVuL(Oc?I@YQPjtSM;EkP`Yx@{So2 zT;y1<8f^FkM2JfV^(Az?7E2ehHGZ>FZ2JVZ0@QgxpGU#Om5+N?@Vm44t;9W=oW89= zlLHS3V6KJDKW&v^+##@uP4S5Bvt8O!9X)2%4kuXJ${H0Fo9>H8@PPFVCTI~;%3a%P z8?R`d-AcLizA_KfbzM~{+r*dKSg~nGzUYG@b-~8IO#*}9;^0mK8C}eFn-=RF=>&?M zeF=0j#?E#EeF5XRRs!vCv1cm*C67(5&DFdkW0&*AO?Ru!S`X0NUzN4h7i=q2?C4KG zWsmh2)gLg9>?EMS)%q%Q-*R#9?X=hSo%-6VyQ1wxal{Y;_4ADGzH6wijVpeNuZ_%> z@$BxQ=5G!(7_6%X_pZAID|YuMkRitu*ycM+raw+yM^;a#*(XKSx~>x2&|};Z(ABTu z)s#AhpBUu~OBqX#Ksob8X@Ou8N0VTdDWRPTv6>UGH{JX%H?q5y(i_+IrW-Yx80D7| zTo)o>yE|9&Sxwc&D(9xLDRa82>mC@mZPxOk!Moqh#`l^+BpW3xh z19jhkLlv)aEbEe5SM@7wOV|1ZiGI|Us+YXGoEVBlbnp`s`m=J6HciYYb$XA=7k`Kp z+emSX{*+f!YqKI1Gc-+Wy(`&adHM5+9o4%m>&?4V{o@U7Js8mZ^%}X7x=Lw|^ zX)ViG&b>?qcBnOO+8qN`EaY&9x!Y1_Sox~ghx(fGhMkS<2&ICYB3H8NO(IIW(pFY} zv5e`{F8ntJ8}~VFeVxsCJCN2%u-u_kV!NP4?a_M!>hFt*4auG!6+UZB6g8LA`*&IC zk<&pNVfqX>U6;ZL?!8FulTUx6=Y(BNqmcK{7wgD;J|3k-<4NHLl`QpL_!~`bmRM}t zAE25}d?TTbf$753M$iFxcomfsLuA93S?I{dSa$QR0uQfA=8UYMMwLt1)cCA3sE6i9 zN3GZFa$0i+rH^#*&LaI637%M*+-E$db1Ykwt7Z-?3vmiu#HyGnA_dNx;5g4&o!p&B z0tTj;EGu?^jg~kA1GOhPylVmyWtl|n_N1bkBL?5DROJzs9pzD})W3`eK%HoNR8`nd z-g_oPk8%f=W(><#Jg{6Mxu%mwLl;FhX&?v^%(aQrk-g++}FU$B_b{5Mjkn$yyl zFZ*245WxI56u*0AD8x6+)s?+Cystq6&K4W+38N|CoT3-NqE>FWtr!sXIfNXb7t}+90w(h z?W~^pVl(Vnmg2((bzRNDT0dHi2}rT2`j!?G7jv$@65}4nEHV@>pJL;xV$EhB6O6Xl zw~G+Zkz=e(*n*7|v-LFFsQg#yuvMEZ&{np3rGXZBg_bmbU{L7DDB zI@gu57KK%5w)e1VU?wXiotawB@2yVcevK?!MYnXy9a0qw3_U@HNRM}{2%mW6OJ(x0 zVE&WhEbw>dVx`6k?0au9Te0vB%rl&C$80b#cbdby9!7`L(0@kRuQaf?W}U(>S610E zOV!odt(7D?psINai5Z-m2=BJEQ^^(f+m=P|{=$A!Da_$~eLcw7?~Ef?O?u|^T9|2O zHJ{YO`qsQ6Edo!J9bCvV)26QrrlN^_b&Bd=)kOJoI=w%Xs7H=R7`04+WaE|3@67Bk zLIntNgdE9|BX!CcBW2I{w3M_va*rU|5p5Q`Mo3=3DcV|7K7((N-FOW52DGUdTF-{u z)eHyyJ*^&@$6B|{HSEp$q_KG+ z^!22d?VX3ex~dFGT;EvXK6MuCY(&}BqUikJt?ufxqJ0%+SDtrSxjR;|u5$LPK7ros zO~_4ETSGhbjpe@DRJIDcZHUy@o}!|SLd}5IV*A%+Wx;+WiT>!~9$A#I>|psxV=#1#24wdU1?@ zP*G=**O^M<7cxAfEjOPIH+W;fCor6EoHNR|jl7Arqj55`WwD^w`*ddsbSyL4Gi@)M zPXq$(6i<9`UWfCFT>|h|9J08Sw?fAO6@e9-MMQc97Aw67h%{lPL3;tmK|X<%dS#02 z-~+Qy6*Yu|F{Lm{>Q67(s`U-hDR7w1ev7oWJ6h?p!rRZ4Nche2v{QqS{-Gm@{?DUvk|2V z!6c3pta=2j_0s?Ja$Z(lj#FhZC}$hU8ZPm718Q zei^=Qm4kWLvQ(~3);Ac4#uHSw#uPObR%TrjM$;8#>Z$%r)i?9=^O>cB;jZZD7z19_ zZ@~=u<{iSdoL$#pJu_()Y$x4*O$aMY*^*7)TrB7`(yS_L$7VT9T-DBiO#0>(rZC}V zv$c(|&JNndW%aP?({4dK^Udb>@MX^chN-Q4GGA>5MIRmkjHxsie+yMTnFR8b+MoE+M&z!a9`A{5QWj za90eR1{`AIQU{rT3f>R`^jQ=uBBGnEHDx)oV zR1d<;=RYx+<|DwwY?e0nnO=F`Tfjy>pYQPBq>@j7u;`&f`W7&@yGQQR7t^DZh@yK$ zDq%{9^0`GnpO7!VHG`BJ;>OM8WiN4w-{V>-Pu!8o66HCuya}h5vP2$hMUgqdGx@pi z7HYntyY{nmM>pT<1OrVwHIp!F>s3!Ki}qgDV?M71BTaMB=(9`r&D4S+*^BdGDJbX~ zj=`e$A(ZlCGoJk9;poX=EXZNCju=TU+m3pa?P^TWdaMzv67hb-65`|$*Cdj_5wN0F z5tMGw_$=M*Gg*%hNlQlY21OStu81!|;}JQ@vr6>-I0-Ysd@x%gIq9OTmSr>^tXhgo zK3pPMo%5^}#2aA0hG`Q@FEc?iv0nHuCs*b~asSbdwBx+^v-;dGue>%~z2-?;@P_?n ztf&iP@|)4*moabnuK=|s7s7v{SKhYZ&Xu_)*EzD~Uq5jF?R25ri>3aIi>I-%(FuoR zC*D6gDCTcUi~ZTEhSdU_*{t6|hi6wHt>{o$^=w{(^Lq2!Z}zjmqGVJC=P_AFl<2BE zYSFx_Taw&Qgf&Tr z@AN|wpq&+s+*t|{gIU~KMiw{mw0V6F9cn=ZV0STwt0Z|VA@Pi3Uaoi>v-*3uHryqy z%7E2MJdP1E;rmBz{ZBhyzM4dEK*AK+B_&EZowQPx|AHy1l`(ju>Vo1zKOYo*R!ZkT z+3SkYYdu4iBo}rM#_!+g*?tv=CA^viQwyRMthz^NL1BWS8~5I3rXIRyc1WRci|i(b ze%pyj^eb|9M}?`*_VF-x9)ADitZe96aOTg1V&L)ncg4_}z@7)^ydgs=n^qM-kxl%6bF#!zbTj*QeWoWh;|o?_U5jPm@^HrN*ppKH>UXAmNdjRSZ$K z88D%gU}|oC+U?h9WRQujLDsiKUDEPuSoNv3U)Ps;6gI^#iHWMJH(ysFlfF5JadG(T z=^vKZW(Z%Hnk_bc^EF_8TUOJM%|aN+s-69eS_XZ~2vN4anDo+5eU%fZ(#RaCF28x=VW!5o-N6&zT7`^|Us&6Uw^Bb(GUz6SvH3?~{Ws<(7*e{@?1y_pUKy`hF zRKNMU9Q%k_b=4bvZt-ieR$rYit0e1rp;?FWCiUr5k}Ah1 zwTWOxusGioFy_uRI_4!RbtKSZOs$r<4?o^h)(VRdC#u`BU3nB4uN9M*jjOf{H5H&E;yLSQibb)Qh*ErvkmJa%Do;JWS9 zQ+@3^|Afj{5l!Kwa#pKK=C%*yA{ zZgo{McVX4xHk-SIC$vpfoFl6?48QoIHNNfqEzai6KNf!n)*P{Tn4Z5Y;wf0OTLiUN z4aD46p$M)B_FzS!gC8OUd1KHgkeMV1Z$;)|mg?g4Sz~LH05g1q+aR#X93wS>4O|%D zCs5I4@5YGg+Ttj;_$V;PU{)fEMyUcfxtRF$N&x@*a%n;uIF)(4IKh85wIRy!7}?d z2biEC3@d>Zc(0VmiVeXg5y;<7vj5~uYr!SoiZgAKfZ=2j0@XXR_27b+A^;JTjlhDf zXQZ)lLZE2`?3`zpZnPzOuzaj=Wnx`10R_KzP~tLBOdO>(2uSolbp`8av(@3JUzX{O@G70E;CtfCBsM;h@{PkS+-~3m=75nWZly13MCq@=aps-*= zUOMlY%#C8OxlRH>6GnJZ&VTh)@UmEEAJ(keda(F#urQyv1=kE5+BXPT55`*N1z`T$ z=);-^VtLQx$zO-o3>(@@0{J9V*&&t(fgc2X0@jBuKSRxIOg}faK)?{lJ!n>#-L@Id zB*CAx6R>`>OP9x{XBbD^L|6xb76P8*I6snU$%kPOXc90UChfA_G(#U1zKG=_|7i*0(!h7Yj<64P9HzNTvfz_YN3@{^p z@g!px5Xy00uUF&jAV33wNd(N?=RUwW9&}gR{5UB$P6mM>0qeXr*X8?n&EDYY7zBaI z1gr-;my@#~00?*l%6oCK==7f1>79xV5a1;-|z1kBu5yo}_b{5$dF=m-D;g9+3g9DFKH009;Pg$G$e zAqWVJA&`Cg=iHdbM8G*900JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd& z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY J0wB;N@P87svs?fG diff --git a/test/shapes/p09_shape24.bmp b/test/shapes/p09_shape24.bmp deleted file mode 100644 index e5a7c0043d98f084f9d91d099bb33bddd47a01fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 diff --git a/test/shapes/p09_shape32alpha.bmp b/test/shapes/p09_shape32alpha.bmp deleted file mode 100644 index 250d267d1491cad72a1c13c8eb0d43e07ce2adb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 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 U0RjXF5FkK+009C72t*P1f6jE^6aWAK diff --git a/test/shapes/p09_shape8.bmp b/test/shapes/p09_shape8.bmp deleted file mode 100644 index 4d1cd014ec313dcbbef5ce5655084c4456b8ab69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 diff --git a/test/shapes/p10_shape1.bmp b/test/shapes/p10_shape1.bmp deleted file mode 100644 index 42b5a7f347490c85a373aaaf4dd23275b6eccd9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51346 zcmeI$u}#B306V-0>nc9D~jm;Dd*Vv=Zo{o z+}v(nhV9tQ$NPD%&vtVh#$A~E<;8B!Y51JOFzsL4i?5a2a`$-kwmq2-tJUiJ{Q32I zzUgQDzGwgGG#xD2f82Wl2_%p}0tqCLKmrLQkU#@BF0A z=9`!Mtq=D<_G(=2_i)++zAyJX_JNk`m;3d6OCi3_kA1A>XF}ZbV;`&enGpB<*vD#q zCd55I_OY6u331PleXQnZLfrFXAFKJ95cmAp$7+5i#63Uuv6`O=anFx^tmbDz-1B1} ztNED__x#w$YJMifJwNubnx6@A&yRhq=4V3O^J5>Y`I!*+{Mg58ekQ~{KlZVjp9yi# zkA1A>XF}ZbV;`&enGpB<*vD#qCd55I_OY6u331PleXQnZLfrFXAFKJ95cmAp$7+5i z#63Uuv6`O=anFx^tmbDz-1B1}tNED__x#w$YJMifJwNubnx6@A&yRhq=4V3O^J5>Y z`I!*+{Mg58ekQ~{KlZVjp9yi#kA1A>XF}ZbV;`&enGpB<*vD#qCd55I_OY6u331Pl zeXQnZLfrFXAFKJ95cmAp$7+5i#63Uuv6`O=anFx^tmbDz-1B1}tNED__x#w$YJMif zJwNubnx6@A&yRhq=4V3O^J5>Y`I!*+{Mg58ekQ~{KlZVjp9yi#kA1A>XF}ZbV;`&e znGpB<*vD#qCd55I_OY6u331PleXQnZLfrFXAFKJ95cmAp$7+5i#63Uuv6`O=anFx^ ztmbDz-1B1}tNED__x#w$YJMifJwNubnx6@A&yRhq=4V3O^J5>Y`I!*+{Mg58ekR0y u>9^+PR>$Rj(~0As_p{$qPauH=5=bC{1QJLffdmprAb|uDNFaef1U>+I;GfL^ diff --git a/test/shapes/p10_shape24.bmp b/test/shapes/p10_shape24.bmp deleted file mode 100644 index bc1faf4e7b4605ee27a376685706859529eda898..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 E0oy;U=l}o! diff --git a/test/shapes/p10_shape8.bmp b/test/shapes/p10_shape8.bmp deleted file mode 100644 index 64fb5c372067554fc0d3d7f15fce0d17397a2591..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 b1-8Hz*aBN%3v7Wcum!fj7T5y+&jtPmU}+S4 diff --git a/test/shapes/p11_shape32alpha.bmp b/test/shapes/p11_shape32alpha.bmp deleted file mode 100644 index 406d20a815ee196b67353bc40614484a8c6d76c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 zcmeF4F_NxZt`+a&nOK-O#4{NOJ|1J}QD9)d5itO!ghxcvr%&i?l`2Uu>#yJ+`G5M4fBp04pVxo> z@9%&8_4~hHx4-|(3;y~a|NFoEzqtPGZ-4tU|DXT+U;kmef7yBTrrW@6;5Kj@xDDI} zZUeW0+rVw$HgFrb4crE91Gjwn*J3rRjvG6Sqm-CZ*|wrW3bG-6o~!gr*a>N!=!;>4c^ew@KY5rRjvG6Sqm- zCZ*|wrW3bG-6o~!gr*a>N!=!;>4c^ew@KY5rFrCAH^8sM$*22qoAmm81KgAow@KY5 zrRjvG6Sqm-CZ*|wrW3bG-6o~!gr*a>N!=!;>4c^ew@KY5rRjvG6Sqm-CZ*|wrW3bG z-6o~!gr*a>N!=!;>4c^ew@KY5rRjvG6Sqm-CZ*|wrW3c1e&YuG3nBeNY7&Cp4Y7P3kr&O(!&+xJ~LdDNQFd zow!ZvHYrUfG@ZCj>NY7&Cp4Y7P3kr&O(!&+xJ~LdDNQFdow)szx_R_lH}Lc8=x?9y zr*HU~T%T{?=a%}L+oXNN&xEFvpH_c!o3wBEnb36d)9P<-llBci6PiwbTK&y!(!Swm zLet4ltG~HT+Bf`6Xgc|6^*6Uk`-YzhO(#FC{^mAm-|#b`>Ex%?-`pnc8-6ANY7&Cp4Y7P3kr&O(!&+xJ~LdDNQFdow!ZvHYrUf zG@ZCj>NY7&Cp4Y7P3kr&O(!&+xJ~LdDNQFdA93U8w{PHmA@lU){(z)fOG@U$Sp4=v#TV6`j$us83 zZPK~rr8J#9W1ie5om*Z?)5$aD$!*fP<)t*8JY$~RCY@VeO4G?R=E-f+x#guaojl{` zEx%?-`pnc z8-6AXZj<&6KNFfxep>y_ZPLEsXF}7- zPpiMVP1-m7OlUg!Y4ta^N&AMM2~8(It^VdVY2WZOq3PtO_50>8kKP7;Z@|78W1sHJ zTw~Yg8?ap&bDPv$V>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qy zm}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5N>e|7XW z@HSAtneP6KdFuSi=a!dNue(2Eo;ttsx#gwR>+a8(r_Qf@Zh2|-y8AQcsq-tJTV7hd z?*5E<>io**mX}tqyFX)|I=}L{<)zi@?$4N~&aZrKd1>{!`!nXL^DCcQURu5G{)~C* z{L1H+msYR4KVzOczw)`|rPb^1&zPsquY7KKY4y7MGv=xDE1z3lTD|W6jCsob{PNP< z!0!#@Z)Tc5-PhESv+MH>`b%Uq*F)EXgbNxG`meYb>xhulk7~h z+oV%R&S*Nx&NRDCI(6iXrju|yJ$f792I8C9PMS`(p2*!MjrZG0)5+Eox!a`iemiM8 z*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw*-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h) zr0L{Wk0(cO1HOUn+l$<7(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR^+fJAX}sS~ znohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DVT!{Q7P@A&qZr zJ83%EdLnn5G~RC~O($DV5~UCru|?PvmZs z#{2E0>16AP+-=f$znwIlY(0^?O&agFljf1zfNvnaB~MA?{dUrHvh_snHfg-yPMS`( zp2*!MjrZG0)5+Eox!a`iemiM8*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIl zY(0^?O&agFlctlcCvvw*-%grNww}n{CXM&oNz=*J6S>=@@qRmL zI@x+6cbhccZzs(ow*hV-e@9H6WM`V)CY?HRM$<`lrrB-MsUv4Jon&X4-6ownaz@ih zcBa{F(y1e7G@WE;n%yRyI&wzSNp_~$ZPKYDXEdE;XPVt6ojP(x(@A!w*=^FPBWE<7 zWM`V)CY?HRM$<`lrrB-MsUv4Jon&X4-6ownaz@ihcBa{F(y1e7G@WE;n%zEn8+aS2 z-_J|tse0XgZh2|vSN@E7s$O@WTVC4vl|N&is@L7;mX~&Z<>UHcY{)~C5UU#2cUfTJUKVzP%*WKrqmv(;T&zPs`b@#dDrJY~-Gv=v!-F_qpYzonQGg=Baw!eQvq*+c#j} z&8Ist*Vy&>25eWx+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~ z*BDJF<{ERG)LdgUotSIPZBlcM(R5<2F}F$0HAd5kxyIZkHP;wTC*~S+o77xmG@Y1h z%O(*6WbDPv$ zV>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYC zw@J-4M$?J8#@s&o?HjOfCD^CCiTB%ieZGNhZ;`uA8t=E0rjxBFa<@t2{dUrHvh_sn zHfg-yPMS`(p2*!MjrZG0)5+Eox!a`iemiM8*?J;(n>5~UCru|?PvmZs#{2E0>16AP z+-=f$znwIlY(0^?O&agFlctlcCvvw*7;ty-EGp&ubifn>UDRwNjtxCnog?M z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcl+qKZlL>4GXHcp*_r0+^9@Wp%bDAx*_mdVPNt5WxlNj#X{PC9>d2Yfq}iEfnog#U zoViV!ooS}&Wa`M7+oaij-0tonw@E;>1682ncJkd2YfN563c`Ma3rPj@qQ^AAtku#c3 zvNO$YlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJako>C}-knohDa&2E!U9XX@v zBs^AAtku#c3vNO$YlTIBuqv<3&)9m)qZ`{E2 zo#gD(-DGE)ug^Cy?JQ?*lV)d{X*!uYa^^N^cBYx8lc^(TZj)wbnrS+jI&$VVX?CWW zrjw~7XKs^bXPRj`nL2XjHfeUInWmGeBWG@tW@nmdI+;3h<~C_|rkSRbsUv4@lV)d{ zX*!uYa^^N^cBYx8lc^&zH;;bn2I9Ne&QJHV^+bMszJb`!cDhZv^+Zn7Nxa`qw@J62 z$Z0x>_uJ_<>DCiDO(*ewJKZMTdLpOkB;IeQ+oW4hHNywCaqp~r|G2gD|ef;dflC-lg_W)ZPMy>cbZN*zjC)p ztJmFWI_dn%-6pMGcc0JqOw-BKku$eRvop;!olG4$bDK0f(@fLJ)R8l{ zNwYJ}G@VQxIdhvdJJU?l$<&cEw@I@z%`}~K9sc_0ZJ__1(DhsTbXV2u?$_rV==N2) z+oaX&?lhfre&ueHRfX?oQK5=U47FY4y50O(&gSx!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG=HzP~(r z8~D8e`(})Nx-WB$U7v5jc4f?MQge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgU zotSIPZBlcM(R5<2F}F$0HAd5kxyIZkHP;wTC*~S+o77xmG@Y1h%xzM0jnQ;st}(Ys z%{4~TNp=0z(c8e=K>cRA`!nXL^DCcQURu5G{)~C*{L1H+msYR4KVzOczw)`|rPb^1 z&zPsquY7KKY4y7MGv=xDE1z3lTD|W6jCtz(%IB7sRudFuSi=a!dNue(2Eo;ttsx#gwR>+a8(r_Qf@Zh2|- zy8AQcDf{!wOK$_eH;})XY5sIyQ%BCO&o_{FG|g_4P8~U;=_EVT>^AAtku#c3vNO$Y zlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJako>C}-knohDa&2E!U9XX@vBs^AAtku#c3!twOzZGanyZ)Q7bI@x+6cbhccZzoMB zTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j} zG@Wcck-JSA@3)htlV3fa9K8+r2DWc6a<@t2{dUrHvh_snHfg-yPMS`(p2*!MjrZG0 z)5+Eox!a`iemiM8*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agF zlctlcCvvw*-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cl+pV zz&G&gyYYlHzOn73>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw* z-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{ zc)y)AooqdkyG=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft&O zCtFYCZj;9Q?WE~s>xtZL(s;j}G>_Z{xPkl~F?EuiX?B}*>c|;QC)t^1w@IgtoY8cW zooRNPbn3_%O()rzX17VFj-1hSlAURGn{?{P8BHhInP#_1r;eP_bdsHEcAIqS$Qey1 z*_mdyNvDpS(R7lXX?B}*>c|;QC)t^1w@IgtoY8cWooRNPbn3_%O()rzX17VFj-1hS zlAURG`{-@pZJ>TXFPW$6b@#dDrJY~-Gv=v!-F_qpYzonQGg=Baw!eQtSa=U4uWd8%G_pIctq`ISFoo~qZ~=a!dt ze&x@Yr|Nb0x#gvuU->iUse0XgZh2|vSN@E7s$O@WTVC4vl|N&is@L7;mX~&Z< z>UHO(*6WbDPv$V>F$Z zYs_s@bB)n-Vy-c_kKP9QzxDR%ZtQzAc7479+m$i5NzFAz(}}sp+$J^G7)>YU8grY} zTw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2 zF}F$0HAd5kxyIZkHP;wTC*~S+`{=iCz`m7WpYA5!Z|C*-2DZIL?lx(>-%grNww}n{ zCXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)Aooqdk zyGO))TqgN56Rk@ojYH zr@QI=%CFBiQ1{f`-6rk)%4s^OUUzq!wDT*c>7;ty-EGp&ubifn>UDRwNjtxCnog?M z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnaaqu;uL?mNl+)7@leny=3{Fzqa7Zj)wbnrS+jI&$VVX?CWWrjw~7 zXKs^bXPRj`nL2XjHfeUInWmGeBWG@tW@nmdI+;3h<~C_|rkSRbsUv4@lV)d{X*!uY za^^N^cBYx8lc^(TZj)wbnrS+jI&$VVX?CWWrjw~7XKo+;#tr1}VwykQ&D4>z>+=od z9Zj>_q*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx&NRDCI(6iXrjzVUv)iOoN6u(E z$<8#pO*(btjHZ+9OtaghQ%BBdI?2v7yG=TE`b%Uq*F)EXgbNxG`meYb>xhu zlk7~h+eg1~1Jiesvrl)EooT*4-@vr9oViV!ooS}&Wa`M7+oaij-0tonw@E; z>1682ncJkd2Yfq}iEf znog#UoViV!ooS}&Wa`M7+oaij>z0R`mGy??_xVY-Ott&`Stk*Vn5sIHtE(A zIZY?=emmVJ-FhOY=_KB7r`x1kPvkV6#QW`Zn{?}moTig_znyNAZatCHbQ15k({0kN zCvuuj;{A5IO}h0&PSZ)e-%htlx1PvpI*Iq&={D)s6FE&M@qRnqCf#}>r|Bf#cc)uN zzj*`Qw^I41JE~rHzdqkUx39|GCaqp~r|G2gD|ef;dflC-lg_W)ZPMy>cbZN*zjC)p ztJmFWI_dn%-6pMGcc`XIFCsRkx+$PP=G}Cl4b>z%# z((Ft#O(#=F&fF%=&NS0>GIiw4ZPM&aGfgK`N6y?P&CWE_bkcSB>!Y`U{&zyxZ|T!r zRj<2WpKqYsSLJS#RfX?oQK5=U47FY4y50O(&gSx!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(~0^1^5|{g_Xg~nG4|=c%r$m>z5&~nF}F$0HAd5kxyIZkHP;wTC*~S+o77xm zG@Y1h%xzM0jnQ;st}(Ys%{4~TiMhtyCNO(*6WbDPv$V>F$ZYs_s@bB)n-Vy-c_ zNzFAz(}}sp+$J^G7)>YD^;bu418)QMo9XV)n5WLKd~SJZ^}72r=Be{5pIcs9z3%>u zdFuSi=a!dNue(2Eo;ttsx#gwR>+a8(r_Qf@Zh2|-y8AQcsq-tJTV7hd?*5E<>io** zmX}tqyFX)|I=}L{<)zi@?$4N~&aZrKd1>{!`!nXL^DCcQURu5G{)~C*{L1H+msYR4 zKVzOczw)`|rPb^1&zPs|&o3{%4gB6f{${56(|t`HIlDgJK;F?byG=TE`b%U zq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx&NRDCI(6iXrjzVUv)iOoN6u(E$<8#p zO*(btjHZ+9OtaghQ%BBdI?2v7yG=TE`b%Uq*F)EXgUeU)1$WmZXmvy?WE~s z>xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR^+fJAX}sS~nohQ!$lWH5_uEO+ z$<`CO+obV+J83%EdLnn5G~RC~O($DV}jhHsBlBzP-rZCXM&oNz=*J6S>=@@qRmL zI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft&OCtFYCZj;9Q z?WE~s>xta$qqhOyz_0Jd6Vmv`wv(olttWD~N#p%?(sZ)*MD8|eyx&fmPPU%N-6oCq z+ey>O))Tqgr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA z@3)htldUImw@KsucG7gR^+fJAX}sS~nohQ!$lWH5_uEO+$<`CO+obV+J82%d4fqD) zTk@1N-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR z^+fJAX}sS~nohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DViUse0Xg zZh2|vSN@E7s$O@WTVC4vl|N&is@L7;mX~&Z<>UHcY z{)~C5UU#2cUfTJUKVzP%*WKrqmv(;T&zPs`b@#dDrJY~-Gv=v!-FO(*6WbDPv$V>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qy zm}|^!Qge;bbYiYCw@J-4M$?J8#@s%78|eSm+o!v+@6Fit`37uP#@r?~*BDJF<{ERG z)LdgUotSIPZBlcM(R5<2F}F$0HAd5kxyIZkHP;wTC*~S+o77xmG@Y1h%xzM0jnQ;s zt}(Ys%{4~TiMhtyCNO(*6WbDPv$V>F$ZYs~GV-@XC+R)T%Hn|QyS*XJA9_7=I@ zr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA@3)htldUIm zw@KsucG7gR^+fJAX}sS~nohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DV zSmKHosyQ+IcpwDT*c>7;ty-EGp&ubifn>UDRwNjtxCnog?M z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cejsz>jt{-B=b*qlbvb4KHtE!vz)n2nw@E;>1682 zncJkd2Yfq}iEfnog#U zoViV!ooS}&Wa`M7+oaij-0tonw@E;>1682ncJk^AAtku#c3 zvNO$YlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJako>C}-knohDa&2E!U9XX@v zBsxrDElX%~qZXNyR4Rqg1<)7}Tdfol{d;{ISDtDW-dflC-lg_W)ZPMy>cbZN*zjC)p ztJmFWI_dn%-6pMGccUDRTPCEY=cjM@{Z(#ana`x$-vNO%s=Np)ImNU0W zvop;!olG4$bDK0f(@fLJ)R8l{NwYJ}G@VQxIdhvdJJU?l$<&cEw@I@z%`}}%9XWHG zG&|Ew)5+A4Gq*{zGtD%eOdUCMn>0JqOw-BKku$eRvop;!olG4$bDK0f(@fJz*Ws^^ z-Uj;L30=RXPj^+l?tXo~fo@-wyG>fX?oQK5=U47FY4y50O(&gSx!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(@E!7?lx)lx;srL=KIT|w}Iaquy4lLr~5M3*!B4aY*)tICNO(*6WbDPv$ zV>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYC zw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUomAIf9lZ^_4b*R@yFX)|I=}L{<)zi@?$4N~ z&aZrKd1>{!`!nXL^DCcQURu5G{)~C*{L1H+msYR4KVzOczw)`|rPb^1&zPsquY7KK zY4y7MGv=xDE1z3lTD|W6jCtz(%IB7sRudFuSi=a!dNue(2Ep0Yo`y!1Bkdjt8KndVRTHFf0d`g{XC}-knohDa&2E!U9XX@vBs^AAtku#c3vNO$Y zlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJako>C}-knohDa&2E!U9XX@vBpgqV z-UhgV_-3|~rjxBFa<@t2{dUrHvh_snHfg-yPMS`(p2*!MjrZG0)5+Eox!a`iemiM8 z*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw*-%grNww}n{CXM&oNz=*J6S>=@@qRmLI{DS($xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR^+fJAX}sS~ znohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DV5~UCru|?PvmZs z#{2E0dE_?W8;EboQ_^_9oiv?nJ(0Uj8t=E0rjxBFa<@t2{dUrHvh_snHfg-yPMS`( zp2*!MjrZG0)5+Eox!a`iemiM8*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIl zY(0^?O&agFlctlcCvvw*-%grNww}n{CXM&oN%P2UfE&o)5mP7G znP#_1r;eP_bdsHEcAIqS$Qey1*_mdyNvDpS(R7lXX?B}*>c|;QC)t^1w@IgtoY8cW zooRNPbn3_%O()rzX17VFj-1hSlAURGn{?{P8BHhInP#_1r;eP_bdsHEcAIqS$Qey1 z*_mdyNvDpS(R7lXX?B}*>c|;QC)t^1w~yWi-UjOT^OAY0UU#2cUfTJUKVzP%*WKrq zmv(;T&zPs`b@#dDrJY~-Gv=v!-F_qpYzonQGg=Baw!eQtSa=U4uWd8%G_pIctq`ISFoo~qZ~=a!dte&x@Yr|Nb0 zx#gvuU->iUse0XgZh2|vSN@E7s$O@WTQ2?f4cK?{=}ycwc7479+m$i5NzFAz(}}sp z+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgU zotSIPZBlcM(R5<2F}F$0HAd5kxyIZkHP;wTC*~S+`{-?;|66aL?#8}1W7p>!uw5B* zo77xmG@Y1h%xzM0jnQ;st}(Ys%{4~TiMhtyCNO(*6WbDPv$V>F$ZYs_s@bB)n- zVy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYCw~v1N2JBl2_UUfo z{dQiTZ(!S75~UCru|?PvmZs#{2E0>16AP z+-=f$znwIlY(0^?ee|0*5Z^|3e!82^ul)La19eZ`-EGp&ubifn>UDRwNjtxCnog?M z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cehD9zjB&Rs@L7!KKiX2=)RN8Kiy4sruq7O1JllO z<~C_|rkSRbsUv4@lV)d{X*!uYa^^N^cBYx8lc^(TZj)wbnrS+jI&$VVX?CWWrjw~7 zXKs^bXPRj`nL2XjHfeUInWmGeBWG@tW@nmdI+;3h<~C_|rkSRbsUv4@lV)d{X*!uY za_08YZ`?rsE~fd@-Ao-hyFTAQ-qAF>O*(btjHZ+9OtaghQ%BBdI?2v7yG=TE`b%Uq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx&NRDCI(6iXrjzVUv)iOoN6u(E z$<8#pO*(btjHZ+9OtaghQ%BBdI?2v7yM6Qd2Yfq}iEfnog#UoViV!ooS}&Wa`M7+oaij-0tonw@E; z>1682ncJkWIwEqu;uL z_%62d)BS8ckzb#0AojDJZj)|3k<)Y%@3+%!(yb?Qnoi>VcDhZv^+Zn7Nxa`qw@J62 z$Z0x>_uJ_<>DCiDO(*ewJKZMTdLpOkB;IeQ+oW4hcbZN*zjC)p ztJmFWI_dn%-6pMGccUDRTPCCDGw@Itl-Dx`M{9oLSqu;)P>6^*fr+doI zG+&=@VA@&E+$PP=G}Cl4b>z%#((Ft#O(#=F&fF%=&NS0>GIiw4ZPM&aGfgK`N6y?P z&CWE_bTW11%x%)_OfyX`XIFCsRkx+$PP=G}Cl4b>z%# z((Ft#O($K4zdm{!=zk}4{gyu6RrR|2_4x+6eO2x@Y4y50O(&gSx!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(@E!7?lx)lx;srLonN`zq}A*0G@Y35FOS{^es93O8DpRB%UomE=NqtH8FQP| zTw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2 zF}F$0HAd5kxyIZkHP;wTC*~S+o77xmG@Y1h%xzM0jnQ;cU4M1-Ht;r3znSj-jCtz( z%IB7sRudFuSi=a!dN zue(2Eo;ttsx#gwR>+a8(r_Qf@Zh2|-y8AQcsq-tJTV7hd?*5E<>io**mX}tqyFX)| zI=}L{<)zi@?$4N~&aZrKd1>{!`!nXL^DCcQURu5G{)~Cb{`~UN+raM)`b%U zq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx&NRDCI(6iXrjzVUv)iOoN6u(E$<8#p zO*(btjHZ)tJUx0F;0EHG*-n~Hww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMB zTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WF1CSC1!0Zv(!8 z?c0moZPIwZoiv?nJ(0Uj8t=E0rjxBFa<@t2{dUrHvh_snHfg-yPMS`(p2*!MjrZG0 z)5+Eox!a`iemiM8*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agF zlctlcCvvw*-%grNww}n{K6)GQ4gC6UJRyy5Y&&T>*?J;(n>5~U zCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw* z-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{ zc)y)AooqdkyG-%grNww}n{CXM&oNz=*J z6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft(( zBewx=Ab&?pon&X4-6ownaz@ihcBa{F(y1e7G@WE;n%yRyI&wzSNp_~$ZPKYDXEdE; zXPVt6ojP(x(@A!w*=^FPBWE<7WM`V)CY?HRM$<`lrrB-MsUv4Jon&X4-6ownaz@ih zcBa{F(y1e7G@WE;n%yRyI&wzSNp_~$ZPKYDXEdE;XPVtUdK-8fsNc^^=Baw!eQtSa z=U4uWd8%G_pIctq`ISFoo~qZ~=a!dte&x@Yr|Nb0x#gvuU->iUse0XgZh2|vSN@E7 zs$O@WTVC4vl|N&is@L7;mX~&Z<>UHcY{)~C5UU#2c zUfTJUKVzP%*WKrqmv(;T&zPs`b@#dDrJY~-Gv=v!-FO(*6WbDPv$V>F$ZYs~GVw}Jj|y?weH z``(OQpKri+Wz20-bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;b zbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2F}F$0HAd5kxyIZ+ z`t2LAZzb5LyNUPPd40ZtZEumgO&agFlctlcCvvw*-%grNww}n{ zCXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)Aooqdk zyG+=oNJ#}}tNjtxCnog?M z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cehD9zjB&Rs@L7!Chh#nX*#K1cX#{fw{D>OPBQ;= zH`$ry>+=mvJIk5dq}iEfnog#UoViV!ooS}&Wa`M7+oaij-0tonw@E;>1682 zncJkd2Yfq}iEfnog#U zoViV!ooS}&Wa`M7+eg1~1Npm{=1+Gsb>!^&d;@t$)9g0s)R8lqPO>x2Zj(+OIiu+$ zJJako>C}-knohDa&2E!U9XX@vBs^AAtku#c3 zvNO$YlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJam;(Qn+q^qu7F)7@leny=3{ zFzqa7Zj)wbnrS+jI&$VVX?CWWrjw~7XKs^bXPRj`nL2XjHfeUInWmGeBWG@tW@nmd zI+;3h<~C_|rkSRbsUv4@lV)d{X*!uYa^^N^cBYx8lc^(TZj)wbnrS+jI&$VVX?CWW zrjw~7GB=NY>jvVx*v?P)v-L!NeZGO%&vv>^y7fd((@DJFPPa+7p2%rBiTB&-HtE(A zIZY?=emmVJ-FhOY=_KB7r`x1kPvkV6#QW`Zn{?}moTig_znyNAZatCHbQ15k({0kN zCvuuj;{A5IO}h0&PSZ)e-%htlx1PvpI*Iq)>DJM2-az-QRQ~CXs@L7G&o|KRt8%wV ztJmFWI_dn%-6pMGccUDRTPCCDGw@Itl-Dx`M{L0-XtzLJh>7?_2aW{^B z`v#_OCTE}SDLd1AeZGNdXE}45G&|Ew)5+A4Gq*{zGtD%eOdUCMn>0JqOw-BKku$eR zvop;!olG4$bDK0f(@fLJ)R8l{NwYJ}G@VQxIdhvdJJU?l$<&cEw@I@z%`}}%9XWHG zG&|Ew)5+A4Gq*{zGtD%ebRGWs=xw0?ozV4L`gB*->+aX*8|d~`x!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(@E!7?lx)lx;srLonN`zq}A*0G@W#Qt?0sCf*eY!7m zja{E_z;O(*6WbDPv$V>F$ZYs_s@bB)n-Vy-c_NzFAz(@Ayx)zRC) z+d%zhy8AQcsq-tJTV7hd?*5E<>io**mX}tqyFX)|I=}L{<)zi@?$4N~&aZrKd1>{! z`!nXL^DCcQURu5G{)~C*{L1H+msYR4KVzOczw)`|rPb^1&zPsquY7KKY4y7MGv=xD zE1z3lTD|W6jCtz(%IB7sRx2Zj(+OIiu+$JJako z>C}-knohDa&2E!U9XX@vBs^AAtku#c3vNO$Y zlTIBuqv<3&)9g0s)R8lqPQvl@=xu--h;L>)X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s z>xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR^+fJAX}sS~nohQ!$lWH5_uEO+ z$<`CO+obV+J83%EdLnn5G~RC~O($DV-%grNww}n{CXM&oNz=*J6S>=@@qRmL zI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6s`fZNNA1>$~xUG`_Lz zr0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA z@3)htldUImw@KsucG7gR^+fJAX}sS~nn!K}zJd6bJSC0y+ey>O))Tqgr15?`X*$_@ zB6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR z^+fJAX}sS~nohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DVc|;QC)t^1w@IgtoY8cW zooRNPbn3_%O()rzX17VFj-1hSlAURGn{?{P8BHhInP#_1r;eP_bdsHEcKhgU;BBCO zKQEc5>UHcY{)~C5UU#2cUfTJUKVzP%*WKrqmv(;T&zPs` zb@#dDrJY~-Gv=v!-F_qpYz zonQGg=Baw!eQtSa=U4uWd8%G_pIctq`ISFoo~qZ~=a!dte&x@Yr|Nb0x#iMt-++BL zpYFt5W7p>!uw5B*o77xmG@Y1h%xzM0jnQ;st}(Ys%{4~TiMhtyCNO(*6WbDPv$ zV>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYC zw~yWi`oHz|>2BO(*6WbNlGGZ@|8lV4vO))Tqg zr15?`X*$_@B6piK-ft&OCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA@3)htldUIm zw@KsucG7gR^+fJAX}sS~nohQ!$lWH5_uEO+$<`CO+eg271MzKi=cl{r{K~J-H&FM~ z-Q6bb{K{!Msa|(?o3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cehD9zjB&Rs@L7!Chh#nX*#K1cXyk#^DC$6q`b%Uq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx&NRDCI(6iXrjzVUv)f0%aRbwL zlCw{Dlbvb4KHtE!vz)n2nw@E;>1682ncJkd2Yfq}iEfnog#UoViV!ooS}&Wa`M7+oaij-0tonw@E; z>1682ncJkF0i0@)MKi$vP6Z!S|24X+k={D)s6FE&M@qRnqCf#}> zr|Bf#Z>QU&TTkRPoy7a?benYRiJYdBc)y))lWskc({vK=x6^IXttWDtPU8J`x=p(E zL{8I5yx&f@Nw=QJX*!Ab+vzsx))P5RC-Hte-6q|7BB$vj-gl>4N56Rk-M3Qtr#q@% zcfUU0K)0{T-6pMGccUDRTPCCDGw@Itl-Dx`M{L0-XtzLJh>7?^3cbl|& z-JPbB&i}>TIQs1yn7)~ueY&UYO!M{m2Bw|m%x%)_OfyX`XIFCsRkx+$PP=G}Cl4b>z%#((Ft#O(#=F&fF%=&NS0>GIiw4ZPM&aGfgK`N6y?P z&CWE_bTW11%x%)_OfyXi`IWm( zTD|U0(@E!7?lx)lx;srLonN`zq}A*0G@W#QO(*6WbDPv$V>F$ZYs_s@bB)n- zVy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~ z*BDJF)%90LZv$@w^_%JL&zPsquY7KKY4y7MGv=xDE1z3lTD|W6jCtz(%IB7sRudFuSi=a!dNue(2Eo;tts zx#gwR>+a8(r_Qf@Zh2|-y8AQcsq-tJTV7hd?*5E<>io**mX}tqyFX)|I=}L{<)zi@ z?$4N~?9VSRy$$@{K>lW?`O|$(9XY!`-$35cG`meYb>xhulk7~h+oV%R&S*Nx&NRDC zI(6iXrjzVUv)iOoN6u(E$<8#pO*(btjHZ+9OtaghQ%BBdI?2v7yG=TE`b%U zq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Lb$J3*?0d63^neC+MWb29CZPIwZoiv?n zJ(0Uj8t=E0rjxBFa<@t2{dUrHvh_snHfg-yPMS`(p2*!MjrZG0)5+Eox!a`iemiM8 z*?J;(n>5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw*-%grNe)V{A^furd*uK5U-6oCq+ey>O))Tqgr15?`X*$_@B6piK-ft&O zCtFYCZj;9Q?WE~s>xtZL(s;j}G@Wcck-JSA@3)htldUImw@KsucG7gR^+fJAX}sS~ znohQ!$lWH5_uEO+$<`CO+obV+J83%EdLnn5G~RC~O($DV5~UCru|?PvmZs#{2E0>16AP+-=f$znwIl zY(0^?O&agFlctlcCvvw*_qpYzonQGg=Baw!eQtSa=U4uWd8%G_ zpIctq`ISFoo~qZ~=a!dte&x@Yr|Nb0x#gvuU->iUse0XgZh2|vSN@E7s$O@WTVC4v zl|N&is@L7;mX~&Z<>UHcY{)~C5UU#2cUfTJUKVzP% z*WKrqOTT>s_T7BC6LXDSpKri+Wz20-bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY} zTw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2 zF}F$0HAd5kxyIZ+dK>8f*4wAMvG2{;_4x*DSH|2XHP;wTC*~S+o77xmG@Y1h%xzM0 zjnQ;st}(Ys%{4~TiMhtyCNO(*6WbDPv$V>F$ZYs_s@bB)n-Vy-c_NzFAz(}}sp z+$J^G7)>YU8grY}Tw^qym}|`Kqu;&(`&NQ|x|?{vo!93Z*!C8=+obV+J83%EdLnn5 zG~RC~O($DV5~UCru|?PvmYN{pJnCx6z%S z?xyoAzdqkU-BWjWo3!&Qr|G16-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cehD9zjB&Rs@L7!Chh#nX*#K1cXyk#^DC$6qd2Yfq}iEfnog#UoViV!ooS}&Wa`M7+oaij-0tonw@E;>1682 zncJk^AAtku#c3vNO$YlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$ zJJako>C}-knohDa&2E!U9XX@vBs^AAtku#c3 zvNO$YAN|G+Oy5b)KHW`rruq7O1JllO<~C_|rkSRbsUv4@lV)d{X*!uYa^^N^cBYx8 zlc^(TZj)wbnrS+jI&$VVX?CWWrjw~7XKs^bXPRj`nL2XjHfeUInWmGeBWG@tW@nmd zI+;3h<~C_|rkSRbsUv4@lV)d{X*!uYB6IWTw{9T5i|zb$KU+`a*XJ9E{cNY(q+3tq zG@Zoz?R1-T>xrDElX$VcDhZv^+Zn7Nxa`qw@J62 z$Z0x>_uJ_<>DCiDO(*ewJKZMTdLpOkB;IeQ+oW4hUDRTPCCDGw@Itl-Dx`M{L0-XtzLJh>7?^3cbl|& z-JPbB&ad2U(&}}0noc_Z7kA_6w{KwjW^(rFp0YE|*XJ9Uc9t`@NwYJ}G@VQxIdhvd zJJU?l$<&cEw@I@z%`}}%9XWHGG&|Ew)5+A4Gq*{zGtD%eOdUCMn>0JqOw-BKku$eR zvop;!olG4$bDK0f(@fLJ)R8l{NwYJ}G@VQxIdhvdJJU?lN!Q`8kKP9Q-w9p6rB8QN zz3zT}zJYFEmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(@E!7?lx)lx;srLonN`zq}A*0G@W#Q25eWx+$J^G7)>YU8grY}Tw^qym}|^!Qge;b zbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2F}F$0HAd5kxyIZk zHP;wTC*~S+o77xmG@Vq}Umd*-ybaWErn^65o;ttsx#gwR>+a8(r_Qf@Zh2|-y8AQc zsq-tJTV7hd?*5E<>io**mX}tqyFX)|I=}L{<)zi@?$4N~&aZrKd1>{!`!nXL^DCcQ zURu5G{)~C*{L1H+msYR4KVzOczw)`|rPb^1&zPsquY7KKY4y7MGv=xDE1z3lTD|W6 zjCtz(%IB7sR^AAtku#c3vNO$YlTIBuqv<3&)9g0s)R8lqPO>x2Zj(+OIiu+$JJako z>C}-knohDa&2E!U9XX@vBs-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMB zTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGO))Tqgr15?`X*&7U5~UCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agF zlctlcCvvxs-UfUFzrGt!NaGvZPMS`(p2*!MjrZG0)5+Eox!a`iemiM8*?J;(n>5~U zCru|?PvmZs#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw* z-%grNww}n{CXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)q-%grNww}n{CXM&oNz=*J z6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)AooqdkyGc|;QC)t^1w@IgtoY8cWooRNPbn3_%O()rzX17VFj-1hSlAURGn{?{P8BHhI znP#_1r;eP_bdsHEcAIqS$Qey1*_mdyNvDpS(R7lXX?B}*>c|;QC)t^1w@IgtoY8cW zooRNPbn3_%O()rzX19;t2Hpnh_w$l@s$O@WTVC4vl|N&is@L7;mX~&Z<>UHcY{)~C5UU#2cUfTJUKVzP%*WKrqmv(;T&zPs`b@#dDrJY~- zGv=v!-F_qpYzonQGg=Baw! zeQtSa=U4uWd8%G_pIa{d_6^u~^XX2^HFkZz0o#=^w@J-4M$?J8#@r?~*BDJF<{ERG z)LdgUotSIPZBlcM(R5<2F}F$0HAd5kxyIZkHP;wTC*~S+o77xmG@Y1h%xzM0jnQ;s zt}(Ys%{4~TiMhtyCNO(*6WbNlFRp#NKMpYF!KH)Gf58?ap&bDPv$V>F$ZYs_s@ zbB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY}Tw^qym}|^!Qge;bbYiYCw@J-4M$?J8 z#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2F}II?`v&Y=3HIr3;{A4BpKoB>TjXw& z#{2E0>16AP+-=f$znwIlY(0^?O&agFlctlcCvvw*-%grNww}n{ zCXM&oNz=*J6S>=@@qRmLI@x+6cbhccZzoMBTTkR}lg9h)r0HbqiQH|{c)y)Aooqdk zyM6SVHxS=OcYeB?&aeFXd;@h)-Q8`{&aa%Nlj?PMw@Ev{a+*%6*WKMF?flAVI;mcF zcbl~HE2rtCdfnY^($24(rjzP*cehD9zjB&Rs@L7!Chh#nX*#K1cXyk#^DC$6q`b%Uq*F)EXgbNxG`meYb>xhulk7~h+oV%R&S*Nx z&NRDCI(6iXrjzVUv)iOoN6u(E$<8#pO*(btjHZ+9OtaghQ%BBdI?2v7yG=TE`b%Uq*F)EXgbNxG`oHD8#ge0Cpr6cH`$ry>+=mvJIk5dq}iEfnog#UoViV!ooS}& zWa`M-|7Y(ERxMjrEqMR`s~^Qd(rJXcUVGb0Gt3yU2McDe%5Bo@OfyXQU&TTbk0I*Iq&={D(>6MLFY;{A5I zO}gd8o~Dy{znyNAZaJ~1=_KB7r`x1kPV8wqiTB&-HtCiVdzwz-eRsNb^e;Ei{Z=af zwWI2F_sjDJy1puRo3wh}ou-q{uiS0Y>UDRTPCCDGw@Itl-Dx`M{L0-XtzLJh>7?^3 zcbl|&-JPbB&ad2U(&}}0noc^ua<@sV*WGD4>HNywCaqp~r|G2gD|ef;dflC-lg_W) zZPMy>cbZN*{~veb=wEMO`px9suRUdFnlH~Am^#Zlw@I@z%`}}%8F}Y6X?CWWrjscn z@7yNM&NS0>GG*kQ+oaijJ$K3G&|Ew)5(;PcW#qrXPRj`nKJUuZPM&aGfgK` zM&7winw@E;>14{tJGV)*GtD%eOc{CSHfeUInWmF2!(Si02Ks*!y8f1a?W%g+{qnql zuCL17Caqp~r|G2gD|ef;dflC-lg_W)ZPMy>cbZN*zjC)ptJmFWI_dn%-6pMGcc z{pHbX;J*g!H)HJAzRWdtdES6^Wz20-bB)n-Vy-c_NzFAz(}}sp+$J^G7)>YU8grY} zTw^qym}|^!Qge;bbYiYCw@J-4M$?J8#@r?~*BDJF<{ERG)LdgUotSIPZBlcM(R5<2 zF}F$0HAd4(b^X=RYv46de>2_v8S~WnmCq?}TfOf7jCtz(%IB1~tzLJ3#yoX?<#Wp0 zRUH;L%v0xAKBv5G^}72r z=Be{5pHtqpdfojQ^VIp3&na(Pz3%>udFuSi=ajdtUUz@SJavBMbIRLRue(2Eo;tts zIpuAu*WI5nPuZVe-u4>!uYvrVndV>nnlke4^1OlE(KNeFI%VV?O()rzX17VFjJ%`i zBs*^JDN_iGtF+3P8oSe z(@A!w*=^D(BkyQB$<8#pO*&=d9Ze_MnP#_1r;NO#=_DNA9=!(GK>TL5lctj`C-!cW z#{2E0>14}^z1yVmemiM8*>YmuK6dJT93+ix%SZj;9Q?WE~s%Za_)r15?`X*$_* zV(&I-yx&fmPPUxbyG1??-%grN zww&0zO&agFlctj`C-!cW#{2E0>14}^z1yVmemiM8*>Ym6>#&2vpX*$_*V(&I-yx&fmPPUxbyG1??-%grNww&0zO&agFlctj`C-!cW#{2E0>14}^z1yVm zemiM8*>YmOmJ@roN#p%?(sZ)r#NKVvc)y)AooqR=cbhccZzoMB zTTblVCXM&oNz=)e6MMHw5~UCru|?PVC(#jrZG0 z)5(?-d$&pB{dUrHvgO3yZPIwZoiv?nIk9(}G~RC~%_G+U8_2&SZk=Rjn%yRyGV+e5 zlk7~h+oV%Q-qCcDooRNPbjrv(nohDa&2E!U8F@$3Np_~$ZPF*^ zJDN_iGtF+3P8oSe(@A!w+3lm(z-yrXe%@xDs@L7;l(+5t%AYY$)$8ta%G-8+< z>UH-y>+W;P+jf5C&zPs`b@w^tZ9Bj6 zXUtRey8E2+ww+)3Gv=v!-F;5E?O$)eemB2%Vy>~v^9HOdV{Vh0YmBB7bB(!8YOXPw zPRuptHmSMBXgV?1nA@c08l&mNTw`vNnrn=v6LXEZO=_+&noi6$<~FIh#%MY**O=R+ z<{G2v#9U);lbUOcrW13GxlL-WF`7=yHRkrwYoPzX-hS=Ies9Ju&l|9=jJZu}t}&WU z%r)jVskz2zIx*Ln+oa|iqv^z4V{Vh0YmBB7bB(!8YOXPwPRuptHmSMBXgV?1nA@c0 z8l&mNTw`vNnrn=v6LXEZO=_+&noi6$<~FIh#%MY**O=Q!|9S)VTM71SH}QTuFV7p; zdW*f=r15?`X*$_*V(&I-yx&fmPPUxbyG1??-%grNww&0zO&agFlctj`C-!cW#{2E0>14}^z1yVmemiM8*>YmMZZvCe6+? z({wUr`XIFCsRh=xlNj# zX{PC9%E&vnNwYJ}G@VQtdFM81cBYx8lPM$b+$PP=G}Cl4W#paPq}iEfnog#SymR~L zUu+=%E~fd{Zl;X9yF70ocQnmzlTI0VN7G4mrrB-MDI@P_I?2v7yG=S}`b%Uq*F%T(R7lXX?B}*%E&vKPO>x2 zZj(+Kc}LSpcBa{F(kUbFXgbNxG`oHDFE%j!PV(;8Zn87Ym*)*ko#ma|q}iEfnog#S zymOm0JJU?l$&`_IZj)wbnrS+jGV;!C((Ft#O(#=E-nmVhooS}&WXi}pw@I@z%`}}% z8F}Y6X?CWWrjscn@7yNM&NS0>GG*kQ+oaijJ$K3G&|Ew)5(+(J2#L1)du2s zv7Nv6v*pD8^1OlQXFJ^{-Ev}2(@DJFPPa+7oY>QJ67RRuZPG0#_B5Tu`|Wg_bjyi7 zO(*ewJKZMTa$--@Nxa`qw@J60*wb_p@3+%!(k&fX z?oQK5=U47FY4y50O(&gSx!a`G>+Uq2bbjS-lUA?0({$4L|F|1R|9S({Zzk`4?I}Cc ze0ko$)LGuSO`4r)rs-tL$UC=5vop;!olF^d=Qe3}rkSRbDI@RPCe6+?({wUr`XIFCsRh=xlNj#X{PC9%E&vn zNwYJ}G@W!A{`%-O(Eppz^|$nESJmt8m*)+1eO2x@Y4y50O(&gSx!a`G>+Uq2bbjS- zlUA?0({$4LmAg$^z3xuaN#|GYHfi;`J548@U%A_))$8swopgTXZj)B8yVG>i`IWm( zTD|U0(@E!7?lx)lx;srLonN`zq}A*0G@Y35FOOaW|21I08DqcpWv;Qy^9HOdV{Vh0 zYmBB7bB(!8YOXPwPRuptHmSMBXgV?1nA@c08l&mNTw`vNnrn=v6LXEZO=_+&noi6$ z<~FIh#%MY**O=R+<{G2v#9U);lbUOcrW13GxlL-WF`7=Q>#vSp1FwPlo9XV)n5WLK zd`@}W>UH;L%v0xAKBv5G^}72r=Be{5pHtqpdfojQ^VIp3&na(Pz3%>udFuSi=ajdt zUUz@SJavBMbIRLRue(2Eo;ttsIpuAu*WI5nPn}=+obtBS>+a8(r_Qf@PI=qvb@yk? zQ|DJcr@U?Ty8AQcsq-tJQ{J|E-TfK!)cKXqDQ{c7?*5E<%KrTFw%5Ra4dma

Py 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�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 diff --git a/test/shapes/p12_shape24.bmp b/test/shapes/p12_shape24.bmp deleted file mode 100644 index 582cf994e2e21ad58919600c73b5546748e5300a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 diff --git a/test/shapes/p12_shape8.bmp b/test/shapes/p12_shape8.bmp deleted file mode 100644 index 59377200bbd9ef2b390ac08cabebacbb7e55958b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 diff --git a/test/shapes/p13_shape24.bmp b/test/shapes/p13_shape24.bmp deleted file mode 100644 index 70215db590c7c6c1bac1becf7333d51d5649ff3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1228938 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 z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk v1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlykRtGZT`e)# diff --git a/test/shapes/p13_shape8.bmp b/test/shapes/p13_shape8.bmp deleted file mode 100644 index 822b896e1c7026fc5a62d33f604282bd9edbf337..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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

+MX> 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 OAV7cs0RjYK3j9CtHj-oj diff --git a/test/shapes/p14_shape8.bmp b/test/shapes/p14_shape8.bmp deleted file mode 100644 index d6f981f58add4872ed72ccc2181b10ec4eea6101..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk a1PBlyK!5-N0t5&UAV7cs0RjYW6Zk*>6Vn_3 diff --git a/test/shapes/p15_shape32alpha.bmp b/test/shapes/p15_shape32alpha.bmp deleted file mode 100644 index 6954a5d91c44dc333c5b4822f046d66858ffd919..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638538 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 z=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^! zA==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)o zZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K= zd1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju z+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3? z?n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l? zXM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q) zjm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S z=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^! zA==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)o zZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K= zd1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju z+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3? z?n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l? zXM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q) zjm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S z=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^! zA==l?XM3K=d1`#S=WY3??n$)oZT{Q)jm~ju+|6^!A==l?XM3K=d1`#S=WY3??n$)o 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 I_*Q}c0cCyzH2?qr diff --git a/test/shapes/p16_shape8.bmp b/test/shapes/p16_shape8.bmp deleted file mode 100644 index 0b4d4221c5c47a45ff8418f747c4fe98218a7b4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410678 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 XOuz(8zywUd1WdpLOuz(ok-&ceOT{Tx diff --git a/test/shapes/trollface_24.bmp b/test/shapes/trollface_24.bmp deleted file mode 100644 index e18c2c2ad129e2dfa612d0c4382bbc26fc21edd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196662 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�o2DBOY1($ca-Y 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 diff --git a/test/shapes/trollface_32alpha.bmp b/test/shapes/trollface_32alpha.bmp deleted file mode 100644 index ee3ecf9be4c95a7e76f338bf2c985d1d97054364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262198 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 UQ0hRb1Emg>I#B9BXY0WK4>RWDjQ{`u From 3264e64738f02f4b50f50d98d11792c9cb43ef72 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 22 Nov 2023 17:34:39 -0500 Subject: [PATCH 417/725] SDL_RunApp: Make sure argc/argv are stable if the caller didn't define them. Fixes #8246. --- src/core/SDL_runapp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/SDL_runapp.c b/src/core/SDL_runapp.c index faa2a924bb83e..bb5a602168c43 100644 --- a/src/core/SDL_runapp.c +++ b/src/core/SDL_runapp.c @@ -27,15 +27,14 @@ DECLSPEC int SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved) { - char empty[1] = {0}; - char* argvdummy[2] = { empty, NULL }; - (void)reserved; if(!argv) { - argc = 0; /* make sure argv isn't NULL, in case some user code doesn't like that */ + static char dummyargv0[] = { 'S', 'D', 'L', '_', 'a', 'p', 'p', '\0' }; + static char* argvdummy[2] = { dummyargv0, NULL }; + argc = 1; argv = argvdummy; } From e9659f5738691a954856026145c67142bd6d6706 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 22 Nov 2023 17:53:57 -0500 Subject: [PATCH 418/725] Removed some function declarations that don't actually exist. Reference Issue #8554. (cherry picked from commit 87875a49b4cfc277aba6d2c4c32769a29767e561) --- src/video/kmsdrm/SDL_kmsdrmevents.h | 2 -- src/video/raspberry/SDL_rpievents_c.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmevents.h b/src/video/kmsdrm/SDL_kmsdrmevents.h index e63136717b733..0f9bb8693ffbc 100644 --- a/src/video/kmsdrm/SDL_kmsdrmevents.h +++ b/src/video/kmsdrm/SDL_kmsdrmevents.h @@ -25,7 +25,5 @@ #define SDL_kmsdrmevents_h_ extern void KMSDRM_PumpEvents(SDL_VideoDevice *_this); -extern void KMSDRM_EventInit(SDL_VideoDevice *_this); -extern void KMSDRM_EventQuit(SDL_VideoDevice *_this); #endif /* SDL_kmsdrmevents_h_ */ diff --git a/src/video/raspberry/SDL_rpievents_c.h b/src/video/raspberry/SDL_rpievents_c.h index f56bee883c8fe..5bdd916354573 100644 --- a/src/video/raspberry/SDL_rpievents_c.h +++ b/src/video/raspberry/SDL_rpievents_c.h @@ -25,7 +25,5 @@ #include "SDL_rpivideo.h" void RPI_PumpEvents(SDL_VideoDevice *_this); -void RPI_EventInit(SDL_VideoDevice *_this); -void RPI_EventQuit(SDL_VideoDevice *_this); #endif /* SDL_rpievents_c_h_ */ From 6cde96f9a06b555870fc60b5b3418c2da3b6ee28 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 22 Nov 2023 17:59:36 -0500 Subject: [PATCH 419/725] psp: Hook up event subsystem init/quit. Fixes #8554. (cherry picked from commit 0e9d050296ba754d23e82752eb1bd61221768586) --- src/video/psp/SDL_pspevents_c.h | 2 ++ src/video/psp/SDL_pspvideo.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/video/psp/SDL_pspevents_c.h b/src/video/psp/SDL_pspevents_c.h index dd299a6f27e44..76739678bbb27 100644 --- a/src/video/psp/SDL_pspevents_c.h +++ b/src/video/psp/SDL_pspevents_c.h @@ -23,5 +23,7 @@ extern void PSP_InitOSKeymap(SDL_VideoDevice *_this); extern void PSP_PumpEvents(SDL_VideoDevice *_this); +extern int PSP_EventInit(SDL_VideoDevice *_this); +extern void PSP_EventQuit(SDL_VideoDevice *_this); /* end of SDL_pspevents_c.h ... */ diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 44269db934a9d..14a5599dfce53 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -131,6 +131,10 @@ int PSP_VideoInit(SDL_VideoDevice *_this) { SDL_DisplayMode mode; + if (PSP_EventInit(_this) == -1) { + return -1; /* error string would already be set */ + } + SDL_zero(mode); mode.w = 480; mode.h = 272; @@ -145,8 +149,9 @@ int PSP_VideoInit(SDL_VideoDevice *_this) return 0; } -void PSP_VideoQuit(SDL_VideoDevice *_this) +void PSP_VideoQuit(_THIS) { + PSP_EventQuit(_this); } int PSP_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) From 53544cabaaf42a5eeff2660f9ea4a99ec99b48de Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 23 Nov 2023 04:11:24 +0300 Subject: [PATCH 420/725] psp: fix copy/paste error from SDL2 in PSP_VideoQuit(). --- src/video/psp/SDL_pspvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 14a5599dfce53..27f9b47dbff61 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -149,7 +149,7 @@ int PSP_VideoInit(SDL_VideoDevice *_this) return 0; } -void PSP_VideoQuit(_THIS) +void PSP_VideoQuit(SDL_VideoDevice *_this) { PSP_EventQuit(_this); } From a45b371de07eb381876f10b2ded40c1e1d674df5 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 22 Nov 2023 23:28:39 +0100 Subject: [PATCH 421/725] cmake: create and install SDL3::Jar target for Android --- CMakeLists.txt | 18 ++++++++++++++++-- cmake/SDL3Config.cmake.in | 5 +++++ cmake/SDL3jarTargets.cmake.in | 10 ++++++++++ cmake/test/CMakeLists.txt | 4 ++++ test/CMakeLists.txt | 14 +++++++------- 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 cmake/SDL3jarTargets.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 6eb4b369e1014..9a04b2b39916f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1350,6 +1350,10 @@ if(ANDROID) VERSION "${SDL3_VERSION}" ) set_property(TARGET SDL3-jar PROPERTY OUTPUT "${SDL3_BINARY_DIR}/SDL3-${SDL3_VERSION}.jar") + add_library(SDL3__Jar INTERFACE) + add_library(SDL3::Jar ALIAS SDL3__Jar) + get_property(sdl3_jar_location TARGET SDL3-jar PROPERTY JAR_FILE) + set_property(TARGET SDL3__Jar PROPERTY JAR_FILE "${sdl3_jar_location}") set(javasourcesjar "${SDL3_BINARY_DIR}/SDL3-${SDL3_VERSION}-sources.jar") string(REGEX REPLACE "${android_java_sources_root}/" "" sdl_relative_java_sources "${SDL_JAVA_SOURCES}") add_custom_command( @@ -3292,6 +3296,7 @@ sdl_cmake_config_find_pkg_config_commands(SDL_TEST_FIND_PKG_CONFIG_COMMANDS include(CMakePackageConfigHelpers) configure_package_config_file(cmake/SDL3Config.cmake.in SDL3Config.cmake + NO_SET_AND_CHECK_MACRO PATH_VARS CMAKE_INSTALL_PREFIX INSTALL_DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}" ) @@ -3421,10 +3426,19 @@ if(NOT SDL_DISABLE_INSTALL) endif() if(ANDROID) - set(SDL_INSTALL_JAVADIR "${CMAKE_INSTALL_DATAROOTDIR}/java" CACHE PATH "Path where to install java clases + java sources") if(TARGET SDL3-jar) - install(FILES "${SDL3_BINARY_DIR}/SDL3.jar" "${SDL3_BINARY_DIR}/SDL3-${SDL3_VERSION}.jar" + set(SDL_INSTALL_JAVADIR "${CMAKE_INSTALL_DATAROOTDIR}/java" CACHE PATH "Path where to install java clases + java sources") + install(FILES $ DESTINATION "${SDL_INSTALL_JAVADIR}/SDL3") + configure_package_config_file(cmake/SDL3jarTargets.cmake.in SDL3jarTargets.cmake + INSTALL_DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}" + PATH_VARS SDL_INSTALL_JAVADIR + NO_CHECK_REQUIRED_COMPONENTS_MACRO + INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" + ) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SDL3jarTargets.cmake" + DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}" + ) endif() if(TARGET SDL3-javasources) install(FILES "${SDL3_BINARY_DIR}/SDL3-${SDL3_VERSION}-sources.jar" diff --git a/cmake/SDL3Config.cmake.in b/cmake/SDL3Config.cmake.in index d8b029d4f6549..10f87283b6be8 100644 --- a/cmake/SDL3Config.cmake.in +++ b/cmake/SDL3Config.cmake.in @@ -48,6 +48,11 @@ else() endif() endif() +if(ANDROID AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3jarTargets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/SDL3jarTargets.cmake") + set(SDL3_Jar_FOUND TRUE) +endif() + if(SDL3_SDL3-shared_FOUND OR SDL3_SDL3-static_FOUND) set(SDL3_SDL3_FOUND TRUE) endif() diff --git a/cmake/SDL3jarTargets.cmake.in b/cmake/SDL3jarTargets.cmake.in new file mode 100644 index 0000000000000..732d293ce8bcd --- /dev/null +++ b/cmake/SDL3jarTargets.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set_and_check(SDL3_JAR "@PACKAGE_SDL_INSTALL_JAVADIR@/SDL3/SDL3-@SDL3_VERSION@.jar") + +if(NOT TARGET SDL3::Jar) + add_library(SDL3::Jar INTERFACE IMPORTED) + set_property(TARGET SDL3::Jar PROPERTY JAR_FILE "${SDL3_JAR}") +endif() + +unset(SDL3_JAR) diff --git a/cmake/test/CMakeLists.txt b/cmake/test/CMakeLists.txt index 83ee81dc5166a..f03590f20e74a 100644 --- a/cmake/test/CMakeLists.txt +++ b/cmake/test/CMakeLists.txt @@ -93,4 +93,8 @@ find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) add_executable(gui-whatever WIN32 main_gui.c) target_link_libraries(gui-whatever PRIVATE SDL3::SDL3) +if(ANDROID) + find_package(SDL3 REQUIRED CONFIG COMPONENTS Jar) +endif() + feature_summary(WHAT ALL) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9171dfd1cd3c6..9b917c9c05ffc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -583,7 +583,7 @@ if(SDL_INSTALL_TESTS) ) endif() -if(ANDROID AND TARGET SDL3-jar) +if(ANDROID AND TARGET SDL3::Jar) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake/android") find_package(SdlAndroid MODULE) if(SdlAndroid_FOUND) @@ -640,14 +640,14 @@ if(ANDROID AND TARGET SDL3-jar) COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}" COMMAND ${Java_JAVAC_EXECUTABLE} -source 1.8 -target 1.8 - -bootclasspath "$" + -bootclasspath "$" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" $ - -cp "$:${path_android_jar}" + -cp "$:${SDL_ANDROID_PLATFORM_ANDROID_JAR}" -d "${classes_path}" COMMAND ${Java_JAR_EXECUTABLE} cf "${OUT_JAR}" -C "${classes_path}" . - DEPENDS $ "$" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" + DEPENDS $ "$" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" ) add_custom_target(${TEST}-jar DEPENDS "${OUT_JAR}") set_property(TARGET ${TEST}-jar PROPERTY OUTPUT "${OUT_JAR}") @@ -663,10 +663,10 @@ if(ANDROID AND TARGET SDL3-jar) OUTPUT "${classes_dex}" COMMAND SdlAndroid::d8 $ - $ - --lib "${path_android_jar}" + $ + --lib "${SDL_ANDROID_PLATFORM_ANDROID_JAR}" --output "${dexworkdir}" - DEPENDS $ $ + DEPENDS $ $ ) add_custom_target(${TEST}-dex DEPENDS "${classes_dex}") set_property(TARGET ${TEST}-dex PROPERTY OUTPUT "${classes_dex}") From 42c8366fdc58415c8045097a4f0a0f6f371709b8 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 23 Nov 2023 04:30:56 +0300 Subject: [PATCH 422/725] revise iconv detection: - check libiconv with a linkage test with iconv.h included - check libc iconv with a linkage test with iconv.h included and LIBICONV_PLUG defined (in case libiconv header is in include path) - add new configuration option to prefer iconv from libiconv, if available, over the libc version: SDL_LIBICONV, defaults to disabled. - remove FindIconv + pkg_check_modules for iconv, and use our manual iconv finding only - change FreeBSD specific LIBICONV_PLUG define in SDL_iconv.c to configuration result. --- CMakeLists.txt | 44 +++++++++++-------- include/build_config/SDL_build_config.h.cmake | 5 ++- src/stdlib/SDL_iconv.c | 2 +- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a04b2b39916f..ba5451015020c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,6 +295,7 @@ dep_option(SDL_LASX "Use LASX assembly routines" ON "SDL_ASSEMBLY set_option(SDL_LIBC "Use the system C library" ${SDL_LIBC_DEFAULT}) set_option(SDL_SYSTEM_ICONV "Use iconv() from system-installed libraries" ${SDL_SYSTEM_ICONV_DEFAULT}) +set_option(SDL_LIBICONV "Prefer iconv() from libiconv, if available, over libc version" OFF) set_option(SDL_GCC_ATOMICS "Use gcc builtin atomics" ${SDL_GCC_ATOMICS_DEFAULT}) dep_option(SDL_DBUS "Enable D-Bus support" ON ${UNIX_SYS} OFF) set_option(SDL_DISKAUDIO "Support the disk writer audio driver" ON) @@ -1099,24 +1100,31 @@ if(SDL_LIBC) check_symbol_exists(poll "poll.h" HAVE_POLL) if(SDL_SYSTEM_ICONV) - check_library_exists(iconv iconv_open "" HAVE_LIBICONV) - if(HAVE_LIBICONV) - find_package(Iconv) - if(Iconv_FOUND AND NOT Iconv_IS_BUILT_IN) - set(HAVE_ICONV 1) - set(HAVE_SYSTEM_ICONV TRUE) - pkg_check_modules(PC_ICONV iconv) - if(PC_ICONV_FOUND) - sdl_link_dependency(iconv LIBS Iconv::Iconv CMAKE_MODULE Iconv PKG_CONFIG_SPECS iconv) - else() - sdl_link_dependency(iconv LIBS Iconv::Iconv CMAKE_MODULE Iconv PKG_CONFIG_LIBS iconv) - endif() - endif() - else() - check_library_exists(c iconv_open "" HAVE_BUILTIN_ICONV) - if(HAVE_BUILTIN_ICONV) - set(HAVE_ICONV 1) - set(HAVE_SYSTEM_ICONV TRUE) + check_c_source_compiles(" + #define LIBICONV_PLUG 1 /* in case libiconv header is in include path */ + #include + #include + int main(int argc, char **argv) { + return iconv_open(NULL,NULL); + }" ICONV_IN_LIBC) + + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_LIBRARIES iconv) + check_c_source_compiles(" + #include + #include + int main(int argc, char **argv) { + return iconv_open(NULL,NULL); + }" ICONV_IN_LIBICONV) + cmake_pop_check_state() + + if(ICONV_IN_LIBC OR ICONV_IN_LIBICONV) + set(HAVE_ICONV 1) + set(HAVE_SYSTEM_ICONV TRUE) + if(ICONV_IN_LIBICONV AND (SDL_LIBICONV OR (NOT ICONV_IN_LIBC))) + sdl_link_dependency(iconv LIBS iconv) + set(SDL_USE_LIBICONV 1) + set(HAVE_LIBICONV TRUE) endif() endif() endif() diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 8b26e0dea929d..4c5f9b31c0dbc 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -196,6 +196,7 @@ #cmakedefine HAVE_CLOCK_GETTIME 1 #cmakedefine HAVE_GETPAGESIZE 1 #cmakedefine HAVE_ICONV 1 +#cmakedefine SDL_USE_LIBICONV 1 #cmakedefine HAVE_PTHREAD_SETNAME_NP 1 #cmakedefine HAVE_PTHREAD_SET_NAME_NP 1 #cmakedefine HAVE_SEM_TIMEDWAIT 1 @@ -223,7 +224,7 @@ #cmakedefine HAVE_LINUX_INPUT_H 1 #cmakedefine HAVE_LIBUDEV_H 1 -#cmakedefine HAVE_LIBDECOR_H 1 +#cmakedefine HAVE_LIBDECOR_H 1 #cmakedefine HAVE_D3D_H @HAVE_D3D_H@ #cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@ @@ -487,7 +488,7 @@ #cmakedefine SDL_ARM_NEON_BLITTERS @SDL_ARM_NEON_BLITTERS@ /* Whether SDL_DYNAMIC_API needs dlopen */ -#cmakedefine DYNAPI_NEEDS_DLOPEN @DYNAPI_NEEDS_DLOPEN@ +#cmakedefine DYNAPI_NEEDS_DLOPEN @DYNAPI_NEEDS_DLOPEN@ /* Enable ime support */ #cmakedefine SDL_USE_IME @SDL_USE_IME@ diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c index f1ea29e63e305..2c98b77286f0d 100644 --- a/src/stdlib/SDL_iconv.c +++ b/src/stdlib/SDL_iconv.c @@ -23,7 +23,7 @@ /* This file contains portable iconv functions for SDL */ #if defined(HAVE_ICONV) && defined(HAVE_ICONV_H) -#ifdef __FreeBSD__ +#ifndef SDL_USE_LIBICONV /* Define LIBICONV_PLUG to use iconv from the base instead of ports and avoid linker errors. */ #define LIBICONV_PLUG 1 #endif From 5730eb67f05bd73adfacc4c59753a0a6c7db957d Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 23 Nov 2023 11:33:20 +0300 Subject: [PATCH 423/725] add HAVE_GCC_DIAGNOSTIC_PRAGMA to SDL_internal.h, use it --- src/SDL_internal.h | 4 ++++ src/SDL_log.c | 4 ++-- src/hidapi/windows/hid.c | 12 ++++++------ src/hidapi/windows/hidapi_descriptor_reconstruct.h | 4 ++++ src/render/direct3d11/SDL_render_d3d11.c | 4 ++-- src/render/direct3d12/SDL_render_d3d12.c | 4 ++-- src/render/ps2/SDL_render_ps2.c | 6 ++++++ src/video/ps2/SDL_ps2video.h | 6 ++++++ src/video/x11/SDL_x11sym.h | 4 ++-- 9 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/SDL_internal.h b/src/SDL_internal.h index b0f2c296f64f4..8c5463a924fb4 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -40,6 +40,10 @@ #define SDL_VARIABLE_LENGTH_ARRAY #endif +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__) +#define HAVE_GCC_DIAGNOSTIC_PRAGMA 1 +#endif + #define SDL_MAX_SMALL_ALLOC_STACKSIZE 128 #define SDL_small_alloc(type, count, pisstack) ((*(pisstack) = ((sizeof(type) * (count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type *)SDL_malloc(sizeof(type) * (count)))) #define SDL_small_free(ptr, isstack) \ diff --git a/src/SDL_log.c b/src/SDL_log.c index a9ac740c42783..89cc380c863b1 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -65,7 +65,7 @@ static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput; static void *SDL_log_userdata = NULL; static SDL_Mutex *log_function_mutex = NULL; -#ifdef __GNUC__ +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #endif @@ -80,7 +80,7 @@ static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = { "CRITICAL" }; -#ifdef __GNUC__ +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif diff --git a/src/hidapi/windows/hid.c b/src/hidapi/windows/hid.c index e8b6ee9870143..3a90a3db37cf0 100644 --- a/src/hidapi/windows/hid.c +++ b/src/hidapi/windows/hid.c @@ -120,7 +120,7 @@ static void free_library_handles() cfgmgr32_lib_handle = NULL; } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-function-type" #endif @@ -170,7 +170,7 @@ static int lookup_functions() return -1; } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic pop #endif @@ -325,7 +325,7 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR #endif } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" #endif @@ -355,7 +355,7 @@ static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR #endif /* HIDAPI_USING_SDL_RUNTIME */ } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic pop #endif @@ -1462,7 +1462,7 @@ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned c return hid_get_report(dev, IOCTL_HID_GET_INPUT_REPORT, data, length); } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-function-type" #endif @@ -1486,7 +1486,7 @@ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) } free_hid_device(dev); } -#if defined(__GNUC__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA # pragma GCC diagnostic pop #endif diff --git a/src/hidapi/windows/hidapi_descriptor_reconstruct.h b/src/hidapi/windows/hidapi_descriptor_reconstruct.h index 5f0b54aa0f141..6f3e37f744c45 100644 --- a/src/hidapi/windows/hidapi_descriptor_reconstruct.h +++ b/src/hidapi/windows/hidapi_descriptor_reconstruct.h @@ -217,11 +217,15 @@ typedef struct hidp_preparsed_data_ { // MINGW fails with: Flexible array member in union not supported // Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html union { +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" +#endif hid_pp_cap caps[0]; hid_pp_link_collection_node LinkCollectionArray[0]; +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop +#endif }; #else union { diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 2263f883276c0..103eb21715f82 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -175,7 +175,7 @@ typedef struct * linker errors in WinRT/UWP builds.) */ -#ifdef __GNUC__ +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-const-variable" #endif @@ -190,7 +190,7 @@ static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } }; /*static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };*/ -#ifdef __GNUC__ +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index c241c3bc9cbcf..dee07a4898741 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -235,7 +235,7 @@ typedef struct /* Define D3D GUIDs here so we don't have to include uuid.lib. */ -#if defined(__GNUC__) || defined(__clang__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-const-variable" #endif @@ -260,7 +260,7 @@ static const GUID SDL_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { static const GUID SDL_IID_ID3D12Heap = { 0x6b3b2502, 0x6e51, 0x45b3, { 0x90, 0xee, 0x98, 0x84, 0x26, 0x5e, 0x8d, 0xf3 } }; static const GUID SDL_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } }; -#if defined(__GNUC__) || defined(__clang__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index 467d2745c048a..9d02c3e768abb 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -30,10 +30,16 @@ #include #include +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeclaration-after-statement" +#endif + #include + +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop +#endif /* turn black GS Screen */ #define GS_BLACK GS_SETREG_RGBA(0x00, 0x00, 0x00, 0x80) diff --git a/src/video/ps2/SDL_ps2video.h b/src/video/ps2/SDL_ps2video.h index 33563ea88c821..ef255736f3fef 100644 --- a/src/video/ps2/SDL_ps2video.h +++ b/src/video/ps2/SDL_ps2video.h @@ -32,9 +32,15 @@ #include +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeclaration-after-statement" +#endif + #include + +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop +#endif #endif /* SDL_ps2video_h_ */ diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 67f74d4b0f0a9..001633a5e2683 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -194,7 +194,7 @@ SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c #endif /* XKeycodeToKeysym is a deprecated function */ -#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif @@ -203,7 +203,7 @@ SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),re #else SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return) #endif -#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__) +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif From aaba01aee468d9f06fb4b0f8ce9812b85272eca7 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 23 Nov 2023 11:35:02 +0300 Subject: [PATCH 424/725] hidapi: syncing with mainstream: - macos, pthread_barrier_wait: properly check the wait condition - windows: Assert that struct has the correct size - windows: Fix printf/string-related issues - other miscellaneous stuff irrelevant in SDL. (for symmetry...) --- src/hidapi/BUILD.cmake.md | 2 +- src/hidapi/hidtest/test.c | 2 +- src/hidapi/libusb/hid.c | 2 +- src/hidapi/mac/hid.c | 20 +-- src/hidapi/src/CMakeLists.txt | 5 +- .../windows/hidapi_descriptor_reconstruct.h | 11 +- .../windows/pp_data_dump/pp_data_dump.c | 130 ++++++++-------- .../test/hid_report_reconstructor_test.c | 144 +++++++++--------- 8 files changed, 165 insertions(+), 151 deletions(-) diff --git a/src/hidapi/BUILD.cmake.md b/src/hidapi/BUILD.cmake.md index aa5ba740d07dc..5555fd2ea6a63 100644 --- a/src/hidapi/BUILD.cmake.md +++ b/src/hidapi/BUILD.cmake.md @@ -214,7 +214,7 @@ This is done to let the host project's developer decide what is important (what In a _subdirectory build_, even if not set, those variables remain unchanged, so a host project's developer has a full control over the HIDAPI build configuration. Available CMake targets after `add_subdirectory(hidapi)` _are the same as in case of [standalone build](#standalone-package-build)_, and a few additional ones: -- `hidapi_include` - the interface library; `hidapi::hidapi` is an alias of it; +- `hidapi_include` - the interface library; `hidapi::include` is an alias of it; - `hidapi_winapi` - library target on Windows; `hidapi::winapi` is an alias of it; - `hidapi_darwin` - library target on macOS; `hidapi::darwin` is an alias of it; - `hidapi_libusb` - library target for libusb backend; `hidapi::libusb` is an alias of it; diff --git a/src/hidapi/hidtest/test.c b/src/hidapi/hidtest/test.c index 94bbf37a33a56..1eb658229a003 100644 --- a/src/hidapi/hidtest/test.c +++ b/src/hidapi/hidtest/test.c @@ -77,7 +77,7 @@ void print_device(struct hid_device_info *cur_dev) { printf(" Release: %hx\n", cur_dev->release_number); printf(" Interface: %d\n", cur_dev->interface_number); printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page); - printf(" Bus type: %d (%s)\n", cur_dev->bus_type, hid_bus_name(cur_dev->bus_type)); + printf(" Bus type: %u (%s)\n", (unsigned)cur_dev->bus_type, hid_bus_name(cur_dev->bus_type)); printf("\n"); } diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index b063dafe39f45..f0ec00ca7ff8c 100644 --- a/src/hidapi/libusb/hid.c +++ b/src/hidapi/libusb/hid.c @@ -2088,7 +2088,7 @@ uint16_t get_usb_code_for_current_locale(void) return 0x0; /* Make a copy of the current locale string. */ - strncpy(search_string, locale, sizeof(search_string)); + strncpy(search_string, locale, sizeof(search_string)-1); search_string[sizeof(search_string)-1] = '\0'; /* Chop off the encoding part, and make it lower case. */ diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c index 1eb49b5d3120b..ee6666b6963a3 100644 --- a/src/hidapi/mac/hid.c +++ b/src/hidapi/mac/hid.c @@ -54,15 +54,15 @@ static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrie { (void) attr; - if(count == 0) { + if (count == 0) { errno = EINVAL; return -1; } - if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + if (pthread_mutex_init(&barrier->mutex, 0) < 0) { return -1; } - if(pthread_cond_init(&barrier->cond, 0) < 0) { + if (pthread_cond_init(&barrier->cond, 0) < 0) { pthread_mutex_destroy(&barrier->mutex); return -1; } @@ -83,16 +83,18 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier) { pthread_mutex_lock(&barrier->mutex); ++(barrier->count); - if(barrier->count >= barrier->trip_count) - { + if (barrier->count >= barrier->trip_count) { barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); pthread_mutex_unlock(&barrier->mutex); + pthread_cond_broadcast(&barrier->cond); return 1; } - else - { - pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + else { + do { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + } + while (barrier->count != 0); + pthread_mutex_unlock(&barrier->mutex); return 0; } diff --git a/src/hidapi/src/CMakeLists.txt b/src/hidapi/src/CMakeLists.txt index d08224be8ed43..507b2d13e231e 100644 --- a/src/hidapi/src/CMakeLists.txt +++ b/src/hidapi/src/CMakeLists.txt @@ -68,8 +68,9 @@ function(hidapi_configure_pc PC_IN_FILE) get_filename_component(PC_IN_FILENAME "${PC_IN_FILE}" NAME_WE) set(PC_FILE "${CMAKE_CURRENT_BINARY_DIR}/pc/${PC_IN_FILENAME}.pc") configure_file("${PC_IN_FILE}" "${PC_FILE}" @ONLY) - - install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") + if(HIDAPI_INSTALL_TARGETS) + install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") + endif() endfunction() # The library diff --git a/src/hidapi/windows/hidapi_descriptor_reconstruct.h b/src/hidapi/windows/hidapi_descriptor_reconstruct.h index 6f3e37f744c45..a6223b6a4027e 100644 --- a/src/hidapi/windows/hidapi_descriptor_reconstruct.h +++ b/src/hidapi/windows/hidapi_descriptor_reconstruct.h @@ -37,6 +37,7 @@ #include #include "hidapi_hidsdi.h" +/*#include */ #define NUM_OF_HIDP_REPORT_TYPES 3 @@ -125,6 +126,14 @@ typedef struct hid_pp_link_collection_node_ { // Same as the public API structure HIDP_LINK_COLLECTION_NODE, but without PVOID UserContext at the end } hid_pp_link_collection_node, *phid_pp_link_collection_node; +// Note: This is risk-reduction-measure for this specific struct, as it has ULONG bit-field. +// Although very unlikely, it might still be possible that the compiler creates a memory layout that is +// not binary compatile. +// Other structs are not checked at the time of writing. +//static_assert(sizeof(struct hid_pp_link_collection_node_) == 16, +// "Size of struct hid_pp_link_collection_node_ not as expected. This might break binary compatibility"); +SDL_COMPILE_TIME_ASSERT(hid_pp_link_collection_node_, sizeof(struct hid_pp_link_collection_node_) == 16); + typedef struct hidp_unknown_token_ { UCHAR Token; /* Specifies the one-byte prefix of a global item. */ UCHAR Reserved[3]; @@ -213,7 +222,7 @@ typedef struct hidp_preparsed_data_ { USHORT FirstByteOfLinkCollectionArray; USHORT NumberLinkCollectionNodes; -#if defined(__MINGW32__) || defined(__CYGWIN__) +#ifndef _MSC_VER // MINGW fails with: Flexible array member in union not supported // Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html union { diff --git a/src/hidapi/windows/pp_data_dump/pp_data_dump.c b/src/hidapi/windows/pp_data_dump/pp_data_dump.c index 561dc96af65a7..d5df68b50f520 100644 --- a/src/hidapi/windows/pp_data_dump/pp_data_dump.c +++ b/src/hidapi/windows/pp_data_dump/pp_data_dump.c @@ -1,95 +1,95 @@ - +#if defined(__MINGW32__) + // Needed for %hh + #define __USE_MINGW_ANSI_STDIO 1 +#endif #include #include <../windows/hidapi_descriptor_reconstruct.h> #include -#if defined(__MINGW32__) -#pragma GCC diagnostic ignored "-Wformat" -#pragma GCC diagnostic ignored "-Wformat-extra-args" -#endif - void dump_hid_pp_cap(FILE* file, phid_pp_cap pp_cap, unsigned int cap_idx) { - fprintf(file, "pp_data->cap[%d]->UsagePage = 0x%04hX\n", cap_idx, pp_cap->UsagePage); - fprintf(file, "pp_data->cap[%d]->ReportID = 0x%02hhX\n", cap_idx, pp_cap->ReportID); - fprintf(file, "pp_data->cap[%d]->BitPosition = %hhu\n", cap_idx, pp_cap->BitPosition); - fprintf(file, "pp_data->cap[%d]->BitSize = %hu\n", cap_idx, pp_cap->ReportSize); - fprintf(file, "pp_data->cap[%d]->ReportCount = %hu\n", cap_idx, pp_cap->ReportCount); - fprintf(file, "pp_data->cap[%d]->BytePosition = 0x%04hX\n", cap_idx, pp_cap->BytePosition); - fprintf(file, "pp_data->cap[%d]->BitCount = %hu\n", cap_idx, pp_cap->BitCount); - fprintf(file, "pp_data->cap[%d]->BitField = 0x%02lX\n", cap_idx, pp_cap->BitField); - fprintf(file, "pp_data->cap[%d]->NextBytePosition = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition); - fprintf(file, "pp_data->cap[%d]->LinkCollection = 0x%04hX\n", cap_idx, pp_cap->LinkCollection); - fprintf(file, "pp_data->cap[%d]->LinkUsagePage = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage); - fprintf(file, "pp_data->cap[%d]->LinkUsage = 0x%04hX\n", cap_idx, pp_cap->LinkUsage); + fprintf(file, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", cap_idx, pp_cap->UsagePage); + fprintf(file, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", cap_idx, pp_cap->ReportID); + fprintf(file, "pp_data->cap[%u]->BitPosition = %hhu\n", cap_idx, pp_cap->BitPosition); + fprintf(file, "pp_data->cap[%u]->BitSize = %hu\n", cap_idx, pp_cap->ReportSize); + fprintf(file, "pp_data->cap[%u]->ReportCount = %hu\n", cap_idx, pp_cap->ReportCount); + fprintf(file, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", cap_idx, pp_cap->BytePosition); + fprintf(file, "pp_data->cap[%u]->BitCount = %hu\n", cap_idx, pp_cap->BitCount); + fprintf(file, "pp_data->cap[%u]->BitField = 0x%02lX\n", cap_idx, pp_cap->BitField); + fprintf(file, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition); + fprintf(file, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", cap_idx, pp_cap->LinkCollection); + fprintf(file, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage); + fprintf(file, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", cap_idx, pp_cap->LinkUsage); // 8 Flags in one byte - fprintf(file, "pp_data->cap[%d]->IsMultipleItemsForArray = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray); - fprintf(file, "pp_data->cap[%d]->IsButtonCap = %hhu\n", cap_idx, pp_cap->IsButtonCap); - fprintf(file, "pp_data->cap[%d]->IsPadding = %hhu\n", cap_idx, pp_cap->IsPadding); - fprintf(file, "pp_data->cap[%d]->IsAbsolute = %hhu\n", cap_idx, pp_cap->IsAbsolute); - fprintf(file, "pp_data->cap[%d]->IsRange = %hhu\n", cap_idx, pp_cap->IsRange); - fprintf(file, "pp_data->cap[%d]->IsAlias = %hhu\n", cap_idx, pp_cap->IsAlias); - fprintf(file, "pp_data->cap[%d]->IsStringRange = %hhu\n", cap_idx, pp_cap->IsStringRange); - fprintf(file, "pp_data->cap[%d]->IsDesignatorRange = %hhu\n", cap_idx, pp_cap->IsDesignatorRange); + fprintf(file, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray); + fprintf(file, "pp_data->cap[%u]->IsButtonCap = %hhu\n", cap_idx, pp_cap->IsButtonCap); + fprintf(file, "pp_data->cap[%u]->IsPadding = %hhu\n", cap_idx, pp_cap->IsPadding); + fprintf(file, "pp_data->cap[%u]->IsAbsolute = %hhu\n", cap_idx, pp_cap->IsAbsolute); + fprintf(file, "pp_data->cap[%u]->IsRange = %hhu\n", cap_idx, pp_cap->IsRange); + fprintf(file, "pp_data->cap[%u]->IsAlias = %hhu\n", cap_idx, pp_cap->IsAlias); + fprintf(file, "pp_data->cap[%u]->IsStringRange = %hhu\n", cap_idx, pp_cap->IsStringRange); + fprintf(file, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", cap_idx, pp_cap->IsDesignatorRange); - fprintf(file, "pp_data->cap[%d]->Reserved1 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]); + fprintf(file, "pp_data->cap[%u]->Reserved1 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]); for (int token_idx = 0; token_idx < 4; token_idx++) { - fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token); - fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]); - fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField); + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token); + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]); + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField); } if (pp_cap->IsRange) { - fprintf(file, "pp_data->cap[%d]->Range.UsageMin = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin); - fprintf(file, "pp_data->cap[%d]->Range.UsageMax = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax); - fprintf(file, "pp_data->cap[%d]->Range.StringMin = %hu\n", cap_idx, pp_cap->Range.StringMin); - fprintf(file, "pp_data->cap[%d]->Range.StringMax = %hu\n", cap_idx, pp_cap->Range.StringMax); - fprintf(file, "pp_data->cap[%d]->Range.DesignatorMin = %hu\n", cap_idx, pp_cap->Range.DesignatorMin); - fprintf(file, "pp_data->cap[%d]->Range.DesignatorMax = %hu\n", cap_idx, pp_cap->Range.DesignatorMax); - fprintf(file, "pp_data->cap[%d]->Range.DataIndexMin = %hu\n", cap_idx, pp_cap->Range.DataIndexMin); - fprintf(file, "pp_data->cap[%d]->Range.DataIndexMax = %hu\n", cap_idx, pp_cap->Range.DataIndexMax); + fprintf(file, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin); + fprintf(file, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax); + fprintf(file, "pp_data->cap[%u]->Range.StringMin = %hu\n", cap_idx, pp_cap->Range.StringMin); + fprintf(file, "pp_data->cap[%u]->Range.StringMax = %hu\n", cap_idx, pp_cap->Range.StringMax); + fprintf(file, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", cap_idx, pp_cap->Range.DesignatorMin); + fprintf(file, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", cap_idx, pp_cap->Range.DesignatorMax); + fprintf(file, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", cap_idx, pp_cap->Range.DataIndexMin); + fprintf(file, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", cap_idx, pp_cap->Range.DataIndexMax); } else { - fprintf(file, "pp_data->cap[%d]->NotRange.Usage = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage); - fprintf(file, "pp_data->cap[%d]->NotRange.Reserved1 = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1); - fprintf(file, "pp_data->cap[%d]->NotRange.StringIndex = %hu\n", cap_idx, pp_cap->NotRange.StringIndex); - fprintf(file, "pp_data->cap[%d]->NotRange.Reserved2 = %hu\n", cap_idx, pp_cap->NotRange.Reserved2); - fprintf(file, "pp_data->cap[%d]->NotRange.DesignatorIndex = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex); - fprintf(file, "pp_data->cap[%d]->NotRange.Reserved3 = %hu\n", cap_idx, pp_cap->NotRange.Reserved3); - fprintf(file, "pp_data->cap[%d]->NotRange.DataIndex = %hu\n", cap_idx, pp_cap->NotRange.DataIndex); - fprintf(file, "pp_data->cap[%d]->NotRange.Reserved4 = %hu\n", cap_idx, pp_cap->NotRange.Reserved4); + fprintf(file, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1); + fprintf(file, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", cap_idx, pp_cap->NotRange.StringIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", cap_idx, pp_cap->NotRange.Reserved2); + fprintf(file, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", cap_idx, pp_cap->NotRange.Reserved3); + fprintf(file, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", cap_idx, pp_cap->NotRange.DataIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", cap_idx, pp_cap->NotRange.Reserved4); } if (pp_cap->IsButtonCap) { - fprintf(file, "pp_data->cap[%d]->Button.LogicalMin = %ld\n", cap_idx, pp_cap->Button.LogicalMin); - fprintf(file, "pp_data->cap[%d]->Button.LogicalMax = %ld\n", cap_idx, pp_cap->Button.LogicalMax); + fprintf(file, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", cap_idx, pp_cap->Button.LogicalMin); + fprintf(file, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", cap_idx, pp_cap->Button.LogicalMax); } else { - fprintf(file, "pp_data->cap[%d]->NotButton.HasNull = %hhu\n", cap_idx, pp_cap->NotButton.HasNull); - fprintf(file, "pp_data->cap[%d]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]); - fprintf(file, "pp_data->cap[%d]->NotButton.LogicalMin = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin); - fprintf(file, "pp_data->cap[%d]->NotButton.LogicalMax = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax); - fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMin = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin); - fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMax = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax); + fprintf(file, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", cap_idx, pp_cap->NotButton.HasNull); + fprintf(file, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]); + fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin); + fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax); + fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin); + fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax); }; - fprintf(file, "pp_data->cap[%d]->Units = %lu\n", cap_idx, pp_cap->Units); - fprintf(file, "pp_data->cap[%d]->UnitsExp = %lu\n", cap_idx, pp_cap->UnitsExp); + fprintf(file, "pp_data->cap[%u]->Units = %lu\n", cap_idx, pp_cap->Units); + fprintf(file, "pp_data->cap[%u]->UnitsExp = %lu\n", cap_idx, pp_cap->UnitsExp); } void dump_hidp_link_collection_node(FILE* file, phid_pp_link_collection_node pcoll, unsigned int coll_idx) { - fprintf(file, "pp_data->LinkCollectionArray[%d]->LinkUsage = 0x%04hX\n", coll_idx, pcoll->LinkUsage); - fprintf(file, "pp_data->LinkCollectionArray[%d]->LinkUsagePage = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage); - fprintf(file, "pp_data->LinkCollectionArray[%d]->Parent = %hu\n", coll_idx, pcoll->Parent); - fprintf(file, "pp_data->LinkCollectionArray[%d]->NumberOfChildren = %hu\n", coll_idx, pcoll->NumberOfChildren); - fprintf(file, "pp_data->LinkCollectionArray[%d]->NextSibling = %hu\n", coll_idx, pcoll->NextSibling); - fprintf(file, "pp_data->LinkCollectionArray[%d]->FirstChild = %hu\n", coll_idx, pcoll->FirstChild); - fprintf(file, "pp_data->LinkCollectionArray[%d]->CollectionType = %d\n", coll_idx, pcoll->CollectionType); - fprintf(file, "pp_data->LinkCollectionArray[%d]->IsAlias = %d\n", coll_idx, pcoll->IsAlias); - fprintf(file, "pp_data->LinkCollectionArray[%d]->Reserved = 0x%08X\n", coll_idx, pcoll->Reserved); + fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", coll_idx, pcoll->LinkUsage); + fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage); + fprintf(file, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", coll_idx, pcoll->Parent); + fprintf(file, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", coll_idx, pcoll->NumberOfChildren); + fprintf(file, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", coll_idx, pcoll->NextSibling); + fprintf(file, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", coll_idx, pcoll->FirstChild); + // The compilers are not consistent on ULONG-bit-fields: They lose the unsinged or define them as int. + // Thus just always cast them to unsinged int, which should be fine, as the biggest bit-field is 28 bit + fprintf(file, "pp_data->LinkCollectionArray[%u]->CollectionType = %u\n", coll_idx, (unsigned int)(pcoll->CollectionType)); + fprintf(file, "pp_data->LinkCollectionArray[%u]->IsAlias = %u\n", coll_idx, (unsigned int)(pcoll->IsAlias)); + fprintf(file, "pp_data->LinkCollectionArray[%u]->Reserved = 0x%08X\n", coll_idx, (unsigned int)(pcoll->Reserved)); } int dump_pp_data(FILE* file, hid_device* dev) diff --git a/src/hidapi/windows/test/hid_report_reconstructor_test.c b/src/hidapi/windows/test/hid_report_reconstructor_test.c index 4c94fd9766db7..a7adeb54d0426 100644 --- a/src/hidapi/windows/test/hid_report_reconstructor_test.c +++ b/src/hidapi/windows/test/hid_report_reconstructor_test.c @@ -1,12 +1,14 @@ +#if defined(__MINGW32__) + // Needed for %zu + #define __USE_MINGW_ANSI_STDIO 1 +#endif + #include "../hidapi_descriptor_reconstruct.h" #include #include #include -#if defined(__MINGW32__) -#pragma GCC diagnostic ignored "-Wformat" -#endif static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) { FILE* file; @@ -107,25 +109,25 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) if (sscanf(line, "pp_data->UsagePage = 0x%04hX\n", &pp_data->UsagePage)) continue; if (sscanf(line, "pp_data->Reserved = 0x%04hX%04hX\n", &pp_data->Reserved[0], &pp_data->Reserved[1])) continue; - if (sscanf(line, "pp_data->caps_info[%d]", &rt_idx) == 1) { + if (sscanf(line, "pp_data->caps_info[%u]", &rt_idx) == 1) { const size_t caps_info_count = sizeof(pp_data->caps_info) / sizeof(pp_data->caps_info[0]); if (rt_idx >= caps_info_count) { fprintf(stderr, "Broken pp_data file, pp_data->caps_info[] can have at most %zu elements, accessing %ud, (%s)", caps_info_count, rt_idx, line); continue; } - if (sscanf(line, "pp_data->caps_info[%d]->FirstCap = %hu\n", &rt_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->caps_info[%u]->FirstCap = %hu\n", &rt_idx, &temp_ushort) == 2) { pp_data->caps_info[rt_idx].FirstCap = temp_ushort; continue; } - if (sscanf(line, "pp_data->caps_info[%d]->LastCap = %hu\n", &rt_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->caps_info[%u]->LastCap = %hu\n", &rt_idx, &temp_ushort) == 2) { pp_data->caps_info[rt_idx].LastCap = temp_ushort; continue; } - if (sscanf(line, "pp_data->caps_info[%d]->NumberOfCaps = %hu\n", &rt_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->caps_info[%u]->NumberOfCaps = %hu\n", &rt_idx, &temp_ushort) == 2) { pp_data->caps_info[rt_idx].NumberOfCaps = temp_ushort; continue; } - if (sscanf(line, "pp_data->caps_info[%d]->ReportByteLength = %hu\n", &rt_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->caps_info[%u]->ReportByteLength = %hu\n", &rt_idx, &temp_ushort) == 2) { pp_data->caps_info[rt_idx].ReportByteLength = temp_ushort; continue; } @@ -140,7 +142,7 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) continue; } - if (sscanf(line, "pp_data->cap[%d]", &caps_idx) == 1) { + if (sscanf(line, "pp_data->cap[%u]", &caps_idx) == 1) { if (pp_data->FirstByteOfLinkCollectionArray == 0) { fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray is 0 or not reported yet\n", line); continue; @@ -149,113 +151,113 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) fprintf(stderr, "Error reading pp_data file (%s): the caps index (%u) is out of pp_data bytes boundary (%hu vs %hu)\n", line, caps_idx, (unsigned short) ((caps_idx + 1) * sizeof(hid_pp_cap)), pp_data->FirstByteOfLinkCollectionArray); continue; } - if (sscanf(line, "pp_data->cap[%d]->UsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].UsagePage = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->ReportID = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) { pp_data->caps[caps_idx].ReportID = temp_uchar[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->BitPosition = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->BitPosition = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) { pp_data->caps[caps_idx].BitPosition = temp_uchar[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->BitSize = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->BitSize = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].ReportSize = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->ReportCount = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->ReportCount = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].ReportCount = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->BytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].BytePosition = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->BitCount = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->BitCount = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].BitCount = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->BitField = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->cap[%u]->BitField = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) { pp_data->caps[caps_idx].BitField = temp_ulong; continue; } - if (sscanf(line, "pp_data->cap[%d]->NextBytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NextBytePosition = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->LinkCollection = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].LinkCollection = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->LinkUsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].LinkUsagePage = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->LinkUsage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].LinkUsage = temp_usage; continue; } // 8 Flags in one byte - if (sscanf(line, "pp_data->cap[%d]->IsMultipleItemsForArray = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsMultipleItemsForArray = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsButtonCap = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsButtonCap = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsButtonCap = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsPadding = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsPadding = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsPadding = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsAbsolute = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsAbsolute = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsAbsolute = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsRange = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsAlias = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsAlias = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsAlias = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsStringRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsStringRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsStringRange = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->IsDesignatorRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].IsDesignatorRange = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->Reserved1 = 0x%hhu%hhu%hhu\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%hhu%hhu%hhu\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; continue; } - if (sscanf(line, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d]", &caps_idx, &token_idx) == 2) { + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u]", &caps_idx, &token_idx) == 2) { const size_t unknown_tokens_count = sizeof(pp_data->caps[0].UnknownTokens) / sizeof(pp_data->caps[0].UnknownTokens[0]); if (token_idx >= unknown_tokens_count) { fprintf(stderr, "Broken pp_data file, pp_data->caps[].UnknownTokens[] can have at most %zu elements, accessing %ud, (%s)", unknown_tokens_count, token_idx, line); continue; } - if (sscanf(line, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0]) == 3) { + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Token = 0x%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0]) == 3) { pp_data->caps[caps_idx].UnknownTokens[token_idx].Token = temp_uchar[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 5) { + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Reserved = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 5) { pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[0] = temp_uchar[0]; pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[1] = temp_uchar[1]; pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[2] = temp_uchar[2]; continue; } - if (sscanf(line, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", &caps_idx, &token_idx, &temp_ulong) == 3) { + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].BitField = 0x%08lX\n", &caps_idx, &token_idx, &temp_ulong) == 3) { pp_data->caps[caps_idx].UnknownTokens[token_idx].BitField = temp_ulong; continue; } @@ -264,120 +266,120 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) } // Range - if (sscanf(line, "pp_data->cap[%d]->Range.UsageMin = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].Range.UsageMin = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.UsageMax = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].Range.UsageMax = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.StringMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.StringMin = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.StringMin = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.StringMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.StringMax = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.StringMax = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.DesignatorMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.DesignatorMin = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.DesignatorMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.DesignatorMax = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.DataIndexMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.DataIndexMin = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->Range.DataIndexMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].Range.DataIndexMax = temp_ushort; continue; } // NotRange - if (sscanf(line, "pp_data->cap[%d]->NotRange.Usage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].NotRange.Usage = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.Reserved1 = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { pp_data->caps[caps_idx].NotRange.Reserved1 = temp_usage; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.StringIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.StringIndex = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.Reserved2 = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.Reserved2 = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.DesignatorIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.DesignatorIndex = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.Reserved3 = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.Reserved3 = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.DataIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.DataIndex = temp_ushort; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotRange.Reserved4 = %hu\n", &caps_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", &caps_idx, &temp_ushort) == 2) { pp_data->caps[caps_idx].NotRange.Reserved4 = temp_ushort; continue; } // Button - if (sscanf(line, "pp_data->cap[%d]->Button.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].Button.LogicalMin = temp_long; continue; } - if (sscanf(line, "pp_data->cap[%d]->Button.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].Button.LogicalMax = temp_long; continue; } // NotButton - if (sscanf(line, "pp_data->cap[%d]->NotButton.HasNull = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { pp_data->caps[caps_idx].NotButton.HasNull = temp_boolean[0]; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { pp_data->caps[caps_idx].NotButton.Reserved4[0] = temp_uchar[0]; pp_data->caps[caps_idx].NotButton.Reserved4[1] = temp_uchar[1]; pp_data->caps[caps_idx].NotButton.Reserved4[2] = temp_uchar[2]; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotButton.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].NotButton.LogicalMin = temp_long; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotButton.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].NotButton.LogicalMax = temp_long; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotButton.PhysicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].NotButton.PhysicalMin = temp_long; continue; } - if (sscanf(line, "pp_data->cap[%d]->NotButton.PhysicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", &caps_idx, &temp_long) == 2) { pp_data->caps[caps_idx].NotButton.PhysicalMax = temp_long; continue; } - if (sscanf(line, "pp_data->cap[%d]->Units = %lu\n", &caps_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->cap[%u]->Units = %lu\n", &caps_idx, &temp_ulong) == 2) { pp_data->caps[caps_idx].Units = temp_ulong; continue; } - if (sscanf(line, "pp_data->cap[%d]->UnitsExp = %lu\n", &caps_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->cap[%u]->UnitsExp = %lu\n", &caps_idx, &temp_ulong) == 2) { pp_data->caps[caps_idx].UnitsExp = temp_ulong; continue; } - if (sscanf(line, "pp_data->cap[%d]->Reserved1 = 0x%02hhu%02hhu%02hhu\n", &coll_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%02hhu%02hhu%02hhu\n", &coll_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; @@ -387,7 +389,7 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]", &coll_idx) == 1) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]", &coll_idx) == 1) { if (pp_data->FirstByteOfLinkCollectionArray == 0 || pp_data->NumberLinkCollectionNodes == 0) { fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray or NumberLinkCollectionNodes is 0 or not reported yet\n", line); continue; @@ -397,39 +399,39 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) continue; } phid_pp_link_collection_node pcoll = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray); - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->LinkUsage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { pcoll[coll_idx].LinkUsage = temp_usage; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->LinkUsagePage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { pcoll[coll_idx].LinkUsagePage = temp_usage; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->Parent = %hu\n", &coll_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", &coll_idx, &temp_ushort) == 2) { pcoll[coll_idx].Parent = temp_ushort; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->NumberOfChildren = %hu\n", &coll_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", &coll_idx, &temp_ushort) == 2) { pcoll[coll_idx].NumberOfChildren = temp_ushort; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->NextSibling = %hu\n", &coll_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", &coll_idx, &temp_ushort) == 2) { pcoll[coll_idx].NextSibling = temp_ushort; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->FirstChild = %hu\n", &coll_idx, &temp_ushort) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", &coll_idx, &temp_ushort) == 2) { pcoll[coll_idx].FirstChild = temp_ushort; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->CollectionType = %ld\n", &coll_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->CollectionType = %lu\n", &coll_idx, &temp_ulong) == 2) { pcoll[coll_idx].CollectionType = temp_ulong; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->IsAlias = %ld\n", &coll_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->IsAlias = %lu\n", &coll_idx, &temp_ulong) == 2) { pcoll[coll_idx].IsAlias = temp_ulong; continue; } - if (sscanf(line, "pp_data->LinkCollectionArray[%d]->Reserved = %ld\n", &coll_idx, &temp_ulong) == 2) { + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Reserved = %lu\n", &coll_idx, &temp_ulong) == 2) { pcoll[coll_idx].Reserved = temp_ulong; continue; } From 08fac5b1b2cbee512004c2c2c261f6408e8d794c Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Thu, 23 Nov 2023 11:56:50 +0300 Subject: [PATCH 425/725] SDL_PenModifyForWacomID: return zero as axis_flags upon failure. Fixes uninitialized warning in testautomation_pen.c: testautomation_pen.c:1512: warning: 'mask' may be used uninitialized in this function --- src/events/SDL_pen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index 78e6b617c0c72..3f545e56ea545 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -1058,6 +1058,7 @@ int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *ax } if (!name) { + *axis_flags = 0; return SDL_FALSE; } From 74a25425646d64edeff508ec8e99622a41576905 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 23 Nov 2023 13:47:13 -0500 Subject: [PATCH 426/725] x11: Deal with difference in GLX_EXT_swap_control_tear behavior. Mesa and Nvidia handle it differently, and one or the other may fix their implementation in the future, so test which way it works at runtime. Reference Issue #8004. --- src/video/x11/SDL_x11opengl.c | 68 ++++++++++++++++++++++++++++++++--- src/video/x11/SDL_x11opengl.h | 10 ++++++ test/testgl.c | 21 ++++++----- 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 1a24358b24f74..aad96462d56cb 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -237,6 +237,8 @@ int X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) return SDL_SetError("GLX is not supported"); } + _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNTESTED; + /* Initialize extensions */ /* See lengthy comment about the inc/dec in ../windows/SDL_windowsopengl.c. */ @@ -902,7 +904,6 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval) X11_GL_GetSwapInterval(_this, ¤tInterval); _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval); _this->gl_data->glXSwapIntervalEXT(display, drawable, interval); - status = 0; swapinterval = interval; } else if (_this->gl_data->glXSwapIntervalMESA) { @@ -925,6 +926,53 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval) return status; } +static SDL_GLSwapIntervalTearBehavior CheckSwapIntervalTearBehavior(SDL_VideoDevice *_this, Window drawable, unsigned int current_val, unsigned int current_allow_late) +{ + /* Mesa and Nvidia interpret GLX_EXT_swap_control_tear differently, as of this writing, so + figure out which behavior we have. + Technical details: https://github.com/libsdl-org/SDL/issues/8004#issuecomment-1819603282 */ + if (_this->gl_data->swap_interval_tear_behavior == SDL_SWAPINTERVALTEAR_UNTESTED) { + if (!_this->gl_data->HAS_GLX_EXT_swap_control_tear) { + _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN; + } else { + Display *display = _this->driverdata->display; + unsigned int allow_late_swap_tearing = 22; + int original_val = (int) current_val; + + /* + * This is a workaround for a bug in NVIDIA drivers. Bug has been reported + * and will be fixed in a future release (probably 319.xx). + * + * There's a bug where glXSetSwapIntervalEXT ignores updates because + * it has the wrong value cached. To work around it, we just run a no-op + * update to the current value. + */ + _this->gl_data->glXSwapIntervalEXT(display, drawable, current_val); + + /* set it to no swap interval and see how it affects GLX_LATE_SWAPS_TEAR_EXT... */ + _this->gl_data->glXSwapIntervalEXT(display, drawable, 0); + _this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing); + + if (allow_late_swap_tearing == 0) { /* GLX_LATE_SWAPS_TEAR_EXT says whether late swapping is currently in use */ + _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_NVIDIA; + if (current_allow_late) { + original_val = -original_val; + } + } else if (allow_late_swap_tearing == 1) { /* GLX_LATE_SWAPS_TEAR_EXT says whether the Drawable can use late swapping at all */ + _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_MESA; + } else { /* unexpected outcome! */ + _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN; + } + + /* set us back to what it was originally... */ + _this->gl_data->glXSwapIntervalEXT(display, drawable, original_val); + } + } + + return _this->gl_data->swap_interval_tear_behavior; +} + + int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval) { if (_this->gl_data->glXSwapIntervalEXT) { @@ -935,6 +983,7 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval) unsigned int val = 0; if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) { + allow_late_swap_tearing = 22; /* set this to nonsense. */ _this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing); @@ -943,12 +992,21 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval) _this->gl_data->glXQueryDrawable(display, drawable, GLX_SWAP_INTERVAL_EXT, &val); - if ((allow_late_swap_tearing) && (val > 0)) { - *interval = -((int)val); - return 0; + *interval = (int)val; + + switch (CheckSwapIntervalTearBehavior(_this, drawable, val, allow_late_swap_tearing)) { + case SDL_SWAPINTERVALTEAR_MESA: + *interval = (int)val; /* unsigned int cast to signed that generates negative value if necessary. */ + break; + + case SDL_SWAPINTERVALTEAR_NVIDIA: + default: + if ((allow_late_swap_tearing) && (val > 0)) { + *interval = -((int)val); + } + break; } - *interval = (int)val; return 0; } else if (_this->gl_data->glXGetSwapIntervalMESA) { int val = _this->gl_data->glXGetSwapIntervalMESA(); diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index f49f556683a8b..70840231c7a7d 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -29,6 +29,14 @@ typedef void (*__GLXextFuncPtr)(void); +typedef enum SDL_GLSwapIntervalTearBehavior +{ + SDL_SWAPINTERVALTEAR_UNTESTED, + SDL_SWAPINTERVALTEAR_UNKNOWN, + SDL_SWAPINTERVALTEAR_MESA, + SDL_SWAPINTERVALTEAR_NVIDIA +} SDL_GLSwapIntervalTearBehavior; + struct SDL_GLDriverData { int errorBase, eventBase; @@ -50,6 +58,8 @@ struct SDL_GLDriverData int minor; } es_profile_max_supported_version; + SDL_GLSwapIntervalTearBehavior swap_interval_tear_behavior; + Bool (*glXQueryExtension)(Display *, int *, int *); __GLXextFuncPtr (*glXGetProcAddress)(const GLubyte *); XVisualInfo *(*glXChooseVisual)(Display *, int, int *); diff --git a/test/testgl.c b/test/testgl.c index 635782e9bc54b..0df67e73f9c14 100644 --- a/test/testgl.c +++ b/test/testgl.c @@ -199,6 +199,17 @@ static void Render(void) ctx.glRotatef(5.0, 1.0, 1.0, 1.0); } +static void LogSwapInterval(void) +{ + int interval = 0; + const int ret_interval = SDL_GL_GetSwapInterval(&interval); + if (ret_interval < 0) { + SDL_Log("Swap Interval : %d error: %s\n", interval, SDL_GetError()); + } else { + SDL_Log("Swap Interval : %d\n", interval); + } +} + int main(int argc, char *argv[]) { int fsaa, accel; @@ -211,8 +222,6 @@ int main(int argc, char *argv[]) int status; int dw, dh; int swap_interval = 0; - int interval = 0; - int ret_interval = 0; /* Initialize parameters */ fsaa = 0; @@ -304,12 +313,7 @@ int main(int argc, char *argv[]) SDL_Log("Screen BPP : %" SDL_PRIu32 "\n", SDL_BITSPERPIXEL(mode->format)); } - ret_interval = SDL_GL_GetSwapInterval(&interval); - if (ret_interval < 0) { - SDL_Log("Swap Interval : %d error: %s\n", interval, SDL_GetError()); - } else { - SDL_Log("Swap Interval : %d\n", interval); - } + LogSwapInterval(); SDL_GetWindowSize(state->windows[0], &dw, &dh); SDL_Log("Window Size : %d,%d\n", dw, dh); @@ -421,6 +425,7 @@ int main(int argc, char *argv[]) SDL_GL_MakeCurrent(state->windows[i], context); if (update_swap_interval) { SDL_GL_SetSwapInterval(swap_interval); + LogSwapInterval(); } SDL_GetWindowSizeInPixels(state->windows[i], &w, &h); ctx.glViewport(0, 0, w, h); From dcf04559dbd64d2763a8f514f671da7a2fc01da8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 23 Nov 2023 18:28:43 -0500 Subject: [PATCH 427/725] render: GL-based renderers should treat adaptive vsync as vsync being enabled. Fixes #8004. --- src/render/opengl/SDL_render_gl.c | 8 +++----- src/render/opengles2/SDL_render_gles2.c | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index d63eef782123d..c047c08c614a5 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1701,7 +1701,7 @@ static int GL_SetVSync(SDL_Renderer *renderer, const int vsync) return retval; } - if (interval > 0) { + if (interval != 0) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } else { renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC; @@ -1850,10 +1850,8 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea int interval = 0; if (SDL_GL_GetSwapInterval(&interval) < 0) { /* Error */ - } else { - if (interval > 0) { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } + } else if (interval != 0) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } } diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 9b7ca50c43eac..1eb17c6e17ad1 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1988,7 +1988,7 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync) return retval; } - if (interval > 0) { + if (interval != 0) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } else { renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC; @@ -2151,10 +2151,8 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c int interval = 0; if (SDL_GL_GetSwapInterval(&interval) < 0) { /* Error */ - } else { - if (interval > 0) { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } + } else if (interval != 0) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } } From b24d6bd59a86059383742b9b31ac955f8f4a49c4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 23 Nov 2023 20:00:01 -0500 Subject: [PATCH 428/725] opengl: Creating a texture trashes the cached `texturing` state, fix it. Reference Issue #7194. (cherry picked from commit e9b486937238680053bdf76b27693e120f00a70f) --- src/render/opengl/SDL_render_gl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index c047c08c614a5..04c5d51002680 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -450,6 +450,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr GL_ActivateRenderer(renderer); renderdata->drawstate.texture = NULL; /* we trash this state. */ + renderdata->drawstate.texturing = SDL_FALSE; /* we trash this state. */ if (texture->access == SDL_TEXTUREACCESS_TARGET && !renderdata->GL_EXT_framebuffer_object_supported) { From 6ba90f77752ab0350f28fb228c5dde550244904e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 20 Nov 2023 20:26:12 -0500 Subject: [PATCH 429/725] render: Batching is always enabled now! Make sure your app uses SDL_RenderFlush() before it talks to D3D/OpenGL/etc! Fixes #8584. --- docs/README-migration.md | 8 +++++ include/SDL3/SDL_hints.h | 24 --------------- include/SDL3/SDL_render.h | 20 ++++-------- src/render/SDL_render.c | 47 +++++++---------------------- src/render/SDL_sysrender.h | 2 -- src/render/metal/SDL_render_metal.m | 2 -- src/test/SDL_test_common.c | 1 - 7 files changed, 25 insertions(+), 79 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index ff1e8f9763ae0..92351965f6abb 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -559,6 +559,7 @@ The following hints have been removed: * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer * SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() +* SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API. * SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled @@ -811,6 +812,13 @@ The following functions have been renamed: ## SDL_render.h +The 2D renderer API always uses batching in SDL3. There is no magic to turn +it on and off; it doesn't matter if you select a specific renderer or try to +use any hint. This means that all apps that use SDL3's 2D renderer and also +want to call directly into the platform's lower-layer graphics API _must_ call +SDL_RenderFlush() before doing so. This will make sure any pending rendering +work from SDL is done before the app starts directly drawing. + SDL_GetRenderDriverInfo() has been removed, since most of the information it reported were estimates and could not be accurate before creating a renderer. Often times this function was used to figure out the index of a driver, so one would call it in a for-loop, looking diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index d2c2b0d8a73a9..184dac3fb1e74 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1387,30 +1387,6 @@ extern "C" { */ #define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS" -/** - * A variable controlling whether the 2D render API is compatible or efficient. - * - * This variable can be set to the following values: - * - * "0" - Don't use batching to make rendering more efficient. - * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls. - * - * Up to SDL 2.0.9, the render API would draw immediately when requested. Now - * it batches up draw requests and sends them all to the GPU only when forced - * to (during SDL_RenderPresent, when changing render targets, by updating a - * texture that the batch needs, etc). This is significantly more efficient, - * but it can cause problems for apps that expect to render on top of the - * render API's output. As such, SDL will disable batching if a specific - * render backend is requested (since this might indicate that the app is - * planning to use the underlying graphics API directly). This hint can - * be used to explicitly request batching in this instance. It is a contract - * that you will either never use the underlying graphics API directly, or - * if you do, you will call SDL_RenderFlush() before you do so any current - * batch goes to the GPU before your work begins. Not following this contract - * will result in undefined behavior. - */ -#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" - /** * A variable controlling how the 2D render API renders lines * diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index b7313d9d09d2e..caff6f87a672f 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1559,20 +1559,12 @@ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); * are planning to call into OpenGL/Direct3D/Metal/whatever directly in * addition to using an SDL_Renderer. * - * This is for a very-specific case: if you are using SDL's render API, you - * asked for a specific renderer backend (OpenGL, Direct3D, etc), you set - * SDL_HINT_RENDER_BATCHING to "1", and you plan to make OpenGL/D3D/whatever - * calls in addition to SDL render API calls. If all of this applies, you - * should call SDL_RenderFlush() between calls to SDL's render API and the - * low-level API you're using in cooperation. - * - * In all other cases, you can ignore this function. This is only here to get - * maximum performance out of a specific situation. In all other cases, SDL - * will do the right thing, perhaps at a performance loss. - * - * This function is first available in SDL 2.0.10, and is not needed in 2.0.9 - * and earlier, as earlier versions did not queue rendering commands at all, - * instead flushing them to the OS immediately. + * This is for a very-specific case: if you are using SDL's render API, and + * you plan to make OpenGL/D3D/whatever calls in addition to SDL render API + * calls. If this applies, you should call SDL_RenderFlush() between calls to + * SDL's render API and the low-level API you're using in cooperation. + * + * In all other cases, you can ignore this function. * * \param renderer the rendering context * \returns 0 on success or a negative error code on failure; call diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index aedde6af332c8..533a2fe524c5d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -265,11 +265,6 @@ static int FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture) return 0; } -static SDL_INLINE int FlushRenderCommandsIfNotBatching(SDL_Renderer *renderer) -{ - return renderer->batching ? 0 : FlushRenderCommands(renderer); -} - int SDL_RenderFlush(SDL_Renderer *renderer) { return FlushRenderCommands(renderer); @@ -813,7 +808,6 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) const char *name = SDL_GetStringProperty(props, "name", NULL); SDL_Renderer *renderer = NULL; const int n = SDL_GetNumRenderDrivers(); - SDL_bool batching = SDL_TRUE; const char *hint; int i; @@ -855,9 +849,6 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) if (SDL_strcasecmp(name, driver->info.name) == 0) { /* Create a new renderer instance */ renderer = driver->CreateRenderer(window, props); - if (renderer) { - batching = SDL_FALSE; - } break; } } @@ -890,14 +881,6 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) VerifyDrawQueueFunctions(renderer); - /* let app/user override batching decisions. */ - if (renderer->always_batch) { - batching = SDL_TRUE; - } else if (SDL_GetHint(SDL_HINT_RENDER_BATCHING)) { - batching = SDL_GetHintBoolean(SDL_HINT_RENDER_BATCHING, SDL_TRUE); - } - - renderer->batching = batching; renderer->magic = &SDL_renderer_magic; renderer->window = window; renderer->target_mutex = SDL_CreateMutex(); @@ -2106,7 +2089,7 @@ static int SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *text } /* All set! */ - return FlushRenderCommandsIfNotBatching(renderer); + return 0; } int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) @@ -2506,7 +2489,6 @@ int SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) { - int retval; CHECK_RENDERER_MAGIC(renderer, -1); if (rect) { @@ -2520,8 +2502,7 @@ int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) renderer->view->viewport.w = -1; renderer->view->viewport.h = -1; } - retval = QueueCmdSetViewport(renderer); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return QueueCmdSetViewport(renderer); } int SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) @@ -2563,7 +2544,6 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect) int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) { - int retval; CHECK_RENDERER_MAGIC(renderer, -1) if (rect && rect->w >= 0 && rect->h >= 0) { @@ -2577,8 +2557,7 @@ int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) SDL_zero(renderer->view->clip_rect); } - retval = QueueCmdSetClipRect(renderer); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return QueueCmdSetClipRect(renderer); } int SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect) @@ -2617,7 +2596,7 @@ int SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY) /* The scale affects the existing viewport and clip rectangle */ retval += QueueCmdSetViewport(renderer); retval += QueueCmdSetClipRect(renderer); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY) @@ -2687,7 +2666,7 @@ int SDL_RenderClear(SDL_Renderer *renderer) int retval; CHECK_RENDERER_MAGIC(renderer, -1); retval = QueueCmdClear(renderer); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderPoint(SDL_Renderer *renderer, float x, float y) @@ -2753,7 +2732,7 @@ int SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count } else { retval = QueueCmdDrawPoints(renderer, points, count); } - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderLine(SDL_Renderer *renderer, float x1, float y1, float x2, float y2) @@ -3072,7 +3051,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) retval = QueueCmdDrawLines(renderer, points, count); } - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect) @@ -3181,7 +3160,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun SDL_small_free(frects, isstack); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect) @@ -3286,7 +3265,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect); } - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, @@ -3441,7 +3420,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, renderer->view->scale.x, renderer->view->scale.y); } - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderGeometry(SDL_Renderer *renderer, @@ -3798,8 +3777,6 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, renderer->view->scale.y); if (retval < 0) { goto end; - } else { - FlushRenderCommandsIfNotBatching(renderer); } } @@ -3821,8 +3798,6 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, renderer->view->scale.y); if (retval < 0) { goto end; - } else { - FlushRenderCommandsIfNotBatching(renderer); } } @@ -3944,7 +3919,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, renderer->view->scale.x, renderer->view->scale.y); - return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); + return retval; } int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch) diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 187073de13097..54d2d151484ec 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -254,8 +254,6 @@ struct SDL_Renderer SDL_Color color; /**< Color for drawing operations values */ SDL_BlendMode blendMode; /**< The drawing blend mode */ - SDL_bool always_batch; - SDL_bool batching; SDL_RenderCommand *render_commands; SDL_RenderCommand *render_commands_tail; SDL_RenderCommand *render_commands_pool; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 285d42018ec12..dc2b6124b6094 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1917,8 +1917,6 @@ in case we want to use it later (recreating the renderer) renderer->info = METAL_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; - renderer->always_batch = SDL_TRUE; - #if (defined(__MACOS__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST if (@available(macOS 10.13, *)) { data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE); diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 45928628df90d..80a7865889f8d 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -228,7 +228,6 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index) } state->renderdriver = argv[index]; SDL_SetHint(SDL_HINT_RENDER_DRIVER, state->renderdriver); - SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1"); return 2; } if (SDL_strcasecmp(argv[index], "--gldebug") == 0) { From dd5b8db3a626c2f43419796419fa0d20436e54bb Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 24 Nov 2023 21:31:35 +0100 Subject: [PATCH 430/725] SDL_hidapi requires libusb >= 1.0.16 Co-authored-by: Ozkan Sezer --- .github/workflows/cpactions.yml | 1 - cmake/sdlchecks.cmake | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cpactions.yml b/.github/workflows/cpactions.yml index b4ebb38d99d72..4a11b81686ad5 100644 --- a/.github/workflows/cpactions.yml +++ b/.github/workflows/cpactions.yml @@ -51,7 +51,6 @@ jobs: cmake -S . -B build -GNinja \ -Wdeprecated -Wdev -Werror \ -DCMAKE_BUILD_TYPE=Release \ - -DSDL_HIDAPI_LIBUSB=OFF \ -DSDL_CHECK_REQUIRED_INCLUDES="/usr/local/include" \ -DSDL_CHECK_REQUIRED_LINK_OPTIONS="-L/usr/local/lib" cmake --build build/ --config Release --verbose -- -j`sysctl -n hw.ncpu` diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index f4723b312d08a..6a0be91b21f65 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -1021,7 +1021,7 @@ macro(CheckHIDAPI) if(SDL_HIDAPI_LIBUSB) set(HAVE_LIBUSB FALSE) - set(LibUSB_PKG_CONFIG_SPEC libusb-1.0) + set(LibUSB_PKG_CONFIG_SPEC libusb-1.0>=1.0.16) pkg_check_modules(PC_LIBUSB IMPORTED_TARGET ${LibUSB_PKG_CONFIG_SPEC}) if(PC_LIBUSB_FOUND) cmake_push_check_state() From e548044a82c8ae6ffd2605ceef285598adbe6bd0 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sat, 11 Nov 2023 21:52:07 +0100 Subject: [PATCH 431/725] ci: add NetBSD to test matrix Co-authored-by: Ozkan Sezer --- .github/workflows/cpactions.yml | 64 ++++++++++++++------------------- CMakeLists.txt | 2 +- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/.github/workflows/cpactions.yml b/.github/workflows/cpactions.yml index 4a11b81686ad5..7591c0dc2a667 100644 --- a/.github/workflows/cpactions.yml +++ b/.github/workflows/cpactions.yml @@ -9,53 +9,41 @@ concurrency: jobs: freebsd: runs-on: ubuntu-latest - name: FreeBSD + name: '${{ matrix.platform.name }} ${{ matrix.platform.os-version }}' timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + platform: + - { name: FreeBSD, os: freebsd, os-version: 13.2, os-arch: x86-64, artifact: SDL-freebsd-x64, + sdl-cmake-configure-arguments: '-DSDL_CHECK_REQUIRED_INCLUDES="/usr/local/include" -DSDL_CHECK_REQUIRED_LINK_OPTIONS="-L/usr/local/lib"', + setup-cmd: 'sudo pkg update', + install-cmd: 'sudo pkg install -y cmake ninja pkgconf libXcursor libXext libXinerama libXi libXfixes libXrandr libXScrnSaver libXxf86vm wayland wayland-protocols libxkbcommon mesa-libs libglvnd evdev-proto libinotify alsa-lib jackit pipewire pulseaudio sndio dbus zh-fcitx ibus libudev-devd', + } + - { name: NetBSD, os: netbsd, os-version: 9.3, os-arch: x86-64, artifact: SDL-netbsd-x64, + sdl-cmake-configure-arguments: '', + setup-cmd: 'export PATH="/usr/pkg/sbin:/usr/pkg/bin:/sbin:$PATH";export PKG_CONFIG_PATH="/usr/pkg/lib/pkgconfig";export PKG_PATH="https://cdn.netBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f "1 2" -d.)/All/";echo "PKG_PATH=$PKG_PATH";echo "uname -a -> \"$(uname -a)\"";sudo -E sysctl -w security.pax.aslr.enabled=0;sudo -E sysctl -w security.pax.aslr.global=0;sudo -E pkgin clean;sudo -E pkgin update', + install-cmd: 'sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1', + } steps: - uses: actions/checkout@v3 - name: Build - uses: cross-platform-actions/action@v0.19.1 + uses: cross-platform-actions/action@v0.21.1 with: - operating_system: freebsd - version: '13.2' + operating_system: ${{ matrix.platform.os }} + architecture: ${{ matrix.platform.os-arch }} + version: ${{ matrix.platform.os-version }} run: | - sudo pkg update - sudo pkg install -y \ - cmake \ - ninja \ - pkgconf \ - libXcursor \ - libXext \ - libXinerama \ - libXi \ - libXfixes \ - libXrandr \ - libXScrnSaver \ - libXxf86vm \ - wayland \ - wayland-protocols \ - libxkbcommon \ - mesa-libs \ - libglvnd \ - evdev-proto \ - libinotify \ - alsa-lib \ - jackit \ - pipewire \ - pulseaudio \ - sndio \ - dbus \ - zh-fcitx \ - ibus \ - libudev-devd + ${{ matrix.platform.setup-cmd }} + ${{ matrix.platform.install-cmd }} cmake -S . -B build -GNinja \ -Wdeprecated -Wdev -Werror \ -DCMAKE_BUILD_TYPE=Release \ - -DSDL_CHECK_REQUIRED_INCLUDES="/usr/local/include" \ - -DSDL_CHECK_REQUIRED_LINK_OPTIONS="-L/usr/local/lib" - cmake --build build/ --config Release --verbose -- -j`sysctl -n hw.ncpu` + -DSDL_WERROR=ON \ + ${{ matrix.platform.sdl-cmake-configure-arguments }} + cmake --build build/ --config Release --verbose cmake --build build/ --config Release --target package - + cmake --build build/ --config Release --target clean rm -rf build/dist/_CPack_Packages rm -rf build/CMakeFiles @@ -64,5 +52,5 @@ jobs: - uses: actions/upload-artifact@v3 with: if-no-files-found: error - name: SDL-freebsd + name: ${{ matrix.platform.artifact }} path: build/dist/SDL3* diff --git a/CMakeLists.txt b/CMakeLists.txt index ba5451015020c..52e3f900591c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1590,7 +1590,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) set(SDL_USE_IME 1) endif() - if(FREEBSD AND NOT HAVE_INOTIFY) + if((FREEBSD OR NETBSD) AND NOT HAVE_INOTIFY) set(LibInotify_PKG_CONFIG_SPEC libinotify) pkg_check_modules(PC_LIBINOTIFY IMPORTED_TARGET ${LibInotify_PKG_CONFIG_SPEC}) if(PC_LIBINOTIFY_FOUND) From db7f6425d05092b1ca1e5c3f0be63d7974150faa Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 24 Nov 2023 19:29:39 -0500 Subject: [PATCH 432/725] rect: Avoid numeric overflow on massive lines in SDL_IntersectRectAndLine. Reference Issue #8301. Reference Issue #8113. (cherry picked from commit a391dd5fef70e0da4702d355b6331da5bf1f84a2) --- src/video/SDL_rect.c | 2 ++ src/video/SDL_rect_impl.h | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/video/SDL_rect.c b/src/video/SDL_rect.c index d37361149b258..b91723636d080 100644 --- a/src/video/SDL_rect.c +++ b/src/video/SDL_rect.c @@ -88,6 +88,7 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height, #define RECTTYPE SDL_Rect #define POINTTYPE SDL_Point #define SCALARTYPE int +#define BIGSCALARTYPE Sint64 #define COMPUTEOUTCODE ComputeOutCode #define SDL_HASINTERSECTION SDL_HasRectIntersection #define SDL_INTERSECTRECT SDL_GetRectIntersection @@ -100,6 +101,7 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height, #define RECTTYPE SDL_FRect #define POINTTYPE SDL_FPoint #define SCALARTYPE float +#define BIGSCALARTYPE double #define COMPUTEOUTCODE ComputeOutCodeFloat #define SDL_HASINTERSECTION SDL_HasRectIntersectionFloat #define SDL_INTERSECTRECT SDL_GetRectIntersectionFloat diff --git a/src/video/SDL_rect_impl.h b/src/video/SDL_rect_impl.h index 15591a5ac4143..0b623808a29a9 100644 --- a/src/video/SDL_rect_impl.h +++ b/src/video/SDL_rect_impl.h @@ -376,16 +376,16 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY if (outcode1) { if (outcode1 & CODE_TOP) { y = recty1; - x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); + x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1)); } else if (outcode1 & CODE_BOTTOM) { y = recty2; - x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); + x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1)); } else if (outcode1 & CODE_LEFT) { x = rectx1; - y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); + y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1)); } else if (outcode1 & CODE_RIGHT) { x = rectx2; - y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); + y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1)); } x1 = x; y1 = y; @@ -394,23 +394,23 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY if (outcode2 & CODE_TOP) { SDL_assert(y2 != y1); /* if equal: division by zero. */ y = recty1; - x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); + x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1)); } else if (outcode2 & CODE_BOTTOM) { SDL_assert(y2 != y1); /* if equal: division by zero. */ y = recty2; - x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1); + x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1)); } else if (outcode2 & CODE_LEFT) { /* If this assertion ever fires, here's the static analysis that warned about it: http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-b0d01a.html#EndPath */ SDL_assert(x2 != x1); /* if equal: division by zero. */ x = rectx1; - y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); + y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1)); } else if (outcode2 & CODE_RIGHT) { /* If this assertion ever fires, here's the static analysis that warned about it: http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-39b114.html#EndPath */ SDL_assert(x2 != x1); /* if equal: division by zero. */ x = rectx2; - y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1); + y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1)); } x2 = x; y2 = y; @@ -427,6 +427,7 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY #undef RECTTYPE #undef POINTTYPE #undef SCALARTYPE +#undef BIGSCALARTYPE #undef COMPUTEOUTCODE #undef SDL_HASINTERSECTION #undef SDL_INTERSECTRECT From 983f178b7d3ebf002ef3ec3cdf73f93766bfccd0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 24 Nov 2023 19:31:30 -0500 Subject: [PATCH 433/725] render: Clip lines before Bresenham algorithm generates points. Otherwise, a massive line might generate gigabytes worth of points to render, which the backend would simply throw away anyhow. Fixes #8113. (cherry picked from commit 4339647d900bb8559ac3f6258166d21fe6d72a9a) --- src/render/SDL_render.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 533a2fe524c5d..e7006fb407b1e 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -2755,6 +2755,18 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i int retval; SDL_bool isstack; SDL_FPoint *points; + SDL_Rect clip_rect; + + /* the backend might clip this further to the clipping rect, but we + just want a basic safety against generating millions of points for + massive lines. */ + clip_rect.x = (int) renderer->viewport.x; + clip_rect.y = (int) renderer->viewport.y; + clip_rect.w = (int) renderer->viewport.w; + clip_rect.h = (int) renderer->viewport.h; + if (!SDL_IntersectRectAndLine(&clip_rect, &x1, &y1, &x2, &y2)) { + return 0; + } deltax = SDL_abs(x2 - x1); deltay = SDL_abs(y2 - y1); From 4a40a272bd317f99869f3f9c95d845457d3107f8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 24 Nov 2023 22:47:44 -0500 Subject: [PATCH 434/725] render: Patched to compile. Bad cherry-pick on my part, sorry! Fixes #8609. --- src/render/SDL_render.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index e7006fb407b1e..847e14d680971 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -2755,16 +2755,11 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i int retval; SDL_bool isstack; SDL_FPoint *points; - SDL_Rect clip_rect; /* the backend might clip this further to the clipping rect, but we just want a basic safety against generating millions of points for massive lines. */ - clip_rect.x = (int) renderer->viewport.x; - clip_rect.y = (int) renderer->viewport.y; - clip_rect.w = (int) renderer->viewport.w; - clip_rect.h = (int) renderer->viewport.h; - if (!SDL_IntersectRectAndLine(&clip_rect, &x1, &y1, &x2, &y2)) { + if (!SDL_GetRectAndLineIntersection(&renderer->view->viewport, &x1, &y1, &x2, &y2)) { return 0; } From 42a8139fd662cefd32f851af95cc44f546c5834a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 25 Nov 2023 01:51:35 -0500 Subject: [PATCH 435/725] render: Clip bresenham lines against a real viewport thing. You can't just use renderer->view->viewport, because it might be (0,0), -1x-1. I _think_ this is more right? Fixes #8609. --- src/render/SDL_render.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 847e14d680971..a9cd2105ad26f 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -2755,11 +2755,13 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i int retval; SDL_bool isstack; SDL_FPoint *points; + SDL_Rect viewport; /* the backend might clip this further to the clipping rect, but we just want a basic safety against generating millions of points for massive lines. */ - if (!SDL_GetRectAndLineIntersection(&renderer->view->viewport, &x1, &y1, &x2, &y2)) { + GetRenderViewportInPixels(renderer, &viewport); + if (!SDL_GetRectAndLineIntersection(&viewport, &x1, &y1, &x2, &y2)) { return 0; } From d486de634917b80c53362d0f62a9d1f762c8f4fb Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Sun, 26 Nov 2023 01:55:28 +0300 Subject: [PATCH 436/725] cmake: fixed iconv detection test program Fixes https://github.com/libsdl-org/SDL/issues/8614 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52e3f900591c9..91b660e52c046 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1105,7 +1105,7 @@ if(SDL_LIBC) #include #include int main(int argc, char **argv) { - return iconv_open(NULL,NULL); + return !iconv_open(NULL,NULL); }" ICONV_IN_LIBC) cmake_push_check_state() @@ -1114,7 +1114,7 @@ if(SDL_LIBC) #include #include int main(int argc, char **argv) { - return iconv_open(NULL,NULL); + return !iconv_open(NULL,NULL); }" ICONV_IN_LIBICONV) cmake_pop_check_state() From c4ca64deaf556ad298cdd4f226ba838dec7ffb0b Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 26 Nov 2023 02:02:10 +0100 Subject: [PATCH 437/725] ci: do 'brew update' & don't run dependent checks on installed things --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 46d2b1e87e76b..9cfb6a845b0b6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,6 +66,8 @@ jobs: - name: Setup Macos dependencies if: runner.os == 'macOS' run: | + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + brew update brew install \ ninja \ pkg-config \ From 1b284cd4153d967f17cad9535cf00c153dd62570 Mon Sep 17 00:00:00 2001 From: Christoph Reichenbach Date: Sun, 26 Nov 2023 08:47:32 +0000 Subject: [PATCH 438/725] X11 pen detection: fix misclassification due to improper init xinput2_device_is_pen() was testing against default-zero values in the X11 Atom cache on at least the first round of detections, leading to imprecise detection. The patch fixes two aspects of initialisation: 1. Ensure that the selector cache is always initialised in xinput2_device_is_pen(). 2. Ensure that all X11 Atoms used in SDL_x11pen.c are instantiated if missing. This ensures that they are never None and avoids potential failures to detect hot-plugged tablet devices. Acknowledgements: @tilman3 for narrowing down the issue and an initial fix --- src/video/x11/SDL_x11pen.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/video/x11/SDL_x11pen.c b/src/video/x11/SDL_x11pen.c index 94b4a5c1b94c8..6d0dbca4ec075 100644 --- a/src/video/x11/SDL_x11pen.c +++ b/src/video/x11/SDL_x11pen.c @@ -114,9 +114,9 @@ static void pen_atoms_ensure_initialized(SDL_VideoDevice *_this) pen_atoms.device_product_id = X11_XInternAtom(data->display, "Device Product ID", False); pen_atoms.wacom_serial_ids = X11_XInternAtom(data->display, "Wacom Serial IDs", False); pen_atoms.wacom_tool_type = X11_XInternAtom(data->display, "Wacom Tool Type", False); - pen_atoms.abs_pressure = X11_XInternAtom(data->display, "Abs Pressure", True); - pen_atoms.abs_tilt_x = X11_XInternAtom(data->display, "Abs Tilt X", True); - pen_atoms.abs_tilt_y = X11_XInternAtom(data->display, "Abs Tilt Y", True); + pen_atoms.abs_pressure = X11_XInternAtom(data->display, "Abs Pressure", False); + pen_atoms.abs_tilt_x = X11_XInternAtom(data->display, "Abs Tilt X", False); + pen_atoms.abs_tilt_y = X11_XInternAtom(data->display, "Abs Tilt Y", False); pen_atoms.initialized = 1; } @@ -390,9 +390,12 @@ static void xinput2_vendor_peninfo(SDL_VideoDevice *_this, const XIDeviceInfo *d } /* Does this device have a valuator for pressure sensitivity? */ -static SDL_bool xinput2_device_is_pen(const XIDeviceInfo *dev) +static SDL_bool xinput2_device_is_pen(SDL_VideoDevice *_this, const XIDeviceInfo *dev) { int classct; + + pen_atoms_ensure_initialized(_this); + for (classct = 0; classct < dev->num_classes; ++classct) { const XIAnyClassInfo *classinfo = dev->classes[classct]; @@ -445,8 +448,8 @@ void X11_InitPen(SDL_VideoDevice *_this) int old_num_pens_known = pen_map.num_pens_known; int k; - /* Only track physical devices that are enabled */ - if (dev->use != XISlavePointer || dev->enabled == 0 || !xinput2_device_is_pen(dev)) { + /* Only track physical devices that are enabled and look like pens */ + if (dev->use != XISlavePointer || dev->enabled == 0 || !xinput2_device_is_pen(_this, dev)) { continue; } From 2f806c89b5e61237a3778b7f3bbf2755416f6e6b Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Sun, 26 Nov 2023 08:55:02 +0300 Subject: [PATCH 439/725] initial import of hidapi netbsd uhid native backend from mainstream https://github.com/libusb/hidapi/commit/c19ae126d8856b55af34d64ee11641920475961c https://github.com/libusb/hidapi/pull/612 --- src/hidapi/CMakeLists.txt | 3 + src/hidapi/SDL_hidapi.c | 2 + src/hidapi/SDL_hidapi_netbsd.h | 25 + src/hidapi/netbsd/CMakeLists.txt | 35 + src/hidapi/netbsd/README.md | 29 + src/hidapi/netbsd/hid.c | 1173 +++++++++++++++++++++++++++++ src/hidapi/pc/hidapi-netbsd.pc.in | 11 + src/hidapi/src/CMakeLists.txt | 12 + 8 files changed, 1290 insertions(+) create mode 100644 src/hidapi/SDL_hidapi_netbsd.h create mode 100644 src/hidapi/netbsd/CMakeLists.txt create mode 100644 src/hidapi/netbsd/README.md create mode 100644 src/hidapi/netbsd/hid.c create mode 100644 src/hidapi/pc/hidapi-netbsd.pc.in diff --git a/src/hidapi/CMakeLists.txt b/src/hidapi/CMakeLists.txt index e18ee23be848b..b4c99be51cc52 100644 --- a/src/hidapi/CMakeLists.txt +++ b/src/hidapi/CMakeLists.txt @@ -42,6 +42,9 @@ elseif(NOT WIN32) option(HIDAPI_WITH_HIDRAW "Build HIDRAW-based implementation of HIDAPI" ON) option(HIDAPI_WITH_LIBUSB "Build LIBUSB-based implementation of HIDAPI" ON) endif() + if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + option(HIDAPI_WITH_NETBSD "Build NetBSD/UHID implementation of HIDAPI" ON) + endif() endif() option(BUILD_SHARED_LIBS "Build shared version of the libraries, otherwise build statically" ON) diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index b31683b36e917..9d168ade4c9b8 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -573,6 +573,8 @@ typedef struct PLATFORM_hid_device_ PLATFORM_hid_device; #ifdef __LINUX__ #include "SDL_hidapi_linux.h" +#elif defined(__NETBSD__) +#include "SDL_hidapi_netbsd.h" #elif defined(__MACOS__) #include "SDL_hidapi_mac.h" #elif defined(__WINDOWS__) || defined(__WINGDK__) diff --git a/src/hidapi/SDL_hidapi_netbsd.h b/src/hidapi/SDL_hidapi_netbsd.h new file mode 100644 index 0000000000000..3ca6803b2b691 --- /dev/null +++ b/src/hidapi/SDL_hidapi_netbsd.h @@ -0,0 +1,25 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#undef HIDAPI_H__ +#include "netbsd/hid.c" +#define HAVE_PLATFORM_BACKEND 1 +#define udev_ctx 1 diff --git a/src/hidapi/netbsd/CMakeLists.txt b/src/hidapi/netbsd/CMakeLists.txt new file mode 100644 index 0000000000000..86067f895fd87 --- /dev/null +++ b/src/hidapi/netbsd/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) + +add_library(hidapi_netbsd + ${HIDAPI_PUBLIC_HEADERS} + hid.c +) +target_link_libraries(hidapi_netbsd PUBLIC hidapi_include) + +find_package(Threads REQUIRED) + +target_link_libraries(hidapi_netbsd PRIVATE Threads::Threads) + +set_target_properties(hidapi_netbsd + PROPERTIES + EXPORT_NAME "netbsd" + OUTPUT_NAME "hidapi-netbsd" + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}" +) + +# compatibility with find_package() +add_library(hidapi::netbsd ALIAS hidapi_netbsd) +# compatibility with raw library link +add_library(hidapi-netbsd ALIAS hidapi_netbsd) + +if(HIDAPI_INSTALL_TARGETS) + install(TARGETS hidapi_netbsd EXPORT hidapi + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/hidapi" + ) +endif() + +hidapi_configure_pc("${PROJECT_ROOT}/pc/hidapi-netbsd.pc.in") diff --git a/src/hidapi/netbsd/README.md b/src/hidapi/netbsd/README.md new file mode 100644 index 0000000000000..f1b12a0aeae02 --- /dev/null +++ b/src/hidapi/netbsd/README.md @@ -0,0 +1,29 @@ +Implementation Notes +-------------------- +NetBSD maps every `uhidev` device to one or more `uhid` +devices. Each `uhid` device only supports one report ID. +The parent device `uhidev` creates one `uhid` device per +report ID found in the hardware's report descriptor. + +In the event there are no report ID(s) found within the +report descriptor, only one `uhid` device with a report ID +of `0` is created. + +In order to remain compatible with existing `hidapi` APIs, +all the `uhid` devices created by the parent `uhidev` device +must be opened under the same `hid_device` instance to ensure +that we can route reports to their appropriate `uhid` device. + +Internally the `uhid` driver will insert the report ID as +needed so we must also omit the report ID in any situation +where the `hidapi` API expects it to be included in the +report data stream. + +Given the design of `uhid`, it must be augmented with extra +platform specific APIs to ensure that the exact relationship +between `uhidev` devices and `uhid` devices can be determined. + +The NetBSD implementation does this via the `drvctl` kernel +driver. At present there is no known way to do this on OpenBSD +for a `uhid` implementation to be at the same level as the +NetBSD one. diff --git a/src/hidapi/netbsd/hid.c b/src/hidapi/netbsd/hid.c new file mode 100644 index 0000000000000..4c4d0a1a86c51 --- /dev/null +++ b/src/hidapi/netbsd/hid.c @@ -0,0 +1,1173 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + James Buren + libusb/hidapi Team + + Copyright 2023, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + https://github.com/libusb/hidapi . +********************************************************/ + +/* C */ +#include +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include + +/* NetBSD */ +#include +#include +#include + +#include "../hidapi/hidapi.h" + +#define HIDAPI_MAX_CHILD_DEVICES 256 + +struct hid_device_ { + int device_handle; + int blocking; + wchar_t *last_error_str; + struct hid_device_info *device_info; + size_t poll_handles_length; + struct pollfd poll_handles[256]; + int report_handles[256]; + char path[USB_MAX_DEVNAMELEN]; +}; + +struct hid_enumerate_data { + struct hid_device_info *root; + struct hid_device_info *end; + int drvctl; + uint16_t vendor_id; + uint16_t product_id; +}; + +typedef void (*enumerate_devices_callback) (const struct usb_device_info *, void *); + +static wchar_t *last_global_error_str = NULL; + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); + if (ret == NULL) { + /* as much as we can do at this point */ + return NULL; + } + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + +/* Makes a copy of the given error message (and decoded according to the + * currently locale) into the wide string pointer pointed by error_str. + * The last stored error string is freed. + * Use register_error_str(NULL) to free the error message completely. */ +static void register_error_str(wchar_t **error_str, const char *msg) +{ + free(*error_str); + *error_str = utf8_to_wchar_t(msg); +} + +/* Semilar to register_error_str, but allows passing a format string with va_list args into this function. */ +static void register_error_str_vformat(wchar_t **error_str, const char *format, va_list args) +{ + char msg[256]; + vsnprintf(msg, sizeof(msg), format, args); + + register_error_str(error_str, msg); +} + +/* Set the last global error to be reported by hid_error(NULL). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored global error message is freed. + * Use register_global_error(NULL) to indicate "no error". */ +static void register_global_error(const char *msg) +{ + register_error_str(&last_global_error_str, msg); +} + +/* Similar to register_global_error, but allows passing a format string into this function. */ +static void register_global_error_format(const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&last_global_error_str, format, args); + va_end(args); +} + +/* Set the last error for a device to be reported by hid_error(dev). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored device error message is freed. + * Use register_device_error(dev, NULL) to indicate "no error". */ +static void register_device_error(hid_device *dev, const char *msg) +{ + register_error_str(&dev->last_error_str, msg); +} + +/* Similar to register_device_error, but you can pass a format string into this function. */ +static void register_device_error_format(hid_device *dev, const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&dev->last_error_str, format, args); + va_end(args); +} + + +/* + * Gets the size of the HID item at the given position + * Returns 1 if successful, 0 if an invalid key + * Sets data_len and key_size when successful + */ +static int get_hid_item_size(const uint8_t *report_descriptor, uint32_t size, unsigned int pos, int *data_len, int *key_size) +{ + int key = report_descriptor[pos]; + int size_code; + + /* + * This is a Long Item. The next byte contains the + * length of the data section (value) for this key. + * See the HID specification, version 1.11, section + * 6.2.2.3, titled "Long Items." + */ + if ((key & 0xf0) == 0xf0) { + if (pos + 1 < size) + { + *data_len = report_descriptor[pos + 1]; + *key_size = 3; + return 1; + } + *data_len = 0; /* malformed report */ + *key_size = 0; + } + + /* + * This is a Short Item. The bottom two bits of the + * key contain the size code for the data section + * (value) for this key. Refer to the HID + * specification, version 1.11, section 6.2.2.2, + * titled "Short Items." + */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + *data_len = size_code; + *key_size = 1; + return 1; + case 3: + *data_len = 4; + *key_size = 1; + return 1; + default: + /* Can't ever happen since size_code is & 0x3 */ + *data_len = 0; + *key_size = 0; + break; + }; + + /* malformed report */ + return 0; +} + +/* + * Get bytes from a HID Report Descriptor. + * Only call with a num_bytes of 0, 1, 2, or 4. + */ +static uint32_t get_hid_report_bytes(const uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) +{ + /* Return if there aren't enough bytes. */ + if (cur + num_bytes >= len) + return 0; + + if (num_bytes == 0) + return 0; + else if (num_bytes == 1) + return rpt[cur + 1]; + else if (num_bytes == 2) + return (rpt[cur + 2] * 256 + rpt[cur + 1]); + else if (num_bytes == 4) + return ( + rpt[cur + 4] * 0x01000000 + + rpt[cur + 3] * 0x00010000 + + rpt[cur + 2] * 0x00000100 + + rpt[cur + 1] * 0x00000001 + ); + else + return 0; +} + +/* + * Iterates until the end of a Collection. + * Assumes that *pos is exactly at the beginning of a Collection. + * Skips all nested Collection, i.e. iterates until the end of current level Collection. + * + * The return value is non-0 when an end of current Collection is found, + * 0 when error is occured (broken Descriptor, end of a Collection is found before its begin, + * or no Collection is found at all). + */ +static int hid_iterate_over_collection(const uint8_t *report_descriptor, uint32_t size, unsigned int *pos, int *data_len, int *key_size) +{ + int collection_level = 0; + + while (*pos < size) { + int key = report_descriptor[*pos]; + int key_cmd = key & 0xfc; + + /* Determine data_len and key_size */ + if (!get_hid_item_size(report_descriptor, size, *pos, data_len, key_size)) + return 0; /* malformed report */ + + switch (key_cmd) { + case 0xa0: /* Collection 6.2.2.4 (Main) */ + collection_level++; + break; + case 0xc0: /* End Collection 6.2.2.4 (Main) */ + collection_level--; + break; + } + + if (collection_level < 0) { + /* Broken descriptor or someone is using this function wrong, + * i.e. should be called exactly at the collection start */ + return 0; + } + + if (collection_level == 0) { + /* Found it! + * Also possible when called not at the collection start, but should not happen if used correctly */ + return 1; + } + + *pos += *data_len + *key_size; + } + + return 0; /* Did not find the end of a Collection */ +} + +struct hid_usage_iterator { + unsigned int pos; + int usage_page_found; + unsigned short usage_page; +}; + +/* + * Retrieves the device's Usage Page and Usage from the report descriptor. + * The algorithm returns the current Usage Page/Usage pair whenever a new + * Collection is found and a Usage Local Item is currently in scope. + * Usage Local Items are consumed by each Main Item (See. 6.2.2.8). + * The algorithm should give similar results as Apple's: + * https://developer.apple.com/documentation/iokit/kiohiddeviceusagepairskey?language=objc + * Physical Collections are also matched (macOS does the same). + * + * This function can be called repeatedly until it returns non-0 + * Usage is found. pos is the starting point (initially 0) and will be updated + * to the next search position. + * + * The return value is 0 when a pair is found. + * 1 when finished processing descriptor. + * -1 on a malformed report. + */ +static int get_next_hid_usage(const uint8_t *report_descriptor, uint32_t size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage) +{ + int data_len, key_size; + int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */ + + int usage_found = 0; + + while (ctx->pos < size) { + int key = report_descriptor[ctx->pos]; + int key_cmd = key & 0xfc; + + /* Determine data_len and key_size */ + if (!get_hid_item_size(report_descriptor, size, ctx->pos, &data_len, &key_size)) + return -1; /* malformed report */ + + switch (key_cmd) { + case 0x4: /* Usage Page 6.2.2.7 (Global) */ + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + ctx->usage_page_found = 1; + break; + + case 0x8: /* Usage 6.2.2.8 (Local) */ + if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2); + ctx->usage_page_found = 1; + *usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos); + usage_found = 1; + } + else { + *usage = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + usage_found = 1; + } + break; + + case 0xa0: /* Collection 6.2.2.4 (Main) */ + if (!hid_iterate_over_collection(report_descriptor, size, &ctx->pos, &data_len, &key_size)) { + return -1; + } + + /* A pair is valid - to be reported when Collection is found */ + if (usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; + } + + break; + } + + /* Skip over this key and its associated data */ + ctx->pos += data_len + key_size; + } + + /* If no top-level application collection is found and usage page/usage pair is found, pair is valid + https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */ + if (initial && usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; /* success */ + } + + return 1; /* finished processing */ +} + +static struct hid_device_info *create_device_info(const struct usb_device_info *udi, const char *path, const struct usb_ctl_report_desc *ucrd) +{ + struct hid_device_info *root; + struct hid_device_info *end; + + root = (struct hid_device_info *) calloc(1, sizeof(struct hid_device_info)); + if (!root) + return NULL; + + end = root; + + /* Path */ + end->path = (path) ? strdup(path) : NULL; + + /* Vendor Id */ + end->vendor_id = udi->udi_vendorNo; + + /* Product Id */ + end->product_id = udi->udi_productNo; + + /* Serial Number */ + end->serial_number = utf8_to_wchar_t(udi->udi_serial); + + /* Release Number */ + end->release_number = udi->udi_releaseNo; + + /* Manufacturer String */ + end->manufacturer_string = utf8_to_wchar_t(udi->udi_vendor); + + /* Product String */ + end->product_string = utf8_to_wchar_t(udi->udi_product); + + /* Usage Page */ + end->usage_page = 0; + + /* Usage */ + end->usage = 0; + + /* Interface Number */ + end->interface_number = -1; + + /* Next Device Info */ + end->next = NULL; + + /* Bus Type */ + end->bus_type = HID_API_BUS_USB; + + if (ucrd) { + uint16_t page; + uint16_t usage; + struct hid_usage_iterator usage_iterator; + + page = usage = 0; + memset(&usage_iterator, 0, sizeof(usage_iterator)); + + /* + * Parse the first usage and usage page + * out of the report descriptor. + */ + if (get_next_hid_usage(ucrd->ucrd_data, ucrd->ucrd_size, &usage_iterator, &page, &usage) == 0) { + end->usage_page = page; + end->usage = usage; + } + + /* + * Parse any additional usage and usage pages + * out of the report descriptor. + */ + while (get_next_hid_usage(ucrd->ucrd_data, ucrd->ucrd_size, &usage_iterator, &page, &usage) == 0) { + /* Create new record for additional usage pairs */ + struct hid_device_info *node = (struct hid_device_info *) calloc(1, sizeof(struct hid_device_info)); + + if (!node) + continue; + + /* Update fields */ + node->path = (end->path) ? strdup(end->path) : NULL; + node->vendor_id = end->vendor_id; + node->product_id = end->product_id; + node->serial_number = (end->serial_number) ? wcsdup(end->serial_number) : NULL; + node->release_number = end->release_number; + node->manufacturer_string = (end->manufacturer_string) ? wcsdup(end->manufacturer_string) : NULL; + node->product_string = (end->product_string) ? wcsdup(end->product_string) : NULL; + node->usage_page = page; + node->usage = usage; + node->interface_number = end->interface_number; + node->next = NULL; + node->bus_type = end->bus_type; + + /* Insert node */ + end->next = node; + end = node; + } + } + + return root; +} + +static int is_usb_controller(const char *s) +{ + return (!strncmp(s, "usb", 3) && isdigit((int) s[3])); +} + +static int is_uhid_parent_device(const char *s) +{ + return (!strncmp(s, "uhidev", 6) && isdigit((int) s[6])); +} + +static int is_uhid_device(const char *s) +{ + return (!strncmp(s, "uhid", 4) && isdigit((int) s[4])); +} + +static void walk_device_tree(int drvctl, const char *dev, int depth, char arr[static HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN], size_t *len, int (*cmp) (const char *)) +{ + int res; + char childname[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + struct devlistargs dla; + + if (depth && (!dev || !*dev)) + return; + + if (cmp(dev) && *len < HIDAPI_MAX_CHILD_DEVICES) + strlcpy(arr[(*len)++], dev, sizeof(*arr)); + + strlcpy(dla.l_devname, dev, sizeof(dla.l_devname)); + dla.l_childname = childname; + dla.l_children = HIDAPI_MAX_CHILD_DEVICES; + + res = ioctl(drvctl, DRVLISTDEV, &dla); + if (res == -1) + return; + + /* + * DO NOT CHANGE THIS. This is a fail-safe check + * for the unlikely event that a parent device has + * more than HIDAPI_MAX_CHILD_DEVICES child devices + * to prevent iterating over uninitialized data. + */ + if (dla.l_children > HIDAPI_MAX_CHILD_DEVICES) + return; + + for (size_t i = 0; i < dla.l_children; i++) + walk_device_tree(drvctl, dla.l_childname[i], depth + 1, arr, len, cmp); +} + +static void enumerate_usb_devices(int bus, uint8_t addr, enumerate_devices_callback func, void *data) +{ + int res; + struct usb_device_info udi; + + udi.udi_addr = addr; + + res = ioctl(bus, USB_DEVICEINFO, &udi); + if (res == -1) + return; + + for (int port = 0; port < udi.udi_nports; port++) { + addr = udi.udi_ports[port]; + if (addr >= USB_MAX_DEVICES) + continue; + + enumerate_usb_devices(bus, addr, func, data); + } + + func(&udi, data); +} + +static void hid_enumerate_callback(const struct usb_device_info *udi, void *data) +{ + struct hid_enumerate_data *hed; + + hed = (struct hid_enumerate_data *) data; + + if (hed->vendor_id != 0 && hed->vendor_id != udi->udi_vendorNo) + return; + + if (hed->product_id != 0 && hed->product_id != udi->udi_productNo) + return; + + for (size_t i = 0; i < USB_MAX_DEVNAMES; i++) { + const char *parent_dev; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + const char *child_dev; + char devpath[USB_MAX_DEVNAMELEN]; + int uhid; + struct usb_ctl_report_desc ucrd; + int use_ucrd; + struct hid_device_info *node; + + parent_dev = udi->udi_devnames[i]; + if (!is_uhid_parent_device(parent_dev)) + continue; + + len = 0; + walk_device_tree(hed->drvctl, parent_dev, 0, arr, &len, is_uhid_device); + + if (len == 0) + continue; + + child_dev = arr[0]; + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, child_dev, sizeof(devpath)); + + uhid = open(devpath, O_RDONLY | O_CLOEXEC); + if (uhid >= 0) { + use_ucrd = (ioctl(uhid, USB_GET_REPORT_DESC, &ucrd) != -1); + close(uhid); + } else { + use_ucrd = 0; + } + + node = create_device_info(udi, parent_dev, (use_ucrd) ? &ucrd : NULL); + if (!node) + continue; + + if (!hed->root) { + hed->root = node; + hed->end = node; + } else { + hed->end->next = node; + hed->end = node; + } + + while (hed->end->next) + hed->end = hed->end->next; + } +} + +static int set_report(hid_device *dev, const uint8_t *data, size_t length, int report) +{ + int res; + int device_handle; + struct usb_ctl_report ucr; + + if (length < 1) { + register_device_error(dev, "report must be greater than 1 byte"); + return -1; + } + + device_handle = dev->report_handles[*data]; + if (device_handle < 0) { + register_device_error_format(dev, "unsupported report id: %hhu", *data); + return -1; + } + + length--; + data++; + + if (length > sizeof(ucr.ucr_data)) { + register_device_error_format(dev, "report must be less than or equal to %zu bytes", sizeof(ucr.ucr_data)); + return -1; + } + + ucr.ucr_report = report; + memcpy(ucr.ucr_data, data, length); + + res = ioctl(device_handle, USB_SET_REPORT, &ucr); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_SET_REPORT): %s", strerror(errno)); + return -1; + } + + return (int) (length + 1); +} + +static int get_report(hid_device *dev, uint8_t *data, size_t length, int report) +{ + int res; + int device_handle; + struct usb_ctl_report ucr; + + if (length < 1) { + register_device_error(dev, "report must be greater than 1 byte"); + return -1; + } + + device_handle = dev->report_handles[*data]; + if (device_handle < 0) { + register_device_error_format(dev, "unsupported report id: %hhu", *data); + return -1; + } + + length--; + data++; + + if (length > sizeof(ucr.ucr_data)) { + length = sizeof(ucr.ucr_data); + } + + ucr.ucr_report = report; + + res = ioctl(device_handle, USB_GET_REPORT, &ucr); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_REPORT): %s", strerror(errno)); + return -1; + } + + memcpy(data, ucr.ucr_data, length); + + return (int) (length + 1); +} + +int HID_API_EXPORT HID_API_CALL hid_init(void) +{ + /* indicate no error */ + register_global_error(NULL); + + return 0; +} + +int HID_API_EXPORT HID_API_CALL hid_exit(void) +{ + /* Free global error message */ + register_global_error(NULL); + + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + int res; + int drvctl; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + struct hid_enumerate_data hed; + + res = hid_init(); + if (res == -1) + return NULL; + + drvctl = open(DRVCTLDEV, O_RDONLY | O_CLOEXEC); + if (drvctl == -1) { + register_global_error_format("failed to open drvctl: %s", strerror(errno)); + return NULL; + } + + len = 0; + walk_device_tree(drvctl, "", 0, arr, &len, is_usb_controller); + + hed.root = NULL; + hed.end = NULL; + hed.drvctl = drvctl; + hed.vendor_id = vendor_id; + hed.product_id = product_id; + + for (size_t i = 0; i < len; i++) { + char devpath[USB_MAX_DEVNAMELEN]; + int bus; + + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, arr[i], sizeof(devpath)); + + bus = open(devpath, O_RDONLY | O_CLOEXEC); + if (bus == -1) + continue; + + enumerate_usb_devices(bus, 0, hid_enumerate_callback, &hed); + + close(bus); + } + + close(drvctl); + + return hed.root; +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + while (devs) { + struct hid_device_info *next = devs->next; + free(devs->path); + free(devs->serial_number); + free(devs->manufacturer_string); + free(devs->product_string); + free(devs); + devs = next; + } +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs; + struct hid_device_info *dev; + char path[USB_MAX_DEVNAMELEN]; + + devs = hid_enumerate(vendor_id, product_id); + if (!devs) + return NULL; + + *path = '\0'; + + for (dev = devs; dev; dev = dev->next) { + if (dev->vendor_id != vendor_id) + continue; + + if (dev->product_id != product_id) + continue; + + if (serial_number && wcscmp(dev->serial_number, serial_number)) + continue; + + strlcpy(path, dev->path, sizeof(path)); + + break; + } + + hid_free_enumeration(devs); + + if (*path == '\0') { + register_global_error("Device with requested VID/PID/(SerialNumber) not found"); + return NULL; + } + + return hid_open_path(path); +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + int res; + hid_device *dev; + int drvctl; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + + res = hid_init(); + if (res == -1) + goto err_0; + + dev = (hid_device *) calloc(1, sizeof(hid_device)); + if (!dev) { + register_global_error("could not allocate hid_device"); + goto err_0; + } + + drvctl = open(DRVCTLDEV, O_RDONLY | O_CLOEXEC); + if (drvctl == -1) { + register_global_error_format("failed to open drvctl: %s", strerror(errno)); + goto err_1; + } + + if (!is_uhid_parent_device(path)) { + register_global_error("not a uhidev device"); + goto err_2; + } + + len = 0; + walk_device_tree(drvctl, path, 0, arr, &len, is_uhid_device); + + dev->poll_handles_length = 0; + memset(dev->poll_handles, 0x00, sizeof(dev->poll_handles)); + memset(dev->report_handles, 0xff, sizeof(dev->report_handles)); + + for (size_t i = 0; i < len; i++) { + const char *child_dev; + char devpath[USB_MAX_DEVNAMELEN]; + int uhid; + int rep_id; + struct pollfd *ph; + + child_dev = arr[i]; + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, child_dev, sizeof(devpath)); + + uhid = open(devpath, O_RDWR | O_CLOEXEC); + if (uhid == -1) { + register_global_error_format("failed to open %s: %s", child_dev, strerror(errno)); + goto err_3; + } + + res = ioctl(uhid, USB_GET_REPORT_ID, &rep_id); + if (res == -1) { + close(uhid); + register_global_error_format("failed to get report id %s: %s", child_dev, strerror(errno)); + goto err_3; + } + + ph = &dev->poll_handles[dev->poll_handles_length++]; + ph->fd = uhid; + ph->events = POLLIN; + ph->revents = 0; + dev->report_handles[rep_id] = uhid; + dev->device_handle = uhid; + } + + dev->blocking = 1; + dev->last_error_str = NULL; + dev->device_info = NULL; + strlcpy(dev->path, path, sizeof(dev->path)); + + register_global_error(NULL); + return dev; + +err_3: + for (size_t i = 0; i < dev->poll_handles_length; i++) + close(dev->poll_handles[i].fd); +err_2: + close(drvctl); +err_1: + free(dev); +err_0: + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, data, length, UHID_OUTPUT_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int res; + size_t i; + struct pollfd *ph; + ssize_t n; + + res = poll(dev->poll_handles, dev->poll_handles_length, milliseconds); + if (res == -1) { + register_device_error_format(dev, "error while polling: %s", strerror(errno)); + return -1; + } + + if (res == 0) + return 0; + + for (i = 0; i < dev->poll_handles_length; i++) { + ph = &dev->poll_handles[i]; + + if (ph->revents & (POLLERR | POLLHUP | POLLNVAL)) { + register_device_error(dev, "device IO error while polling"); + return -1; + } + + if (ph->revents & POLLIN) + break; + } + + if (i == dev->poll_handles_length) + return 0; + + n = read(ph->fd, data, length); + if (n == -1) { + if (errno == EAGAIN || errno == EINPROGRESS) + n = 0; + else + register_device_error_format(dev, "error while reading: %s", strerror(errno)); + } + + return n; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking) ? -1 : 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, data, length, UHID_FEATURE_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + return get_report(dev, data, length, UHID_FEATURE_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + return get_report(dev, data, length, UHID_INPUT_REPORT); +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Free the device error message */ + register_device_error(dev, NULL); + + hid_free_enumeration(dev->device_info); + + for (size_t i = 0; i < dev->poll_handles_length; i++) + close(dev->poll_handles[i].fd); + + free(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->manufacturer_string) { + wcsncpy(string, hdi->manufacturer_string, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->product_string) { + wcsncpy(string, hdi->product_string, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->serial_number) { + wcsncpy(string, hdi->serial_number, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev) +{ + int res; + struct usb_device_info udi; + struct usb_ctl_report_desc ucrd; + int use_ucrd; + struct hid_device_info *hdi; + + if (dev->device_info) + return dev->device_info; + + res = ioctl(dev->device_handle, USB_GET_DEVICEINFO, &udi); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_DEVICEINFO): %s", strerror(errno)); + return NULL; + } + + use_ucrd = (ioctl(dev->device_handle, USB_GET_REPORT_DESC, &ucrd) != -1); + + hdi = create_device_info(&udi, dev->path, (use_ucrd) ? &ucrd : NULL); + if (!hdi) { + register_device_error(dev, "failed to create device info"); + return NULL; + } + + dev->device_info = hdi; + + return hdi; +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + int res; + struct usb_string_desc usd; + usb_string_descriptor_t *str; + iconv_t ic; + const char *src; + size_t srcleft; + char *dst; + size_t dstleft; + size_t ic_res; + + /* First let us get the supported language IDs. */ + usd.usd_string_index = 0; + usd.usd_language_id = 0; + + res = ioctl(dev->device_handle, USB_GET_STRING_DESC, &usd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_STRING_DESC): %s", strerror(errno)); + return -1; + } + + str = &usd.usd_desc; + + if (str->bLength < 4) { + register_device_error(dev, "failed to get supported language IDs"); + return -1; + } + + /* Now we can get the requested string. */ + usd.usd_string_index = string_index; + usd.usd_language_id = UGETW(str->bString[0]); + + res = ioctl(dev->device_handle, USB_GET_STRING_DESC, &usd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_STRING_DESC): %s", strerror(errno)); + return -1; + } + + /* Now we need to convert it, using iconv. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + ic = iconv_open("utf-32le", "utf-16le"); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + ic = iconv_open("utf-32be", "utf-16le"); +#endif + if (ic == (iconv_t) -1) { + register_device_error_format(dev, "iconv_open failed: %s", strerror(errno)); + return -1; + } + + src = (const char *) str->bString; + srcleft = str->bLength - 2; + dst = (char *) string; + dstleft = sizeof(wchar_t[maxlen]); + + ic_res = iconv(ic, &src, &srcleft, &dst, &dstleft); + iconv_close(ic); + if (ic_res == (size_t) -1) { + register_device_error_format(dev, "iconv failed: %s", strerror(errno)); + return -1; + } + + /* Write the terminating NULL. */ + string[maxlen - 1] = L'\0'; + if (dstleft >= sizeof(wchar_t)) + *((wchar_t *) dst) = L'\0'; + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + int res; + struct usb_ctl_report_desc ucrd; + + res = ioctl(dev->device_handle, USB_GET_REPORT_DESC, &ucrd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_REPORT_DESC): %s", strerror(errno)); + return -1; + } + + if ((size_t) ucrd.ucrd_size < buf_size) + buf_size = (size_t) ucrd.ucrd_size; + + memcpy(buf, ucrd.ucrd_data, buf_size); + + return (int) buf_size; +} + +HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev) +{ + if (dev) { + if (dev->last_error_str == NULL) + return L"Success"; + return dev->last_error_str; + } + + if (last_global_error_str == NULL) + return L"Success"; + return last_global_error_str; +} + +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) +{ + static const struct hid_api_version api_version = { + .major = HID_API_VERSION_MAJOR, + .minor = HID_API_VERSION_MINOR, + .patch = HID_API_VERSION_PATCH + }; + + return &api_version; +} + +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) +{ + return HID_API_VERSION_STR; +} diff --git a/src/hidapi/pc/hidapi-netbsd.pc.in b/src/hidapi/pc/hidapi-netbsd.pc.in new file mode 100644 index 0000000000000..fcb5ca2152e87 --- /dev/null +++ b/src/hidapi/pc/hidapi-netbsd.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: hidapi-netbsd +Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the netbsd implementation. +URL: https://github.com/libusb/hidapi +Version: @VERSION@ +Libs: -L${libdir} -lhidapi-netbsd +Cflags: -I${includedir}/hidapi diff --git a/src/hidapi/src/CMakeLists.txt b/src/hidapi/src/CMakeLists.txt index 507b2d13e231e..e663c3fd6247a 100644 --- a/src/hidapi/src/CMakeLists.txt +++ b/src/hidapi/src/CMakeLists.txt @@ -141,6 +141,18 @@ else() set(HIDAPI_NEED_EXPORT_LIBUDEV TRUE) endif() endif() + elseif(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + if(NOT DEFINED HIDAPI_WITH_NETBSD) + set(HIDAPI_WITH_NETBSD ON) + endif() + if(HIDAPI_WITH_NETBSD) + add_subdirectory("${PROJECT_ROOT}/netbsd" netbsd) + list(APPEND EXPORT_COMPONENTS netbsd) + set(EXPORT_ALIAS netbsd) + if(NOT BUILD_SHARED_LIBS) + set(HIDAPI_NEED_EXPORT_THREADS TRUE) + endif() + endif() else() set(HIDAPI_WITH_LIBUSB ON) endif() From f0e47f8ee07410e29dcba8a13c91f3e2ef3c92b1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 27 Nov 2023 12:09:31 -0800 Subject: [PATCH 440/725] Added support for the NACON Revolution 5 Pro controller --- src/joystick/controller_list.h | 4 ++ src/joystick/hidapi/SDL_hidapi_ps4.c | 27 ++++++++++-- src/joystick/hidapi/SDL_hidapi_ps5.c | 52 +++++++++++++++++++++++- src/joystick/hidapi/SDL_hidapijoystick.c | 1 + src/joystick/usb_ids.h | 5 +++ 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 331bf171588ed..d8342f680907f 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -141,6 +141,8 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x2c22, 0x2303 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Obsidian Arcade Joystick { MAKE_CONTROLLER_ID( 0x2c22, 0x2500 ), k_eControllerType_PS4Controller, NULL }, // Qanba Dragon { MAKE_CONTROLLER_ID( 0x2c22, 0x2503 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Dragon Arcade Joystick + { MAKE_CONTROLLER_ID( 0x3285, 0x0d16 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode with dongle) + { MAKE_CONTROLLER_ID( 0x3285, 0x0d17 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode wired) { MAKE_CONTROLLER_ID( 0x7545, 0x0104 ), k_eControllerType_PS4Controller, NULL }, // Armor 3 or Level Up Cobra - At least one variant has gyro { MAKE_CONTROLLER_ID (0x9886, 0x0024 ), k_eControllerType_XInputPS4Controller, NULL }, // Astro C40 in Xbox 360 mode { MAKE_CONTROLLER_ID( 0x9886, 0x0025 ), k_eControllerType_PS4Controller, NULL }, // Astro C40 @@ -154,6 +156,8 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x0f0d, 0x0184 ), k_eControllerType_PS5Controller, NULL }, // Hori Fighting Stick α { MAKE_CONTROLLER_ID( 0x1532, 0x100b ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wired) { MAKE_CONTROLLER_ID( 0x1532, 0x100c ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wireless) + { MAKE_CONTROLLER_ID( 0x3285, 0x0d18 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode with dongle) + { MAKE_CONTROLLER_ID( 0x3285, 0x0d19 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode wired) { MAKE_CONTROLLER_ID( 0x358a, 0x0104 ), k_eControllerType_PS5Controller, NULL }, // Backbone One PlayStation Edition for iOS { MAKE_CONTROLLER_ID( 0x0079, 0x0006 ), k_eControllerType_UnknownNonSteamController, NULL }, // DragonRise Generic USB PCB, sometimes configured as a PC Twin Shock Controller - looks like a DS3 but the face buttons are 1-4 instead of symbols diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 33a262dcd2f43..a5e9cb0a33c96 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -142,6 +142,7 @@ typedef struct SDL_HIDAPI_Device *device; SDL_Joystick *joystick; SDL_bool is_dongle; + SDL_bool is_nacon_dongle; SDL_bool official_controller; SDL_bool sensors_supported; SDL_bool lightbar_supported; @@ -413,6 +414,11 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) } ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported); + if (device->vendor_id == USB_VENDOR_NACON_ALT && + device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS) { + ctx->is_nacon_dongle = SDL_TRUE; + } + if (device->vendor_id == USB_VENDOR_PDP && (device->product_id == USB_PRODUCT_VICTRIX_FS_PRO || device->product_id == USB_PRODUCT_VICTRIX_FS_PRO_V2)) { @@ -438,7 +444,7 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) } else { HIDAPI_DisconnectBluetoothDevice(device->serial); } - if (ctx->is_dongle && serial[0] == '\0') { + if ((ctx->is_dongle || ctx->is_nacon_dongle) && serial[0] == '\0') { /* Not yet connected */ return SDL_TRUE; } @@ -1147,6 +1153,21 @@ static SDL_bool HIDAPI_DriverPS4_IsPacketValid(SDL_DriverPS4_Context *ctx, Uint8 return SDL_TRUE; } + if (ctx->is_nacon_dongle && size >= (1 + sizeof(PS4StatePacket_t))) { + /* The report timestamp doesn't change when the controller isn't connected */ + PS4StatePacket_t *packet = (PS4StatePacket_t *)&data[1]; + if (SDL_memcmp(packet->rgucTimestamp, ctx->last_state.rgucTimestamp, sizeof(packet->rgucTimestamp)) == 0) { + return SDL_FALSE; + } + if (ctx->last_state.rgucAccelX[0] == 0 && ctx->last_state.rgucAccelX[1] == 0 && + ctx->last_state.rgucAccelY[0] == 0 && ctx->last_state.rgucAccelY[1] == 0 && + ctx->last_state.rgucAccelZ[0] == 0 && ctx->last_state.rgucAccelZ[1] == 0) { + /* We don't have any state to compare yet, go ahead and copy it */ + SDL_memcpy(&ctx->last_state, &data[1], sizeof(PS4StatePacket_t)); + return SDL_FALSE; + } + } + /* In the case of a DS4 USB dongle, bit[2] of byte 31 indicates if a DS4 is actually connected (indicated by '0'). * For non-dongle, this bit is always 0 (connected). * This is usually the ID over USB, but the DS4v2 that started shipping with the PS4 Slim will also send this @@ -1258,7 +1279,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) } } - if (ctx->is_dongle) { + if (ctx->is_dongle || ctx->is_nacon_dongle) { if (packet_count == 0) { if (device->num_joysticks > 0) { /* Check to see if it looks like the device disconnected */ @@ -1280,7 +1301,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) } } - if (size < 0 && device->num_joysticks > 0) { + if (packet_count == 0 && size < 0 && device->num_joysticks > 0) { /* Read error, device is disconnected */ HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 37b15991b6dff..4e71f95c61b9c 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -231,6 +231,7 @@ typedef struct { SDL_HIDAPI_Device *device; SDL_Joystick *joystick; + SDL_bool is_nacon_dongle; SDL_bool use_alternate_report; SDL_bool sensors_supported; SDL_bool lightbar_supported; @@ -264,6 +265,7 @@ typedef struct { PS5SimpleStatePacket_t simple; PS5StatePacketCommon_t state; + PS5StatePacketAlt_t alt_state; PS5StatePacket_t full_state; Uint8 data[64]; } last_state; @@ -491,10 +493,17 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) } ctx->use_alternate_report = SDL_TRUE; + + if (device->vendor_id == USB_VENDOR_NACON_ALT && + (device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED || + device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS)) { + /* This doesn't report vibration capability, but it can do rumble */ + ctx->vibration_supported = SDL_TRUE; + } } else if (device->vendor_id == USB_VENDOR_RAZER && (device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRED || device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRELESS)) { - /* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors, but no vibration */ + /* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors and no vibration */ ctx->sensors_supported = SDL_TRUE; ctx->touchpad_supported = SDL_TRUE; ctx->use_alternate_report = SDL_TRUE; @@ -502,6 +511,11 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) } ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported || ctx->playerled_supported); + if (device->vendor_id == USB_VENDOR_NACON_ALT && + device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS) { + ctx->is_nacon_dongle = SDL_TRUE; + } + device->joystick_type = joystick_type; device->type = SDL_GAMEPAD_TYPE_PS5; if (device->vendor_id == USB_VENDOR_SONY) { @@ -513,6 +527,11 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) } HIDAPI_SetDeviceSerial(device, serial); + if (ctx->is_nacon_dongle) { + /* We don't know if this is connected yet, wait for reports */ + return SDL_TRUE; + } + /* Prefer the USB device over the Bluetooth device */ if (device->is_bluetooth) { if (HIDAPI_HasConnectedUSBDevice(device->serial)) { @@ -1437,6 +1456,20 @@ static SDL_bool HIDAPI_DriverPS5_IsPacketValid(SDL_DriverPS5_Context *ctx, Uint8 { switch (data[0]) { case k_EPS5ReportIdState: + if (ctx->is_nacon_dongle && size >= (1 + sizeof(PS5StatePacketAlt_t))) { + /* The report timestamp doesn't change when the controller isn't connected */ + PS5StatePacketAlt_t *packet = (PS5StatePacketAlt_t *)&data[1]; + if (SDL_memcmp(packet->rgucPacketSequence, ctx->last_state.state.rgucPacketSequence, sizeof(packet->rgucPacketSequence)) == 0) { + return SDL_FALSE; + } + if (ctx->last_state.alt_state.rgucAccelX[0] == 0 && ctx->last_state.alt_state.rgucAccelX[1] == 0 && + ctx->last_state.alt_state.rgucAccelY[0] == 0 && ctx->last_state.alt_state.rgucAccelY[1] == 0 && + ctx->last_state.alt_state.rgucAccelZ[0] == 0 && ctx->last_state.alt_state.rgucAccelZ[1] == 0) { + /* We don't have any state to compare yet, go ahead and copy it */ + SDL_memcpy(&ctx->last_state, &data[1], sizeof(PS5StatePacketAlt_t)); + return SDL_FALSE; + } + } return SDL_TRUE; case k_EPS5ReportIdBluetoothState: @@ -1531,7 +1564,22 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) } } - if (size < 0 && device->num_joysticks > 0) { + if (ctx->is_nacon_dongle) { + if (packet_count == 0) { + if (device->num_joysticks > 0) { + /* Check to see if it looks like the device disconnected */ + if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) { + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + } + } + } else { + if (device->num_joysticks == 0) { + HIDAPI_JoystickConnected(device, NULL); + } + } + } + + if (packet_count == 0 && size < 0 && device->num_joysticks > 0) { /* Read error, device is disconnected */ HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 01e44286407af..be3eb2e92d414 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -157,6 +157,7 @@ SDL_bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product) case USB_VENDOR_MADCATZ: return SDL_TRUE; case USB_VENDOR_NACON: + case USB_VENDOR_NACON_ALT: return SDL_TRUE; case USB_VENDOR_PDP: return SDL_TRUE; diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 08bd21bca52cc..a582512ad87d7 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -39,6 +39,7 @@ #define USB_VENDOR_MADCATZ 0x0738 #define USB_VENDOR_MICROSOFT 0x045e #define USB_VENDOR_NACON 0x146b +#define USB_VENDOR_NACON_ALT 0x3285 #define USB_VENDOR_NINTENDO 0x057e #define USB_VENDOR_NVIDIA 0x0955 #define USB_VENDOR_PDP 0x0e6f @@ -72,6 +73,10 @@ #define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184 #define USB_PRODUCT_LOGITECH_F310 0xc216 #define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1 +#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS 0x0d16 +#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17 +#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18 +#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19 #define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337 #define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019 #define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e From 6bb40f1d8d0fa2b1752f60472c84486b1c735b0c Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 27 Nov 2023 19:35:45 +0100 Subject: [PATCH 441/725] SDL_VideoCapture: allow add/remove device at runtime on linux --- src/core/linux/SDL_evdev_capabilities.h | 1 + src/core/linux/SDL_udev.c | 10 + src/video/SDL_sysvideocapture.h | 8 +- src/video/SDL_video_capture.c | 50 ++- src/video/SDL_video_capture_apple.m | 54 +++- src/video/SDL_video_capture_v4l2.c | 286 ++++++++++++++++-- src/video/android/SDL_android_video_capture.c | 39 ++- test/testvideocapture.c | 6 +- test/testvideocaptureminimal.c | 2 +- 9 files changed, 409 insertions(+), 47 deletions(-) diff --git a/src/core/linux/SDL_evdev_capabilities.h b/src/core/linux/SDL_evdev_capabilities.h index 94afee7960e71..ca90309ed0e61 100644 --- a/src/core/linux/SDL_evdev_capabilities.h +++ b/src/core/linux/SDL_evdev_capabilities.h @@ -53,6 +53,7 @@ typedef enum SDL_UDEV_DEVICE_ACCELEROMETER = 0x0020, SDL_UDEV_DEVICE_TOUCHPAD = 0x0040, SDL_UDEV_DEVICE_HAS_KEYS = 0x0080, + SDL_UDEV_DEVICE_VIDEO_CAPTURE = 0x0100, } SDL_UDEV_deviceclass; #define BITS_PER_LONG (sizeof(unsigned long) * 8) diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index a459489b2563e..903f272086693 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -139,6 +139,7 @@ int SDL_UDEV_Init(void) _this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL); _this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL); + _this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "video4linux", NULL); _this->syms.udev_monitor_enable_receiving(_this->udev_mon); /* Do an initial scan of existing devices */ @@ -200,6 +201,7 @@ int SDL_UDEV_Scan(void) _this->syms.udev_enumerate_add_match_subsystem(enumerate, "input"); _this->syms.udev_enumerate_add_match_subsystem(enumerate, "sound"); + _this->syms.udev_enumerate_add_match_subsystem(enumerate, "video4linux"); _this->syms.udev_enumerate_scan_devices(enumerate); devs = _this->syms.udev_enumerate_get_list_entry(enumerate); @@ -405,8 +407,16 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) } subsystem = _this->syms.udev_device_get_subsystem(dev); + if (SDL_strcmp(subsystem, "sound") == 0) { devclass = SDL_UDEV_DEVICE_SOUND; + } else if (SDL_strcmp(subsystem, "video4linux") == 0) { + devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE; + + val = _this->syms.udev_device_get_property_value(dev, "ID_V4L_CAPABILITIES"); + if (!val || !SDL_strcasestr(val, "capture")) { + return; + } } else if (SDL_strcmp(subsystem, "input") == 0) { /* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */ diff --git a/src/video/SDL_sysvideocapture.h b/src/video/SDL_sysvideocapture.h index fe71664f51959..305ba53ec586b 100644 --- a/src/video/SDL_sysvideocapture.h +++ b/src/video/SDL_sysvideocapture.h @@ -61,6 +61,9 @@ struct SDL_VideoCaptureDevice struct SDL_PrivateVideoCaptureData *hidden; }; +extern int SDL_SYS_VideoCaptureInit(void); +extern int SDL_SYS_VideoCaptureQuit(void); + extern int OpenDevice(SDL_VideoCaptureDevice *_this); extern void CloseDevice(SDL_VideoCaptureDevice *_this); @@ -80,9 +83,8 @@ extern int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format); extern int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format); extern int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height); -extern int GetDeviceName(int index, char *buf, int size); -extern int GetNumDevices(void); - +extern int GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size); +extern SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count); extern SDL_bool check_all_device_closed(void); extern SDL_bool check_device_playing(void); diff --git a/src/video/SDL_video_capture.c b/src/video/SDL_video_capture.c index bd4fc8257758a..57f960addb908 100644 --- a/src/video/SDL_video_capture.c +++ b/src/video/SDL_video_capture.c @@ -311,7 +311,6 @@ const char * SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id) { #ifdef SDL_VIDEO_CAPTURE - int index = instance_id - 1; static char buf[256]; buf[0] = 0; buf[255] = 0; @@ -321,7 +320,7 @@ SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id) return NULL; } - if (GetDeviceName(index, buf, sizeof (buf)) < 0) { + if (GetDeviceName(instance_id, buf, sizeof (buf)) < 0) { buf[0] = 0; } return buf; @@ -336,14 +335,21 @@ SDL_VideoCaptureDeviceID * SDL_GetVideoCaptureDevices(int *count) { - int i; -#ifdef SDL_VIDEO_CAPTURE - int num = GetNumDevices(); -#else int num = 0; + SDL_VideoCaptureDeviceID *ret = NULL; +#ifdef SDL_VIDEO_CAPTURE + ret = GetVideoCaptureDevices(&num); #endif - SDL_VideoCaptureDeviceID *ret; + if (ret) { + if (count) { + *count = num; + } + return ret; + } + + /* return list of 0 ID, null terminated */ + num = 0; ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); if (ret == NULL) { @@ -354,11 +360,7 @@ SDL_GetVideoCaptureDevices(int *count) return NULL; } - for (i = 0; i < num; i++) { - ret[i] = i + 1; - } ret[num] = 0; - if (count) { *count = num; } @@ -501,6 +503,8 @@ SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id) } } +#if 0 + // FIXME do we need this ? /* Let the user override. */ { const char *dev = SDL_getenv("SDL_VIDEO_CAPTURE_DEVICE_NAME"); @@ -508,6 +512,7 @@ SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id) device_name = dev; } } +#endif if (device_name == NULL) { goto error; @@ -823,6 +828,8 @@ SDL_VideoCaptureInit(void) { #ifdef SDL_VIDEO_CAPTURE SDL_zeroa(open_devices); + + SDL_SYS_VideoCaptureInit(); return 0; #else return 0; @@ -839,6 +846,8 @@ SDL_QuitVideoCapture(void) } SDL_zeroa(open_devices); + + SDL_SYS_VideoCaptureQuit(); #endif } @@ -857,6 +866,16 @@ SDL_QuitVideoCapture(void) /* See SDL_video_capture_apple.m */ #else +int SDL_SYS_VideoCaptureInit(void) +{ + return 0; +} + +int SDL_SYS_VideoCaptureQuit(void) +{ + return 0; +} + int OpenDevice(SDL_VideoCaptureDevice *_this) { @@ -933,16 +952,17 @@ GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width } int -GetDeviceName(int index, char *buf, int size) +GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) { return -1; } -int -GetNumDevices(void) +SDL_VideoCaptureDeviceID * +GetVideoCaptureDevices(int *count) { - return -1; + return NULL; } + #endif #endif /* SDL_VIDEO_CAPTURE */ diff --git a/src/video/SDL_video_capture_apple.m b/src/video/SDL_video_capture_apple.m index 3e58cf4e7a61c..7e88ea08ad745 100644 --- a/src/video/SDL_video_capture_apple.m +++ b/src/video/SDL_video_capture_apple.m @@ -49,7 +49,7 @@ int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) { } void CloseDevice(SDL_VideoCaptureDevice *_this) { } -int GetDeviceName(int index, char *buf, int size) { +int GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) { return -1; } int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) { @@ -61,8 +61,8 @@ int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) { int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) { return -1; } -int GetNumDevices(void) { - return 0; +SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count) { + return NULL; } int GetNumFormats(SDL_VideoCaptureDevice *_this) { return 0; @@ -79,6 +79,13 @@ int StartCapture(SDL_VideoCaptureDevice *_this) { int StopCapture(SDL_VideoCaptureDevice *_this) { return 0; } +int SDL_SYS_VideoCaptureInit(void) { + return 0; +} +int SDL_SYS_VideoCaptureQuit(void) { + return 0; +} + #else @@ -589,8 +596,9 @@ - (void)captureOutput:(AVCaptureOutput *)output } int -GetDeviceName(int index, char *buf, int size) +GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) { + int index = instance_id - 1; NSArray *devices = discover_devices(); if (index < [devices count]) { AVCaptureDevice *device = devices[index]; @@ -602,13 +610,49 @@ - (void)captureOutput:(AVCaptureOutput *)output return -1; } -int +static int GetNumDevices(void) { NSArray *devices = discover_devices(); return [devices count]; } +SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count) +{ + /* hard-coded list of ID */ + int i; + int num = GetNumDevices(); + SDL_VideoCaptureDeviceID *ret; + + ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); + + if (ret == NULL) { + SDL_OutOfMemory(); + *count = 0; + return NULL; + } + + for (i = 0; i < num; i++) { + ret[i] = i + 1; + } + ret[num] = 0; + *count = num; + return ret; +} + +int SDL_SYS_VideoCaptureInit(void) +{ + return 0; +} + +int SDL_SYS_VideoCaptureQuit(void) +{ + return 0; +} + + + + #endif /* HAVE_COREMEDIA */ #endif /* SDL_VIDEO_CAPTURE */ diff --git a/src/video/SDL_video_capture_v4l2.c b/src/video/SDL_video_capture_v4l2.c index 539cc17112396..29dcb0f4ee62e 100644 --- a/src/video/SDL_video_capture_v4l2.c +++ b/src/video/SDL_video_capture_v4l2.c @@ -28,11 +28,41 @@ #include "SDL_video_capture_c.h" #include "SDL_pixels_c.h" #include "../thread/SDL_systhread.h" +#include "../../core/linux/SDL_evdev_capabilities.h" +#include "../../core/linux/SDL_udev.h" +#include /* INT_MAX */ #define DEBUG_VIDEO_CAPTURE_CAPTURE 1 #if defined(__linux__) && !defined(__ANDROID__) + +#define MAX_CAPTURE_DEVICES 128 /* It's doubtful someone has more than that */ + +static int MaybeAddDevice(const char *path); +#ifdef SDL_USE_LIBUDEV +static int MaybeRemoveDevice(const char *path); +static void capture_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath); +#endif /* SDL_USE_LIBUDEV */ + +/* + * List of available capture devices. + */ +typedef struct SDL_capturelist_item +{ + char *fname; /* Dev path name (like /dev/video0) */ + char *bus_info; /* don't add two paths with same bus_info (eg /dev/video0 and /dev/video1 */ + SDL_VideoCaptureDeviceID instance_id; + SDL_VideoCaptureDevice *device; /* Associated device */ + struct SDL_capturelist_item *next; +} SDL_capturelist_item; + +static SDL_capturelist_item *SDL_capturelist = NULL; +static SDL_capturelist_item *SDL_capturelist_tail = NULL; +static int num_video_captures = 0; + + + enum io_method { IO_METHOD_READ, IO_METHOD_MMAP, @@ -933,32 +963,252 @@ OpenDevice(SDL_VideoCaptureDevice *_this) return 0; } +int +GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) +{ + SDL_capturelist_item *item; + for (item = SDL_capturelist; item; item = item->next) { + if (item->instance_id == instance_id) { + SDL_snprintf(buf, size, "%s", item->fname); + return 0; + } + } + + /* unknown instance_id */ + return -1; +} + +SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count) +{ + /* real list of ID */ + int i = 0; + int num = num_video_captures; + SDL_VideoCaptureDeviceID *ret; + SDL_capturelist_item *item; -int -GetDeviceName(int index, char *buf, int size) { - SDL_snprintf(buf, size, "/dev/video%d", index); + ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); + + if (ret == NULL) { + SDL_OutOfMemory(); + *count = 0; + return NULL; + } + + for (item = SDL_capturelist; item; item = item->next) { + ret[i] = item->instance_id; + i++; + } + + ret[num] = 0; + *count = num; + return ret; +} + + +/* + * Initializes the subsystem by finding available devices. + */ +int SDL_SYS_VideoCaptureInit(void) +{ + const char pattern[] = "/dev/video%d"; + char path[PATH_MAX]; + int i, j; + + /* + * Limit amount of checks to MAX_CAPTURE_DEVICES since we may or may not have + * permission to some or all devices. + */ + i = 0; + for (j = 0; j < MAX_CAPTURE_DEVICES; ++j) { + (void)SDL_snprintf(path, PATH_MAX, pattern, i++); + if (MaybeAddDevice(path) == -2) { + break; + } + } + +#ifdef SDL_USE_LIBUDEV + if (SDL_UDEV_Init() < 0) { + return SDL_SetError("Could not initialize UDEV"); + } + + if (SDL_UDEV_AddCallback(capture_udev_callback) < 0) { + SDL_UDEV_Quit(); + return SDL_SetError("Could not setup Video Capture <-> udev callback"); + } + + /* Force a scan to build the initial device list */ + SDL_UDEV_Scan(); +#endif /* SDL_USE_LIBUDEV */ + + return num_video_captures; +} + + +int SDL_SYS_VideoCaptureQuit(void) +{ + SDL_capturelist_item *item; + for (item = SDL_capturelist; item; ) { + SDL_capturelist_item *tmp = item->next; + + SDL_free(item->fname); + SDL_free(item->bus_info); + SDL_free(item); + item = tmp; + } + + num_video_captures = 0; + SDL_capturelist = NULL; + SDL_capturelist_tail = NULL; + + return SDL_FALSE; +} + +#ifdef SDL_USE_LIBUDEV +static void capture_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) +{ + if (!devpath || !(udev_class & SDL_UDEV_DEVICE_VIDEO_CAPTURE)) { + return; + } + + switch (udev_type) { + case SDL_UDEV_DEVICEADDED: + MaybeAddDevice(devpath); + break; + + case SDL_UDEV_DEVICEREMOVED: + MaybeRemoveDevice(devpath); + break; + + default: + break; + } +} +#endif /* SDL_USE_LIBUDEV */ + +static SDL_bool DeviceExists(const char *path, const char *bus_info) { + SDL_capturelist_item *item; + + for (item = SDL_capturelist; item; item = item->next) { + /* found same dev name */ + if (SDL_strcmp(path, item->fname) == 0) { + return SDL_TRUE; + } + /* found same bus_info */ + if (SDL_strcmp(bus_info, item->bus_info) == 0) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static int MaybeAddDevice(const char *path) +{ + char *bus_info = NULL; + struct v4l2_capability vcap; + int err; + int fd; + SDL_capturelist_item *item; + + if (!path) { + return -1; + } + + fd = open(path, O_RDWR); + if (fd < 0) { + return -2; /* stop iterating /dev/video%d */ + } + err = ioctl(fd, VIDIOC_QUERYCAP, &vcap); + close(fd); + if (err) { + return -1; + } + + bus_info = SDL_strdup((char *)vcap.bus_info); + + if (DeviceExists(path, bus_info)) { + SDL_free(bus_info); + return 0; + } + + + /* Add new item */ + item = (SDL_capturelist_item *)SDL_calloc(1, sizeof(SDL_capturelist_item)); + if (!item) { + SDL_free(bus_info); + return -1; + } + + item->fname = SDL_strdup(path); + if (!item->fname) { + SDL_free(item); + SDL_free(bus_info); + return -1; + } + + item->fname = SDL_strdup(path); + item->bus_info = bus_info; + item->instance_id = SDL_GetNextObjectID(); + + + if (!SDL_capturelist_tail) { + SDL_capturelist = SDL_capturelist_tail = item; + } else { + SDL_capturelist_tail->next = item; + SDL_capturelist_tail = item; + } + + ++num_video_captures; + + /* !!! TODO: Send a add event? */ +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("Added video capture ID: %d %s (%s) (total: %d)", item->instance_id, path, bus_info, num_video_captures); +#endif return 0; } -int -GetNumDevices(void) { - int num; - for (num = 0; num < 128; num++) { - static char buf[256]; - buf[0] = 0; - buf[255] = 0; - GetDeviceName(num, buf, sizeof (buf)); - SDL_RWops *src = SDL_RWFromFile(buf, "rb"); - if (src == NULL) { - // When file does not exist, an error is set. Clear it. - SDL_ClearError(); - return num; +#ifdef SDL_USE_LIBUDEV +static int MaybeRemoveDevice(const char *path) +{ + + SDL_capturelist_item *item; + SDL_capturelist_item *prev = NULL; +#if DEBUG_VIDEO_CAPTURE_CAPTURE + SDL_Log("Remove video capture %s", path); +#endif + if (!path) { + return -1; + } + + for (item = SDL_capturelist; item; item = item->next) { + /* found it, remove it. */ + if (SDL_strcmp(path, item->fname) == 0) { + if (prev) { + prev->next = item->next; + } else { + SDL_assert(SDL_capturelist == item); + SDL_capturelist = item->next; + } + if (item == SDL_capturelist_tail) { + SDL_capturelist_tail = prev; + } + + /* Need to decrement the count */ + --num_video_captures; + /* !!! TODO: Send a remove event? */ + + SDL_free(item->fname); + SDL_free(item->bus_info); + SDL_free(item); + return 0; } - SDL_RWclose(src); + prev = item; } - return num; + return 0; } +#endif /* SDL_USE_LIBUDEV */ + + #endif diff --git a/src/video/android/SDL_android_video_capture.c b/src/video/android/SDL_android_video_capture.c index 244d779c2d6b4..3e8e433bb3bde 100644 --- a/src/video/android/SDL_android_video_capture.c +++ b/src/video/android/SDL_android_video_capture.c @@ -633,9 +633,12 @@ GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width return -1; } +static int GetNumDevices(void); + int -GetDeviceName(int index, char *buf, int size) +GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) { + int index = instance_id - 1; create_cameraMgr(); if (cameraIdList == NULL) { @@ -652,7 +655,7 @@ GetDeviceName(int index, char *buf, int size) return -1; } -int +static int GetNumDevices(void) { camera_status_t res; @@ -673,6 +676,38 @@ GetNumDevices(void) return -1; } +SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count) +{ + /* hard-coded list of ID */ + int i; + int num = GetNumDevices(); + SDL_VideoCaptureDeviceID *ret; + + ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); + + if (ret == NULL) { + SDL_OutOfMemory(); + *count = 0; + return NULL; + } + + for (i = 0; i < num; i++) { + ret[i] = i + 1; + } + ret[num] = 0; + *count = num; + return ret; +} + +int SDL_SYS_VideoCaptureInit(void) { + return 0; +} + +int SDL_SYS_VideoCaptureQuit(void) { + return 0; +} + + #endif diff --git a/test/testvideocapture.c b/test/testvideocapture.c index aff7642b1e3c4..62471a76300c3 100644 --- a/test/testvideocapture.c +++ b/test/testvideocapture.c @@ -125,7 +125,7 @@ static SDL_VideoCaptureDeviceID get_instance_id(int index) { } if (ret == 0) { - SDL_Log("invalid index"); +/* SDL_Log("invalid index"); */ } return ret; @@ -212,7 +212,7 @@ int main(int argc, char **argv) SDL_Log("%s", usage); /* Load the SDL library */ - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { /* FIXME: SDL_INIT_JOYSTICK needed for add/removing devices at runtime */ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); return 1; } @@ -439,7 +439,7 @@ int main(int argc, char **argv) SAVE_CAPTURE_STATE(current_dev); current_dev += 1; - if (current_dev == num || current_dev >= (int) SDL_arraysize(data_capture_tab)) { + if (current_dev >= num || current_dev >= (int) SDL_arraysize(data_capture_tab)) { current_dev = 0; } diff --git a/test/testvideocaptureminimal.c b/test/testvideocaptureminimal.c index 870dcab66037a..3c29d47ce5350 100644 --- a/test/testvideocaptureminimal.c +++ b/test/testvideocaptureminimal.c @@ -53,7 +53,7 @@ int main(int argc, char **argv) SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); /* Load the SDL library */ - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { /* FIXME: SDL_INIT_JOYSTICK needed for add/removing devices at runtime */ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); return 1; } From ed3fad18808714f9fab3111a45d06264ea6fb0c5 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 27 Nov 2023 22:03:56 +0100 Subject: [PATCH 442/725] cmake: disable oss by default on Linux, NetBSD and FreeBSD --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91b660e52c046..2e5b112d78227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,6 +220,12 @@ if(VITA OR PSP OR PS2 OR N3DS OR RISCOS) set(SDL_LOADSO_DEFAULT OFF) endif() +if((RISCOS OR UNIX_SYS) AND NOT (LINUX OR NETBSD OR FREEBSD)) + set(SDL_OSS_DEFAULT ON) +else() + set(SDL_OSS_DEFAULT OFF) +endif() + if(SDL_SHARED_DEFAULT AND SDL_STATIC_DEFAULT AND SDL_SHARED_AVAILABLE) if(DEFINED BUILD_SHARED_LIBS) # When defined, use BUILD_SHARED_LIBS as default @@ -306,7 +312,7 @@ dep_option(SDL_OPENGL "Include OpenGL support" ON "NOT VISIONOS" OF dep_option(SDL_OPENGLES "Include OpenGL ES support" ON "NOT VISIONOS" OFF) set_option(SDL_PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_DEFAULT}) dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" ON "SDL_PTHREADS" OFF) -dep_option(SDL_OSS "Support the OSS audio API" ON "UNIX_SYS OR RISCOS" OFF) +dep_option(SDL_OSS "Support the OSS audio API" ${SDL_OSS_DEFAULT} "UNIX_SYS OR RISCOS" OFF) set_option(SDL_ALSA "Support the ALSA audio API" ${UNIX_SYS}) dep_option(SDL_ALSA_SHARED "Dynamically load ALSA audio support" ON "SDL_ALSA" OFF) set_option(SDL_JACK "Support the JACK audio API" ${UNIX_SYS}) From ceac93ade27e2e147bc21aafc3b80c7879bbfaa5 Mon Sep 17 00:00:00 2001 From: "Jake S. Del Mastro" Date: Tue, 28 Nov 2023 08:48:19 -0500 Subject: [PATCH 443/725] Set framebuffer_srgb_capable to the actual value obtained (#8634) (cherry picked from commit 594a79c2f9db21a11a76c012b2b1655a21fc8982) --- src/video/windows/SDL_windowsopengl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 3b6c879e4efa2..9216b6c7b97e4 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -526,6 +526,9 @@ static int WIN_GL_ChoosePixelFormatARB(SDL_VideoDevice *_this, int *iAttribs, fl int pixel_format = 0; unsigned int matching; + int qAttrib = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; + int srgb = 0; + hwnd = CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0, 10, 10, NULL, NULL, SDL_Instance, NULL); @@ -547,6 +550,10 @@ static int WIN_GL_ChoosePixelFormatARB(SDL_VideoDevice *_this, int *iAttribs, fl &matching); } + /* Check whether we actually got an SRGB capable buffer */ + _this->gl_data->wglGetPixelFormatAttribivARB(hdc, pixel_format, 0, 1, &qAttrib, &srgb); + _this->gl_config.framebuffer_srgb_capable = srgb; + _this->gl_data->wglMakeCurrent(hdc, NULL); _this->gl_data->wglDeleteContext(hglrc); } From 5772e00c3f12f80374f67667dff66315265bb2fb Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 28 Nov 2023 16:45:33 +0100 Subject: [PATCH 444/725] cmake: disable oss by default on OpenBSD, not FreeBSD This fixes ed3fad18808714f9fab3111a45d06264ea6fb0c5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e5b112d78227..fab3c11e20640 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,7 +220,7 @@ if(VITA OR PSP OR PS2 OR N3DS OR RISCOS) set(SDL_LOADSO_DEFAULT OFF) endif() -if((RISCOS OR UNIX_SYS) AND NOT (LINUX OR NETBSD OR FREEBSD)) +if((RISCOS OR UNIX_SYS) AND NOT (LINUX OR NETBSD OR OPENBSD)) set(SDL_OSS_DEFAULT ON) else() set(SDL_OSS_DEFAULT OFF) From c5b0ff77d73411a0118ccc737d3099cac9ada45a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 28 Nov 2023 12:05:02 -0500 Subject: [PATCH 445/725] test: testwm2 now displays keyboard mod state. (cherry picked from commit 258849c9bc2f28b2b6dcacbab4d415054539598c) --- src/test/SDL_test_common.c | 89 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 80a7865889f8d..8c4e0749b96cd 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -861,6 +861,82 @@ static void SDLTest_PrintWindowFlags(char *text, size_t maxlen, Uint32 flags) } } +static void SDLTest_PrintModStateFlag(char *text, size_t maxlen, SDL_Keymod flag) +{ + switch (flag) { + case SDL_KMOD_LSHIFT: + SDL_snprintfcat(text, maxlen, "LSHIFT"); + break; + case SDL_KMOD_RSHIFT: + SDL_snprintfcat(text, maxlen, "RSHIFT"); + break; + case SDL_KMOD_LCTRL: + SDL_snprintfcat(text, maxlen, "LCTRL"); + break; + case SDL_KMOD_RCTRL: + SDL_snprintfcat(text, maxlen, "RCTRL"); + break; + case SDL_KMOD_LALT: + SDL_snprintfcat(text, maxlen, "LALT"); + break; + case SDL_KMOD_RALT: + SDL_snprintfcat(text, maxlen, "RALT"); + break; + case SDL_KMOD_LGUI: + SDL_snprintfcat(text, maxlen, "LGUI"); + break; + case SDL_KMOD_RGUI: + SDL_snprintfcat(text, maxlen, "RGUI"); + break; + case SDL_KMOD_NUM: + SDL_snprintfcat(text, maxlen, "NUM"); + break; + case SDL_KMOD_CAPS: + SDL_snprintfcat(text, maxlen, "CAPS"); + break; + case SDL_KMOD_MODE: + SDL_snprintfcat(text, maxlen, "MODE"); + break; + case SDL_KMOD_SCROLL: + SDL_snprintfcat(text, maxlen, "SCROLL"); + break; + default: + SDL_snprintfcat(text, maxlen, "0x%8.8x", (unsigned int) flag); + break; + } +} + +static void SDLTest_PrintModState(char *text, size_t maxlen, SDL_Keymod keymod) +{ + const SDL_Keymod kmod_flags[] = { + SDL_KMOD_LSHIFT, + SDL_KMOD_RSHIFT, + SDL_KMOD_LCTRL, + SDL_KMOD_RCTRL, + SDL_KMOD_LALT, + SDL_KMOD_RALT, + SDL_KMOD_LGUI, + SDL_KMOD_RGUI, + SDL_KMOD_NUM, + SDL_KMOD_CAPS, + SDL_KMOD_MODE, + SDL_KMOD_SCROLL + }; + + int i; + int count = 0; + for (i = 0; i < SDL_arraysize(kmod_flags); ++i) { + const SDL_Keymod flag = kmod_flags[i]; + if ((keymod & flag) == flag) { + if (count > 0) { + SDL_snprintfcat(text, maxlen, " | "); + } + SDLTest_PrintModStateFlag(text, maxlen, flag); + ++count; + } + } +} + static void SDLTest_PrintButtonMask(char *text, size_t maxlen, Uint32 flags) { int i; @@ -2663,6 +2739,19 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; + /* Keyboard */ + + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDLTest_DrawString(renderer, 0, textY, "-- Keyboard --"); + textY += lineHeight; + + SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255); + + (void)SDL_snprintf(text, sizeof(text), "SDL_GetModState: "); + SDLTest_PrintModState(text, sizeof(text), SDL_GetModState()); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + if (usedHeight) { *usedHeight = textY; } From 3817f5126e67e5f2f2b5c7e0196d42c27e7fdfd0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 28 Nov 2023 12:24:33 -0500 Subject: [PATCH 446/725] cocoa: Use `-[NSApplicationDelegate applicationSupportsSecureRestorableState]`. This prevents warnings at startup on macOS Sonoma (14.0). (cherry picked from commit 7d25a443c45450287e0a3ec5c1eb0e417647070e) --- src/video/cocoa/SDL_cocoaevents.m | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 3674965c8b56e..7673d226d83a3 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -133,6 +133,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; +- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app; @end @implementation SDLAppDelegate : NSObject @@ -319,6 +320,22 @@ - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEv SDL_SendDropComplete(NULL); } +- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app +{ + // This just tells Cocoa that we didn't do any custom save state magic for the app, + // so the system is safe to use NSSecureCoding internally, instead of using unencrypted + // save states for backwards compatibility. If we don't return YES here, we'll get a + // warning on the console at startup: + // + // ``` + // WARNING: Secure coding is not enabled for restorable state! Enable secure coding by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState: and returning YES. + // ``` + // + // More-detailed explanation: + // https://stackoverflow.com/questions/77283578/sonoma-and-nsapplicationdelegate-applicationsupportssecurerestorablestate/77320845#77320845 + return YES; +} + @end static SDLAppDelegate *appDelegate = nil; From dd984dcd9f89c88e2dd96769d2d837af90be7e70 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 28 Nov 2023 09:54:35 -0800 Subject: [PATCH 447/725] Removed HIDAPI controller mappings These are already provided internally by SDL --- src/joystick/SDL_gamepad_db.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 4253e498f3914..6496e03304237 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -622,7 +622,6 @@ 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,", - "030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,", "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,", @@ -805,7 +804,6 @@ static const char *s_GamepadMappings[] = { "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,sdk>=:29,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b2,y:b17,sdk<=:28,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", /* Extremely slow in Bluetooth mode on Android */ "050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", - "030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,", "050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", From 571e9796b9c023c412a79f763c59708f9905974e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 28 Nov 2023 10:07:06 -0800 Subject: [PATCH 448/725] Fixed the GameCube HIDAPI controller mapping Fixes https://github.com/libsdl-org/SDL/issues/8617 Closes https://github.com/libsdl-org/SDL/pull/8623 Closes https://github.com/libsdl-org/SDL/pull/7930 --- src/joystick/SDL_gamepad.c | 2 +- src/joystick/hidapi/SDL_hidapi_gamecube.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index d190aac80bda7..ec1120db71907 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -705,7 +705,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid (product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 || product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2))) { /* GameCube driver has 12 buttons and 6 axes */ - SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b2,y:b3,", sizeof(mapping_string)); } else if (vendor == USB_VENDOR_NINTENDO && (guid.data[15] == k_eSwitchDeviceInfoControllerType_HVCLeft || guid.data[15] == k_eSwitchDeviceInfoControllerType_HVCRight || diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index e52fbf9dc05bf..9b8f97c179bb6 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -263,8 +263,8 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device joystick, \ axis, axis_value); READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0) - READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 0) - READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 1) + READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1) + READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0) READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1) READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) @@ -317,9 +317,9 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device button, \ (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED); READ_BUTTON(1, 0x01, 0) /* A */ - READ_BUTTON(1, 0x04, 1) /* B */ + READ_BUTTON(1, 0x02, 1) /* B */ + READ_BUTTON(1, 0x04, 2) /* X */ READ_BUTTON(1, 0x08, 3) /* Y */ - READ_BUTTON(1, 0x02, 2) /* X */ READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */ READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */ READ_BUTTON(1, 0x40, 6) /* DPAD_DOWN */ @@ -363,7 +363,7 @@ static SDL_bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device) /* Read input packet */ while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) { #ifdef DEBUG_GAMECUBE_PROTOCOL - // HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size); + HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size); #endif if (ctx->pc_mode) { HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size); From 08c6ac1b16eae832a2e01a5e257b2c8eafa154a1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 28 Nov 2023 13:07:56 -0500 Subject: [PATCH 449/725] test: SDLTest_PrintEvent now reports key event mod state. (cherry picked from commit d42fa25a9e850ca9a9c9c0879ca7fdee00c136d1) --- src/test/SDL_test_common.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 8c4e0749b96cd..efc7e6bef234a 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1746,19 +1746,24 @@ static void SDLTest_PrintEvent(const SDL_Event *event) SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " occluded", event->window.windowID); break; case SDL_EVENT_KEY_DOWN: - SDL_Log("SDL EVENT: Keyboard: key pressed in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s", - event->key.windowID, - event->key.keysym.scancode, - SDL_GetScancodeName(event->key.keysym.scancode), - event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym)); - break; - case SDL_EVENT_KEY_UP: - SDL_Log("SDL EVENT: Keyboard: key released in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s", + case SDL_EVENT_KEY_UP: { + char modstr[64]; + if (event->key.keysym.mod) { + modstr[0] = '\0'; + SDLTest_PrintModState(modstr, sizeof (modstr), event->key.keysym.mod); + } else { + SDL_strlcpy(modstr, "NONE", sizeof (modstr)); + } + + SDL_Log("SDL EVENT: Keyboard: key %s in window %" SDL_PRIu32 ": scancode 0x%08X = %s, keycode 0x%08" SDL_PRIX32 " = %s, mods = %s", + (event->type == SDL_EVENT_KEY_DOWN) ? "pressed" : "released", event->key.windowID, event->key.keysym.scancode, SDL_GetScancodeName(event->key.keysym.scancode), - event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym)); + event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym), + modstr); break; + } case SDL_EVENT_TEXT_EDITING: SDL_Log("SDL EVENT: Keyboard: text editing \"%s\" in window %" SDL_PRIu32, event->edit.text, event->edit.windowID); From 7e86b6aef2b16e08a21a03948b6e199e9b4a1ffa Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Wed, 22 Nov 2023 15:44:53 +0200 Subject: [PATCH 450/725] Win32: Fix keymap for keyboard layouts that can print UTF-16 surrogates and ligatures Old implementation with `MapVirtualKey(..., MAPVK_VK_TO_CHAR) & 0x7FFFF` simply returned `A`..`Z` for VK_A..VK_Z and completely useless (`WCH_LGTR 0xF002` without high-order bit) in case of ligature. See https://kbdlayout.info/features/ligatures for a list of affected keyboard layouts. More info on `MAPVK_VK_TO_CHAR`: https://stackoverflow.com/a/72464584/1795050 --- src/video/windows/SDL_windowskeyboard.c | 44 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 7f09c32ec5645..06396c603d611 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -44,9 +44,6 @@ static SDL_bool IME_IsTextInputShown(SDL_VideoData *videodata); #ifndef MAPVK_VSC_TO_VK #define MAPVK_VSC_TO_VK 1 #endif -#ifndef MAPVK_VK_TO_CHAR -#define MAPVK_VK_TO_CHAR 2 -#endif /* Alphabetic scancodes for PC keyboards */ void WIN_InitKeyboard(SDL_VideoDevice *_this) @@ -120,6 +117,7 @@ void WIN_UpdateKeymap(SDL_bool send_event) SDL_Keycode keymap[SDL_NUM_SCANCODES]; SDL_GetDefaultKeymap(keymap); + WIN_ResetDeadKeys(); for (i = 0; i < SDL_arraysize(windows_scancode_table); i++) { int vk; @@ -130,20 +128,44 @@ void WIN_UpdateKeymap(SDL_bool send_event) } /* If this key is one of the non-mappable keys, ignore it */ - /* Uncomment the second part re-enable the behavior of not mapping the "`"(grave) key to the users actual keyboard layout */ - if ((keymap[scancode] & SDLK_SCANCODE_MASK) /*|| scancode == SDL_SCANCODE_GRAVE*/) { + /* Uncomment the third part to re-enable the behavior of not mapping the "`"(grave) key to the users actual keyboard layout */ + if ((keymap[scancode] & SDLK_SCANCODE_MASK) || scancode == SDL_SCANCODE_DELETE /*|| scancode == SDL_SCANCODE_GRAVE*/) { continue; } vk = MapVirtualKey(i, MAPVK_VSC_TO_VK); - if (vk) { - int ch = (MapVirtualKey(vk, MAPVK_VK_TO_CHAR) & 0x7FFF); + if (!vk) { + continue; + } + + /* Always map VK_A..VK_Z to SDLK_a..SDLK_z codes. + * This was behavior with MapVirtualKey(MAPVK_VK_TO_CHAR). */ + //if (vk >= 'A' && vk <= 'Z') { + // keymap[scancode] = SDLK_a + (vk - 'A'); + //} else { + { + BYTE keyboardState[256] = { 0 }; + WCHAR buffer[16] = { 0 }; + Uint32 *ch = 0; + int result = ToUnicode(vk, i, keyboardState, buffer, 16, 0); + buffer[SDL_abs(result) + 1] = 0; + + /* Convert UTF-16 to UTF-32 code points */ + ch = (Uint32 *)SDL_iconv_string("UTF-32LE", "UTF-16LE", (const char *)buffer, (SDL_abs(result) + 1) * sizeof(WCHAR)); if (ch) { - if (ch >= 'A' && ch <= 'Z') { - keymap[scancode] = SDLK_a + (ch - 'A'); + if (ch[0] != 0 && ch[1] != 0) { + /* We have several UTF-32 code points on a single key press. + * Cannot fit into single SDL_Keycode in keymap. + * See https://kbdlayout.info/features/ligatures */ + keymap[scancode] = 0xfffd; /* U+FFFD REPLACEMENT CHARACTER */ } else { - keymap[scancode] = ch; + keymap[scancode] = ch[0]; } + SDL_free(ch); + } + + if (result < 0) { + WIN_ResetDeadKeys(); } } } @@ -186,7 +208,7 @@ void WIN_ResetDeadKeys() } for (i = 0; i < 5; i++) { - result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)buffer, 16, 0); + result = ToUnicode(keycode, scancode, keyboardState, buffer, 16, 0); if (result > 0) { /* success */ return; From 6b28065e9e65b9d49b6fcba610ae2075a603066f Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Mon, 27 Nov 2023 14:27:51 +0200 Subject: [PATCH 451/725] Reformat Win32 scan code table --- src/events/scancodes_windows.h | 157 +++++++++++++++++++++++++++------ 1 file changed, 130 insertions(+), 27 deletions(-) diff --git a/src/events/scancodes_windows.h b/src/events/scancodes_windows.h index 91a3dc385c228..3a65b8c16cdfa 100644 --- a/src/events/scancodes_windows.h +++ b/src/events/scancodes_windows.h @@ -24,32 +24,135 @@ /* derived from Microsoft scan code document, http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc */ /* *INDENT-OFF* */ /* clang-format off */ -static const SDL_Scancode windows_scancode_table[] = -{ - /* 0 1 2 3 4 5 6 7 */ - /* 8 9 A B C D E F */ - SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6, /* 0 */ - SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9, SDL_SCANCODE_0, SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, SDL_SCANCODE_BACKSPACE, SDL_SCANCODE_TAB, /* 0 */ - - SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_E, SDL_SCANCODE_R, SDL_SCANCODE_T, SDL_SCANCODE_Y, SDL_SCANCODE_U, SDL_SCANCODE_I, /* 1 */ - SDL_SCANCODE_O, SDL_SCANCODE_P, SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RETURN, SDL_SCANCODE_LCTRL, SDL_SCANCODE_A, SDL_SCANCODE_S, /* 1 */ - - SDL_SCANCODE_D, SDL_SCANCODE_F, SDL_SCANCODE_G, SDL_SCANCODE_H, SDL_SCANCODE_J, SDL_SCANCODE_K, SDL_SCANCODE_L, SDL_SCANCODE_SEMICOLON, /* 2 */ - SDL_SCANCODE_APOSTROPHE, SDL_SCANCODE_GRAVE, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_BACKSLASH, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_C, SDL_SCANCODE_V, /* 2 */ - - SDL_SCANCODE_B, SDL_SCANCODE_N, SDL_SCANCODE_M, SDL_SCANCODE_COMMA, SDL_SCANCODE_PERIOD, SDL_SCANCODE_SLASH, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_PRINTSCREEN,/* 3 */ - SDL_SCANCODE_LALT, SDL_SCANCODE_SPACE, SDL_SCANCODE_CAPSLOCK, SDL_SCANCODE_F1, SDL_SCANCODE_F2, SDL_SCANCODE_F3, SDL_SCANCODE_F4, SDL_SCANCODE_F5, /* 3 */ - - SDL_SCANCODE_F6, SDL_SCANCODE_F7, SDL_SCANCODE_F8, SDL_SCANCODE_F9, SDL_SCANCODE_F10, SDL_SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_SCROLLLOCK, SDL_SCANCODE_HOME, /* 4 */ - SDL_SCANCODE_UP, SDL_SCANCODE_PAGEUP, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_LEFT, SDL_SCANCODE_KP_5, SDL_SCANCODE_RIGHT, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_END, /* 4 */ - - SDL_SCANCODE_DOWN, SDL_SCANCODE_PAGEDOWN, SDL_SCANCODE_INSERT, SDL_SCANCODE_DELETE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_NONUSBACKSLASH,SDL_SCANCODE_F11, /* 5 */ - SDL_SCANCODE_F12, SDL_SCANCODE_PAUSE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_LGUI, SDL_SCANCODE_RGUI, SDL_SCANCODE_APPLICATION, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 5 */ - - SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_F16, /* 6 */ - SDL_SCANCODE_F17, SDL_SCANCODE_F18, SDL_SCANCODE_F19, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 6 */ - - SDL_SCANCODE_INTERNATIONAL2, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL1, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 7 */ - SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL4, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL5, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL3, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN /* 7 */ +static const SDL_Scancode windows_scancode_table[] = +{ + /*0x00*/ SDL_SCANCODE_UNKNOWN, + /*0x01*/ SDL_SCANCODE_ESCAPE, + /*0x02*/ SDL_SCANCODE_1, + /*0x03*/ SDL_SCANCODE_2, + /*0x04*/ SDL_SCANCODE_3, + /*0x05*/ SDL_SCANCODE_4, + /*0x06*/ SDL_SCANCODE_5, + /*0x07*/ SDL_SCANCODE_6, + /*0x08*/ SDL_SCANCODE_7, + /*0x09*/ SDL_SCANCODE_8, + /*0x0a*/ SDL_SCANCODE_9, + /*0x0b*/ SDL_SCANCODE_0, + /*0x0c*/ SDL_SCANCODE_MINUS, + /*0x0d*/ SDL_SCANCODE_EQUALS, + /*0x0e*/ SDL_SCANCODE_BACKSPACE, + /*0x0f*/ SDL_SCANCODE_TAB, + /*0x10*/ SDL_SCANCODE_Q, + /*0x11*/ SDL_SCANCODE_W, + /*0x12*/ SDL_SCANCODE_E, + /*0x13*/ SDL_SCANCODE_R, + /*0x14*/ SDL_SCANCODE_T, + /*0x15*/ SDL_SCANCODE_Y, + /*0x16*/ SDL_SCANCODE_U, + /*0x17*/ SDL_SCANCODE_I, + /*0x18*/ SDL_SCANCODE_O, + /*0x19*/ SDL_SCANCODE_P, + /*0x1a*/ SDL_SCANCODE_LEFTBRACKET, + /*0x1b*/ SDL_SCANCODE_RIGHTBRACKET, + /*0x1c*/ SDL_SCANCODE_RETURN, + /*0x1d*/ SDL_SCANCODE_LCTRL, + /*0x1e*/ SDL_SCANCODE_A, + /*0x1f*/ SDL_SCANCODE_S, + /*0x20*/ SDL_SCANCODE_D, + /*0x21*/ SDL_SCANCODE_F, + /*0x22*/ SDL_SCANCODE_G, + /*0x23*/ SDL_SCANCODE_H, + /*0x24*/ SDL_SCANCODE_J, + /*0x25*/ SDL_SCANCODE_K, + /*0x26*/ SDL_SCANCODE_L, + /*0x27*/ SDL_SCANCODE_SEMICOLON, + /*0x28*/ SDL_SCANCODE_APOSTROPHE, + /*0x29*/ SDL_SCANCODE_GRAVE, + /*0x2a*/ SDL_SCANCODE_LSHIFT, + /*0x2b*/ SDL_SCANCODE_BACKSLASH, + /*0x2c*/ SDL_SCANCODE_Z, + /*0x2d*/ SDL_SCANCODE_X, + /*0x2e*/ SDL_SCANCODE_C, + /*0x2f*/ SDL_SCANCODE_V, + /*0x30*/ SDL_SCANCODE_B, + /*0x31*/ SDL_SCANCODE_N, + /*0x32*/ SDL_SCANCODE_M, + /*0x33*/ SDL_SCANCODE_COMMA, + /*0x34*/ SDL_SCANCODE_PERIOD, + /*0x35*/ SDL_SCANCODE_SLASH, + /*0x36*/ SDL_SCANCODE_RSHIFT, + /*0x37*/ SDL_SCANCODE_PRINTSCREEN, + /*0x38*/ SDL_SCANCODE_LALT, + /*0x39*/ SDL_SCANCODE_SPACE, + /*0x3a*/ SDL_SCANCODE_CAPSLOCK, + /*0x3b*/ SDL_SCANCODE_F1, + /*0x3c*/ SDL_SCANCODE_F2, + /*0x3d*/ SDL_SCANCODE_F3, + /*0x3e*/ SDL_SCANCODE_F4, + /*0x3f*/ SDL_SCANCODE_F5, + /*0x40*/ SDL_SCANCODE_F6, + /*0x41*/ SDL_SCANCODE_F7, + /*0x42*/ SDL_SCANCODE_F8, + /*0x43*/ SDL_SCANCODE_F9, + /*0x44*/ SDL_SCANCODE_F10, + /*0x45*/ SDL_SCANCODE_NUMLOCKCLEAR, + /*0x46*/ SDL_SCANCODE_SCROLLLOCK, + /*0x47*/ SDL_SCANCODE_HOME, + /*0x48*/ SDL_SCANCODE_UP, + /*0x49*/ SDL_SCANCODE_PAGEUP, + /*0x4a*/ SDL_SCANCODE_KP_MINUS, + /*0x4b*/ SDL_SCANCODE_LEFT, + /*0x4c*/ SDL_SCANCODE_KP_5, + /*0x4d*/ SDL_SCANCODE_RIGHT, + /*0x4e*/ SDL_SCANCODE_KP_PLUS, + /*0x4f*/ SDL_SCANCODE_END, + /*0x50*/ SDL_SCANCODE_DOWN, + /*0x51*/ SDL_SCANCODE_PAGEDOWN, + /*0x52*/ SDL_SCANCODE_INSERT, + /*0x53*/ SDL_SCANCODE_DELETE, + /*0x54*/ SDL_SCANCODE_UNKNOWN, + /*0x55*/ SDL_SCANCODE_UNKNOWN, + /*0x56*/ SDL_SCANCODE_NONUSBACKSLASH, + /*0x57*/ SDL_SCANCODE_F11, + /*0x58*/ SDL_SCANCODE_F12, + /*0x59*/ SDL_SCANCODE_PAUSE, + /*0x5a*/ SDL_SCANCODE_UNKNOWN, + /*0x5b*/ SDL_SCANCODE_LGUI, + /*0x5c*/ SDL_SCANCODE_RGUI, + /*0x5d*/ SDL_SCANCODE_APPLICATION, + /*0x5e*/ SDL_SCANCODE_UNKNOWN, + /*0x5f*/ SDL_SCANCODE_UNKNOWN, + /*0x60*/ SDL_SCANCODE_UNKNOWN, + /*0x61*/ SDL_SCANCODE_UNKNOWN, + /*0x62*/ SDL_SCANCODE_UNKNOWN, + /*0x63*/ SDL_SCANCODE_UNKNOWN, + /*0x64*/ SDL_SCANCODE_F13, + /*0x65*/ SDL_SCANCODE_F14, + /*0x66*/ SDL_SCANCODE_F15, + /*0x67*/ SDL_SCANCODE_F16, + /*0x68*/ SDL_SCANCODE_F17, + /*0x69*/ SDL_SCANCODE_F18, + /*0x6a*/ SDL_SCANCODE_F19, + /*0x6b*/ SDL_SCANCODE_UNKNOWN, + /*0x6c*/ SDL_SCANCODE_UNKNOWN, + /*0x6d*/ SDL_SCANCODE_UNKNOWN, + /*0x6e*/ SDL_SCANCODE_UNKNOWN, + /*0x6f*/ SDL_SCANCODE_UNKNOWN, + /*0x70*/ SDL_SCANCODE_INTERNATIONAL2, + /*0x71*/ SDL_SCANCODE_UNKNOWN, + /*0x72*/ SDL_SCANCODE_UNKNOWN, + /*0x73*/ SDL_SCANCODE_INTERNATIONAL1, + /*0x74*/ SDL_SCANCODE_UNKNOWN, + /*0x75*/ SDL_SCANCODE_UNKNOWN, + /*0x76*/ SDL_SCANCODE_UNKNOWN, + /*0x77*/ SDL_SCANCODE_UNKNOWN, + /*0x78*/ SDL_SCANCODE_UNKNOWN, + /*0x79*/ SDL_SCANCODE_INTERNATIONAL4, + /*0x7a*/ SDL_SCANCODE_UNKNOWN, + /*0x7b*/ SDL_SCANCODE_INTERNATIONAL5, + /*0x7c*/ SDL_SCANCODE_UNKNOWN, + /*0x7d*/ SDL_SCANCODE_INTERNATIONAL3, + /*0x7e*/ SDL_SCANCODE_UNKNOWN, + /*0x7f*/ SDL_SCANCODE_UNKNOWN }; /* *INDENT-ON* */ /* clang-format on */ From acc5bb89f8b526e6d72c76cfdc78eff1a9acc505 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Tue, 21 Nov 2023 14:07:18 +0200 Subject: [PATCH 452/725] [Win32] Better keyboard button mapping to SDL scan codes Using official mappings from the Microsoft docs: https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#scan-codes --- VisualC-GDK/SDL/SDL.vcxproj | 1 - VisualC-GDK/SDL/SDL.vcxproj.filters | 3 - VisualC/SDL/SDL.vcxproj | 1 - VisualC/SDL/SDL.vcxproj.filters | 3 - src/events/scancodes_windows.h | 188 +++++++++++++++++++---- src/video/windows/SDL_vkeys.h | 74 --------- src/video/windows/SDL_windowsevents.c | 211 +++----------------------- 7 files changed, 181 insertions(+), 300 deletions(-) delete mode 100644 src/video/windows/SDL_vkeys.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 6cae7db9582cd..2c5b186f8965f 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -526,7 +526,6 @@ - diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 5b5c77da102e2..c1f85c5a83df3 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -627,9 +627,6 @@ video\yuv2rgb - - video\windows - video\windows diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 528a3fba58ee5..e547e4256ba94 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -454,7 +454,6 @@ - diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 8a79f83f0ca79..5f1d2836f06de 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -621,9 +621,6 @@ video\yuv2rgb - - video\windows - video\windows diff --git a/src/events/scancodes_windows.h b/src/events/scancodes_windows.h index 3a65b8c16cdfa..697d2f28ff256 100644 --- a/src/events/scancodes_windows.h +++ b/src/events/scancodes_windows.h @@ -20,12 +20,12 @@ */ #include "SDL_internal.h" -/* Windows scancode to SDL scancode mapping table */ -/* derived from Microsoft scan code document, http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc */ +/* + * Windows scancode to SDL scancode mapping table + * https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#scan-codes */ /* *INDENT-OFF* */ /* clang-format off */ -static const SDL_Scancode windows_scancode_table[] = -{ +static const SDL_Scancode windows_scancode_table[] = { /*0x00*/ SDL_SCANCODE_UNKNOWN, /*0x01*/ SDL_SCANCODE_ESCAPE, /*0x02*/ SDL_SCANCODE_1, @@ -81,7 +81,7 @@ static const SDL_Scancode windows_scancode_table[] = /*0x34*/ SDL_SCANCODE_PERIOD, /*0x35*/ SDL_SCANCODE_SLASH, /*0x36*/ SDL_SCANCODE_RSHIFT, - /*0x37*/ SDL_SCANCODE_PRINTSCREEN, + /*0x37*/ SDL_SCANCODE_KP_MULTIPLY, /*0x38*/ SDL_SCANCODE_LALT, /*0x39*/ SDL_SCANCODE_SPACE, /*0x3a*/ SDL_SCANCODE_CAPSLOCK, @@ -97,29 +97,29 @@ static const SDL_Scancode windows_scancode_table[] = /*0x44*/ SDL_SCANCODE_F10, /*0x45*/ SDL_SCANCODE_NUMLOCKCLEAR, /*0x46*/ SDL_SCANCODE_SCROLLLOCK, - /*0x47*/ SDL_SCANCODE_HOME, - /*0x48*/ SDL_SCANCODE_UP, - /*0x49*/ SDL_SCANCODE_PAGEUP, + /*0x47*/ SDL_SCANCODE_KP_7, + /*0x48*/ SDL_SCANCODE_KP_8, + /*0x49*/ SDL_SCANCODE_KP_9, /*0x4a*/ SDL_SCANCODE_KP_MINUS, - /*0x4b*/ SDL_SCANCODE_LEFT, + /*0x4b*/ SDL_SCANCODE_KP_4, /*0x4c*/ SDL_SCANCODE_KP_5, - /*0x4d*/ SDL_SCANCODE_RIGHT, + /*0x4d*/ SDL_SCANCODE_KP_6, /*0x4e*/ SDL_SCANCODE_KP_PLUS, - /*0x4f*/ SDL_SCANCODE_END, - /*0x50*/ SDL_SCANCODE_DOWN, - /*0x51*/ SDL_SCANCODE_PAGEDOWN, - /*0x52*/ SDL_SCANCODE_INSERT, - /*0x53*/ SDL_SCANCODE_DELETE, + /*0x4f*/ SDL_SCANCODE_KP_1, + /*0x50*/ SDL_SCANCODE_KP_2, + /*0x51*/ SDL_SCANCODE_KP_3, + /*0x52*/ SDL_SCANCODE_KP_0, + /*0x53*/ SDL_SCANCODE_KP_PERIOD, /*0x54*/ SDL_SCANCODE_UNKNOWN, /*0x55*/ SDL_SCANCODE_UNKNOWN, /*0x56*/ SDL_SCANCODE_NONUSBACKSLASH, /*0x57*/ SDL_SCANCODE_F11, /*0x58*/ SDL_SCANCODE_F12, - /*0x59*/ SDL_SCANCODE_PAUSE, + /*0x59*/ SDL_SCANCODE_KP_EQUALS, /*0x5a*/ SDL_SCANCODE_UNKNOWN, - /*0x5b*/ SDL_SCANCODE_LGUI, - /*0x5c*/ SDL_SCANCODE_RGUI, - /*0x5d*/ SDL_SCANCODE_APPLICATION, + /*0x5b*/ SDL_SCANCODE_UNKNOWN, + /*0x5c*/ SDL_SCANCODE_INTERNATIONAL6, + /*0x5d*/ SDL_SCANCODE_UNKNOWN, /*0x5e*/ SDL_SCANCODE_UNKNOWN, /*0x5f*/ SDL_SCANCODE_UNKNOWN, /*0x60*/ SDL_SCANCODE_UNKNOWN, @@ -133,26 +133,154 @@ static const SDL_Scancode windows_scancode_table[] = /*0x68*/ SDL_SCANCODE_F17, /*0x69*/ SDL_SCANCODE_F18, /*0x6a*/ SDL_SCANCODE_F19, - /*0x6b*/ SDL_SCANCODE_UNKNOWN, - /*0x6c*/ SDL_SCANCODE_UNKNOWN, - /*0x6d*/ SDL_SCANCODE_UNKNOWN, - /*0x6e*/ SDL_SCANCODE_UNKNOWN, + /*0x6b*/ SDL_SCANCODE_F20, + /*0x6c*/ SDL_SCANCODE_F21, + /*0x6d*/ SDL_SCANCODE_F22, + /*0x6e*/ SDL_SCANCODE_F23, /*0x6f*/ SDL_SCANCODE_UNKNOWN, /*0x70*/ SDL_SCANCODE_INTERNATIONAL2, - /*0x71*/ SDL_SCANCODE_UNKNOWN, - /*0x72*/ SDL_SCANCODE_UNKNOWN, + /*0x71*/ SDL_SCANCODE_LANG2, + /*0x72*/ SDL_SCANCODE_LANG1, /*0x73*/ SDL_SCANCODE_INTERNATIONAL1, /*0x74*/ SDL_SCANCODE_UNKNOWN, /*0x75*/ SDL_SCANCODE_UNKNOWN, - /*0x76*/ SDL_SCANCODE_UNKNOWN, - /*0x77*/ SDL_SCANCODE_UNKNOWN, - /*0x78*/ SDL_SCANCODE_UNKNOWN, + /*0x76*/ SDL_SCANCODE_F24, + /*0x77*/ SDL_SCANCODE_LANG4, + /*0x78*/ SDL_SCANCODE_LANG3, /*0x79*/ SDL_SCANCODE_INTERNATIONAL4, /*0x7a*/ SDL_SCANCODE_UNKNOWN, /*0x7b*/ SDL_SCANCODE_INTERNATIONAL5, /*0x7c*/ SDL_SCANCODE_UNKNOWN, /*0x7d*/ SDL_SCANCODE_INTERNATIONAL3, - /*0x7e*/ SDL_SCANCODE_UNKNOWN, - /*0x7f*/ SDL_SCANCODE_UNKNOWN + /*0x7e*/ SDL_SCANCODE_KP_COMMA, + /*0x7f*/ SDL_SCANCODE_UNKNOWN, + /*0xe000*/ SDL_SCANCODE_UNKNOWN, + /*0xe001*/ SDL_SCANCODE_UNKNOWN, + /*0xe002*/ SDL_SCANCODE_UNKNOWN, + /*0xe003*/ SDL_SCANCODE_UNKNOWN, + /*0xe004*/ SDL_SCANCODE_UNKNOWN, + /*0xe005*/ SDL_SCANCODE_UNKNOWN, + /*0xe006*/ SDL_SCANCODE_UNKNOWN, + /*0xe007*/ SDL_SCANCODE_UNKNOWN, + /*0xe008*/ SDL_SCANCODE_UNKNOWN, + /*0xe009*/ SDL_SCANCODE_UNKNOWN, + /*0xe00a*/ SDL_SCANCODE_UNKNOWN, + /*0xe00b*/ SDL_SCANCODE_UNKNOWN, + /*0xe00c*/ SDL_SCANCODE_UNKNOWN, + /*0xe00d*/ SDL_SCANCODE_UNKNOWN, + /*0xe00e*/ SDL_SCANCODE_UNKNOWN, + /*0xe00f*/ SDL_SCANCODE_UNKNOWN, + /*0xe010*/ SDL_SCANCODE_AUDIOPREV, + /*0xe011*/ SDL_SCANCODE_UNKNOWN, + /*0xe012*/ SDL_SCANCODE_UNKNOWN, + /*0xe013*/ SDL_SCANCODE_UNKNOWN, + /*0xe014*/ SDL_SCANCODE_UNKNOWN, + /*0xe015*/ SDL_SCANCODE_UNKNOWN, + /*0xe016*/ SDL_SCANCODE_UNKNOWN, + /*0xe017*/ SDL_SCANCODE_UNKNOWN, + /*0xe018*/ SDL_SCANCODE_UNKNOWN, + /*0xe019*/ SDL_SCANCODE_AUDIONEXT, + /*0xe01a*/ SDL_SCANCODE_UNKNOWN, + /*0xe01b*/ SDL_SCANCODE_UNKNOWN, + /*0xe01c*/ SDL_SCANCODE_KP_ENTER, + /*0xe01d*/ SDL_SCANCODE_RCTRL, + /*0xe01e*/ SDL_SCANCODE_UNKNOWN, + /*0xe01f*/ SDL_SCANCODE_UNKNOWN, + /*0xe020*/ SDL_SCANCODE_MUTE, + /*0xe021*/ SDL_SCANCODE_CALCULATOR, + /*0xe022*/ SDL_SCANCODE_AUDIOPLAY, + /*0xe023*/ SDL_SCANCODE_UNKNOWN, + /*0xe024*/ SDL_SCANCODE_AUDIOSTOP, + /*0xe025*/ SDL_SCANCODE_UNKNOWN, + /*0xe026*/ SDL_SCANCODE_UNKNOWN, + /*0xe027*/ SDL_SCANCODE_UNKNOWN, + /*0xe028*/ SDL_SCANCODE_UNKNOWN, + /*0xe029*/ SDL_SCANCODE_UNKNOWN, + /*0xe02a*/ SDL_SCANCODE_UNKNOWN, + /*0xe02b*/ SDL_SCANCODE_UNKNOWN, + /*0xe02c*/ SDL_SCANCODE_UNKNOWN, + /*0xe02d*/ SDL_SCANCODE_UNKNOWN, + /*0xe02e*/ SDL_SCANCODE_VOLUMEDOWN, + /*0xe02f*/ SDL_SCANCODE_UNKNOWN, + /*0xe030*/ SDL_SCANCODE_VOLUMEUP, + /*0xe031*/ SDL_SCANCODE_UNKNOWN, + /*0xe032*/ SDL_SCANCODE_AC_HOME, + /*0xe033*/ SDL_SCANCODE_UNKNOWN, + /*0xe034*/ SDL_SCANCODE_UNKNOWN, + /*0xe035*/ SDL_SCANCODE_KP_DIVIDE, + /*0xe036*/ SDL_SCANCODE_UNKNOWN, + /*0xe037*/ SDL_SCANCODE_PRINTSCREEN, + /*0xe038*/ SDL_SCANCODE_RALT, + /*0xe039*/ SDL_SCANCODE_UNKNOWN, + /*0xe03a*/ SDL_SCANCODE_UNKNOWN, + /*0xe03b*/ SDL_SCANCODE_UNKNOWN, + /*0xe03c*/ SDL_SCANCODE_UNKNOWN, + /*0xe03d*/ SDL_SCANCODE_UNKNOWN, + /*0xe03e*/ SDL_SCANCODE_UNKNOWN, + /*0xe03f*/ SDL_SCANCODE_UNKNOWN, + /*0xe040*/ SDL_SCANCODE_UNKNOWN, + /*0xe041*/ SDL_SCANCODE_UNKNOWN, + /*0xe042*/ SDL_SCANCODE_UNKNOWN, + /*0xe043*/ SDL_SCANCODE_UNKNOWN, + /*0xe044*/ SDL_SCANCODE_UNKNOWN, + /*0xe045*/ SDL_SCANCODE_NUMLOCKCLEAR, + /*0xe046*/ SDL_SCANCODE_PAUSE, + /*0xe047*/ SDL_SCANCODE_HOME, + /*0xe048*/ SDL_SCANCODE_UP, + /*0xe049*/ SDL_SCANCODE_PAGEUP, + /*0xe04a*/ SDL_SCANCODE_LEFT, + /*0xe04b*/ SDL_SCANCODE_UNKNOWN, + /*0xe04c*/ SDL_SCANCODE_UNKNOWN, + /*0xe04d*/ SDL_SCANCODE_RIGHT, + /*0xe04e*/ SDL_SCANCODE_UNKNOWN, + /*0xe04f*/ SDL_SCANCODE_END, + /*0xe050*/ SDL_SCANCODE_DOWN, + /*0xe051*/ SDL_SCANCODE_PAGEDOWN, + /*0xe052*/ SDL_SCANCODE_INSERT, + /*0xe053*/ SDL_SCANCODE_DELETE, + /*0xe054*/ SDL_SCANCODE_UNKNOWN, + /*0xe055*/ SDL_SCANCODE_UNKNOWN, + /*0xe056*/ SDL_SCANCODE_UNKNOWN, + /*0xe057*/ SDL_SCANCODE_UNKNOWN, + /*0xe058*/ SDL_SCANCODE_UNKNOWN, + /*0xe059*/ SDL_SCANCODE_UNKNOWN, + /*0xe05a*/ SDL_SCANCODE_UNKNOWN, + /*0xe05b*/ SDL_SCANCODE_LGUI, + /*0xe05c*/ SDL_SCANCODE_RGUI, + /*0xe05d*/ SDL_SCANCODE_APPLICATION, + /*0xe05e*/ SDL_SCANCODE_POWER, + /*0xe05f*/ SDL_SCANCODE_SLEEP, + /*0xe060*/ SDL_SCANCODE_UNKNOWN, + /*0xe061*/ SDL_SCANCODE_UNKNOWN, + /*0xe062*/ SDL_SCANCODE_UNKNOWN, + /*0xe063*/ SDL_SCANCODE_UNKNOWN, + /*0xe064*/ SDL_SCANCODE_UNKNOWN, + /*0xe065*/ SDL_SCANCODE_AC_SEARCH, + /*0xe066*/ SDL_SCANCODE_AC_BOOKMARKS, + /*0xe067*/ SDL_SCANCODE_AC_REFRESH, + /*0xe068*/ SDL_SCANCODE_AC_STOP, + /*0xe069*/ SDL_SCANCODE_AC_FORWARD, + /*0xe06a*/ SDL_SCANCODE_AC_BACK, + /*0xe06b*/ SDL_SCANCODE_COMPUTER, + /*0xe06c*/ SDL_SCANCODE_MAIL, + /*0xe06d*/ SDL_SCANCODE_MEDIASELECT, + /*0xe06e*/ SDL_SCANCODE_UNKNOWN, + /*0xe06f*/ SDL_SCANCODE_UNKNOWN, + /*0xe070*/ SDL_SCANCODE_UNKNOWN, + /*0xe071*/ SDL_SCANCODE_UNKNOWN, + /*0xe072*/ SDL_SCANCODE_UNKNOWN, + /*0xe073*/ SDL_SCANCODE_UNKNOWN, + /*0xe074*/ SDL_SCANCODE_UNKNOWN, + /*0xe075*/ SDL_SCANCODE_UNKNOWN, + /*0xe076*/ SDL_SCANCODE_UNKNOWN, + /*0xe077*/ SDL_SCANCODE_UNKNOWN, + /*0xe078*/ SDL_SCANCODE_UNKNOWN, + /*0xe079*/ SDL_SCANCODE_UNKNOWN, + /*0xe07a*/ SDL_SCANCODE_UNKNOWN, + /*0xe07b*/ SDL_SCANCODE_UNKNOWN, + /*0xe07c*/ SDL_SCANCODE_UNKNOWN, + /*0xe07d*/ SDL_SCANCODE_UNKNOWN, + /*0xe07e*/ SDL_SCANCODE_UNKNOWN, + /*0xe07f*/ SDL_SCANCODE_UNKNOWN }; /* *INDENT-ON* */ /* clang-format on */ diff --git a/src/video/windows/SDL_vkeys.h b/src/video/windows/SDL_vkeys.h deleted file mode 100644 index b15a39f09428f..0000000000000 --- a/src/video/windows/SDL_vkeys.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef VK_0 -#define VK_0 '0' -#define VK_1 '1' -#define VK_2 '2' -#define VK_3 '3' -#define VK_4 '4' -#define VK_5 '5' -#define VK_6 '6' -#define VK_7 '7' -#define VK_8 '8' -#define VK_9 '9' -#define VK_A 'A' -#define VK_B 'B' -#define VK_C 'C' -#define VK_D 'D' -#define VK_E 'E' -#define VK_F 'F' -#define VK_G 'G' -#define VK_H 'H' -#define VK_I 'I' -#define VK_J 'J' -#define VK_K 'K' -#define VK_L 'L' -#define VK_M 'M' -#define VK_N 'N' -#define VK_O 'O' -#define VK_P 'P' -#define VK_Q 'Q' -#define VK_R 'R' -#define VK_S 'S' -#define VK_T 'T' -#define VK_U 'U' -#define VK_V 'V' -#define VK_W 'W' -#define VK_X 'X' -#define VK_Y 'Y' -#define VK_Z 'Z' -#endif /* VK_0 */ - -/* These keys haven't been defined, but were experimentally determined */ -#define VK_SEMICOLON 0xBA -#define VK_EQUALS 0xBB -#define VK_COMMA 0xBC -#define VK_MINUS 0xBD -#define VK_PERIOD 0xBE -#define VK_SLASH 0xBF -#define VK_GRAVE 0xC0 -#define VK_LBRACKET 0xDB -#define VK_BACKSLASH 0xDC -#define VK_RBRACKET 0xDD -#define VK_APOSTROPHE 0xDE -#define VK_BACKTICK 0xDF -#define VK_OEM_102 0xE2 diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 5202955bf0543..d5381dd77cf0a 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -23,7 +23,6 @@ #ifdef SDL_VIDEO_DRIVER_WINDOWS #include "SDL_windowsvideo.h" -#include "SDL_vkeys.h" #include "../../events/SDL_events_c.h" #include "../../events/SDL_touch_c.h" #include "../../events/scancodes_windows.h" @@ -152,202 +151,38 @@ static Uint64 WIN_GetEventTimestamp() return timestamp; } -static SDL_Scancode VKeytoScancodeFallback(WPARAM vkey) -{ - switch (vkey) { - case VK_LEFT: - return SDL_SCANCODE_LEFT; - case VK_UP: - return SDL_SCANCODE_UP; - case VK_RIGHT: - return SDL_SCANCODE_RIGHT; - case VK_DOWN: - return SDL_SCANCODE_DOWN; - - default: - return SDL_SCANCODE_UNKNOWN; - } -} - -static SDL_Scancode VKeytoScancode(WPARAM vkey) -{ - switch (vkey) { - case VK_MODECHANGE: - return SDL_SCANCODE_MODE; - case VK_SELECT: - return SDL_SCANCODE_SELECT; - case VK_EXECUTE: - return SDL_SCANCODE_EXECUTE; - case VK_HELP: - return SDL_SCANCODE_HELP; - case VK_PAUSE: - return SDL_SCANCODE_PAUSE; - case VK_NUMLOCK: - return SDL_SCANCODE_NUMLOCKCLEAR; - - case VK_F13: - return SDL_SCANCODE_F13; - case VK_F14: - return SDL_SCANCODE_F14; - case VK_F15: - return SDL_SCANCODE_F15; - case VK_F16: - return SDL_SCANCODE_F16; - case VK_F17: - return SDL_SCANCODE_F17; - case VK_F18: - return SDL_SCANCODE_F18; - case VK_F19: - return SDL_SCANCODE_F19; - case VK_F20: - return SDL_SCANCODE_F20; - case VK_F21: - return SDL_SCANCODE_F21; - case VK_F22: - return SDL_SCANCODE_F22; - case VK_F23: - return SDL_SCANCODE_F23; - case VK_F24: - return SDL_SCANCODE_F24; - - case VK_OEM_NEC_EQUAL: - return SDL_SCANCODE_KP_EQUALS; - case VK_BROWSER_BACK: - return SDL_SCANCODE_AC_BACK; - case VK_BROWSER_FORWARD: - return SDL_SCANCODE_AC_FORWARD; - case VK_BROWSER_REFRESH: - return SDL_SCANCODE_AC_REFRESH; - case VK_BROWSER_STOP: - return SDL_SCANCODE_AC_STOP; - case VK_BROWSER_SEARCH: - return SDL_SCANCODE_AC_SEARCH; - case VK_BROWSER_FAVORITES: - return SDL_SCANCODE_AC_BOOKMARKS; - case VK_BROWSER_HOME: - return SDL_SCANCODE_AC_HOME; - case VK_VOLUME_MUTE: - return SDL_SCANCODE_MUTE; - case VK_VOLUME_DOWN: - return SDL_SCANCODE_VOLUMEDOWN; - case VK_VOLUME_UP: - return SDL_SCANCODE_VOLUMEUP; - - case VK_MEDIA_NEXT_TRACK: - return SDL_SCANCODE_AUDIONEXT; - case VK_MEDIA_PREV_TRACK: - return SDL_SCANCODE_AUDIOPREV; - case VK_MEDIA_STOP: - return SDL_SCANCODE_AUDIOSTOP; - case VK_MEDIA_PLAY_PAUSE: - return SDL_SCANCODE_AUDIOPLAY; - case VK_LAUNCH_MAIL: - return SDL_SCANCODE_MAIL; - case VK_LAUNCH_MEDIA_SELECT: - return SDL_SCANCODE_MEDIASELECT; - - case VK_OEM_102: - return SDL_SCANCODE_NONUSBACKSLASH; - - case VK_ATTN: - return SDL_SCANCODE_SYSREQ; - case VK_CRSEL: - return SDL_SCANCODE_CRSEL; - case VK_EXSEL: - return SDL_SCANCODE_EXSEL; - case VK_OEM_CLEAR: - return SDL_SCANCODE_CLEAR; - - case VK_LAUNCH_APP1: - return SDL_SCANCODE_APP1; - case VK_LAUNCH_APP2: - return SDL_SCANCODE_APP2; - - default: - return SDL_SCANCODE_UNKNOWN; - } -} - static SDL_Scancode WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam) { SDL_Scancode code; - int nScanCode = (lParam >> 16) & 0xFF; - SDL_bool bIsExtended = (lParam & (1 << 24)) != 0; + Uint8 index; + Uint16 keyFlags = HIWORD(lParam); + Uint16 scanCode = LOBYTE(keyFlags); - code = VKeytoScancode(wParam); + /* On-Screen Keyboard can send wrong scan codes with high-order bit set (key break code). + * Strip high-order bit. */ + scanCode &= ~0x80; - if (code == SDL_SCANCODE_UNKNOWN && nScanCode <= 127) { - code = windows_scancode_table[nScanCode]; + if (scanCode != 0) { + if ((keyFlags & KF_EXTENDED) == KF_EXTENDED) { + scanCode = MAKEWORD(scanCode, 0xe0); + } + } else { + Uint16 vkCode = LOWORD(wParam); - if (bIsExtended) { - switch (code) { - case SDL_SCANCODE_RETURN: - code = SDL_SCANCODE_KP_ENTER; - break; - case SDL_SCANCODE_LALT: - code = SDL_SCANCODE_RALT; - break; - case SDL_SCANCODE_LCTRL: - code = SDL_SCANCODE_RCTRL; - break; - case SDL_SCANCODE_SLASH: - code = SDL_SCANCODE_KP_DIVIDE; - break; - case SDL_SCANCODE_CAPSLOCK: - code = SDL_SCANCODE_KP_PLUS; - break; - default: - break; - } - } else { - switch (code) { - case SDL_SCANCODE_HOME: - code = SDL_SCANCODE_KP_7; - break; - case SDL_SCANCODE_UP: - code = SDL_SCANCODE_KP_8; - break; - case SDL_SCANCODE_PAGEUP: - code = SDL_SCANCODE_KP_9; - break; - case SDL_SCANCODE_LEFT: - code = SDL_SCANCODE_KP_4; - break; - case SDL_SCANCODE_RIGHT: - code = SDL_SCANCODE_KP_6; - break; - case SDL_SCANCODE_END: - code = SDL_SCANCODE_KP_1; - break; - case SDL_SCANCODE_DOWN: - code = SDL_SCANCODE_KP_2; - break; - case SDL_SCANCODE_PAGEDOWN: - code = SDL_SCANCODE_KP_3; - break; - case SDL_SCANCODE_INSERT: - code = SDL_SCANCODE_KP_0; - break; - case SDL_SCANCODE_DELETE: - code = SDL_SCANCODE_KP_PERIOD; - break; - case SDL_SCANCODE_PRINTSCREEN: - code = SDL_SCANCODE_KP_MULTIPLY; - break; - default: - break; - } + /* Windows may not report scan codes for some buttons (multimedia buttons etc). + * Get scan code from the VK code.*/ + scanCode = LOWORD(MapVirtualKey(vkCode, MAPVK_VK_TO_VSC_EX)); + + /* Pause/Break key have a special scan code with 0xe1 prefix. + * Use Pause scan code that is used in Win32. */ + if (scanCode == 0xe11d) { + scanCode = 0xe046; } } - /* The on-screen keyboard can generate VK_LEFT and VK_RIGHT events without a scancode - * value set, however we cannot simply map these in VKeytoScancode() or we will be - * incorrectly handling the arrow keys on the number pad when NumLock is disabled - * (which also generate VK_LEFT, VK_RIGHT, etc in that scenario). Instead, we'll only - * map them if none of the above special number pad mappings applied. */ - if (code == SDL_SCANCODE_UNKNOWN) { - code = VKeytoScancodeFallback(wParam); - } + /* Pack scan code into one byte to make the index. */ + index = LOBYTE(scanCode) | (HIBYTE(scanCode) ? 0x80 : 0x00); + code = windows_scancode_table[index]; return code; } From 309ea2d5f90bdce92486d147d9694cebd7284cb1 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Mon, 27 Nov 2023 16:11:20 +0200 Subject: [PATCH 453/725] UWP: Simplify Win32 scan code to SDL scan code mapping --- src/video/winrt/SDL_winrtkeyboard.cpp | 308 ++------------------------ 1 file changed, 17 insertions(+), 291 deletions(-) diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index bf82e8f987ed5..f19f17e60331f 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -34,304 +34,30 @@ extern "C" { #include "../../events/SDL_keyboard_c.h" } -static SDL_Scancode WinRT_Official_Keycodes[] = { - SDL_SCANCODE_UNKNOWN, /* VirtualKey.None -- 0 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftButton -- 1 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightButton -- 2 */ - SDL_SCANCODE_CANCEL, /* VirtualKey.Cancel -- 3 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.MiddleButton -- 4 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton1 -- 5 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton2 -- 6 */ - SDL_SCANCODE_UNKNOWN, /* -- 7 */ - SDL_SCANCODE_BACKSPACE, /* VirtualKey.Back -- 8 */ - SDL_SCANCODE_TAB, /* VirtualKey.Tab -- 9 */ - SDL_SCANCODE_UNKNOWN, /* -- 10 */ - SDL_SCANCODE_UNKNOWN, /* -- 11 */ - SDL_SCANCODE_CLEAR, /* VirtualKey.Clear -- 12 */ - SDL_SCANCODE_RETURN, /* VirtualKey.Enter -- 13 */ - SDL_SCANCODE_UNKNOWN, /* -- 14 */ - SDL_SCANCODE_UNKNOWN, /* -- 15 */ - SDL_SCANCODE_LSHIFT, /* VirtualKey.Shift -- 16 */ - SDL_SCANCODE_LCTRL, /* VirtualKey.Control -- 17 */ - SDL_SCANCODE_MENU, /* VirtualKey.Menu -- 18 */ - SDL_SCANCODE_PAUSE, /* VirtualKey.Pause -- 19 */ - SDL_SCANCODE_CAPSLOCK, /* VirtualKey.CapitalLock -- 20 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Kana or VirtualKey.Hangul -- 21 */ - SDL_SCANCODE_UNKNOWN, /* -- 22 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Junja -- 23 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Final -- 24 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Hanja or VirtualKey.Kanji -- 25 */ - SDL_SCANCODE_UNKNOWN, /* -- 26 */ - SDL_SCANCODE_ESCAPE, /* VirtualKey.Escape -- 27 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Convert -- 28 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.NonConvert -- 29 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Accept -- 30 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?) */ - SDL_SCANCODE_SPACE, /* VirtualKey.Space -- 32 */ - SDL_SCANCODE_PAGEUP, /* VirtualKey.PageUp -- 33 */ - SDL_SCANCODE_PAGEDOWN, /* VirtualKey.PageDown -- 34 */ - SDL_SCANCODE_END, /* VirtualKey.End -- 35 */ - SDL_SCANCODE_HOME, /* VirtualKey.Home -- 36 */ - SDL_SCANCODE_LEFT, /* VirtualKey.Left -- 37 */ - SDL_SCANCODE_UP, /* VirtualKey.Up -- 38 */ - SDL_SCANCODE_RIGHT, /* VirtualKey.Right -- 39 */ - SDL_SCANCODE_DOWN, /* VirtualKey.Down -- 40 */ - SDL_SCANCODE_SELECT, /* VirtualKey.Select -- 41 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?) */ - SDL_SCANCODE_EXECUTE, /* VirtualKey.Execute -- 43 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Snapshot -- 44 */ - SDL_SCANCODE_INSERT, /* VirtualKey.Insert -- 45 */ - SDL_SCANCODE_DELETE, /* VirtualKey.Delete -- 46 */ - SDL_SCANCODE_HELP, /* VirtualKey.Help -- 47 */ - SDL_SCANCODE_0, /* VirtualKey.Number0 -- 48 */ - SDL_SCANCODE_1, /* VirtualKey.Number1 -- 49 */ - SDL_SCANCODE_2, /* VirtualKey.Number2 -- 50 */ - SDL_SCANCODE_3, /* VirtualKey.Number3 -- 51 */ - SDL_SCANCODE_4, /* VirtualKey.Number4 -- 52 */ - SDL_SCANCODE_5, /* VirtualKey.Number5 -- 53 */ - SDL_SCANCODE_6, /* VirtualKey.Number6 -- 54 */ - SDL_SCANCODE_7, /* VirtualKey.Number7 -- 55 */ - SDL_SCANCODE_8, /* VirtualKey.Number8 -- 56 */ - SDL_SCANCODE_9, /* VirtualKey.Number9 -- 57 */ - SDL_SCANCODE_UNKNOWN, /* -- 58 */ - SDL_SCANCODE_UNKNOWN, /* -- 59 */ - SDL_SCANCODE_UNKNOWN, /* -- 60 */ - SDL_SCANCODE_UNKNOWN, /* -- 61 */ - SDL_SCANCODE_UNKNOWN, /* -- 62 */ - SDL_SCANCODE_UNKNOWN, /* -- 63 */ - SDL_SCANCODE_UNKNOWN, /* -- 64 */ - SDL_SCANCODE_A, /* VirtualKey.A -- 65 */ - SDL_SCANCODE_B, /* VirtualKey.B -- 66 */ - SDL_SCANCODE_C, /* VirtualKey.C -- 67 */ - SDL_SCANCODE_D, /* VirtualKey.D -- 68 */ - SDL_SCANCODE_E, /* VirtualKey.E -- 69 */ - SDL_SCANCODE_F, /* VirtualKey.F -- 70 */ - SDL_SCANCODE_G, /* VirtualKey.G -- 71 */ - SDL_SCANCODE_H, /* VirtualKey.H -- 72 */ - SDL_SCANCODE_I, /* VirtualKey.I -- 73 */ - SDL_SCANCODE_J, /* VirtualKey.J -- 74 */ - SDL_SCANCODE_K, /* VirtualKey.K -- 75 */ - SDL_SCANCODE_L, /* VirtualKey.L -- 76 */ - SDL_SCANCODE_M, /* VirtualKey.M -- 77 */ - SDL_SCANCODE_N, /* VirtualKey.N -- 78 */ - SDL_SCANCODE_O, /* VirtualKey.O -- 79 */ - SDL_SCANCODE_P, /* VirtualKey.P -- 80 */ - SDL_SCANCODE_Q, /* VirtualKey.Q -- 81 */ - SDL_SCANCODE_R, /* VirtualKey.R -- 82 */ - SDL_SCANCODE_S, /* VirtualKey.S -- 83 */ - SDL_SCANCODE_T, /* VirtualKey.T -- 84 */ - SDL_SCANCODE_U, /* VirtualKey.U -- 85 */ - SDL_SCANCODE_V, /* VirtualKey.V -- 86 */ - SDL_SCANCODE_W, /* VirtualKey.W -- 87 */ - SDL_SCANCODE_X, /* VirtualKey.X -- 88 */ - SDL_SCANCODE_Y, /* VirtualKey.Y -- 89 */ - SDL_SCANCODE_Z, /* VirtualKey.Z -- 90 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?) */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?) */ - SDL_SCANCODE_APPLICATION, /* VirtualKey.Application -- 93 */ - SDL_SCANCODE_UNKNOWN, /* -- 94 */ - SDL_SCANCODE_SLEEP, /* VirtualKey.Sleep -- 95 */ - SDL_SCANCODE_KP_0, /* VirtualKey.NumberPad0 -- 96 */ - SDL_SCANCODE_KP_1, /* VirtualKey.NumberPad1 -- 97 */ - SDL_SCANCODE_KP_2, /* VirtualKey.NumberPad2 -- 98 */ - SDL_SCANCODE_KP_3, /* VirtualKey.NumberPad3 -- 99 */ - SDL_SCANCODE_KP_4, /* VirtualKey.NumberPad4 -- 100 */ - SDL_SCANCODE_KP_5, /* VirtualKey.NumberPad5 -- 101 */ - SDL_SCANCODE_KP_6, /* VirtualKey.NumberPad6 -- 102 */ - SDL_SCANCODE_KP_7, /* VirtualKey.NumberPad7 -- 103 */ - SDL_SCANCODE_KP_8, /* VirtualKey.NumberPad8 -- 104 */ - SDL_SCANCODE_KP_9, /* VirtualKey.NumberPad9 -- 105 */ - SDL_SCANCODE_KP_MULTIPLY, /* VirtualKey.Multiply -- 106 */ - SDL_SCANCODE_KP_PLUS, /* VirtualKey.Add -- 107 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Separator -- 108 */ - SDL_SCANCODE_KP_MINUS, /* VirtualKey.Subtract -- 109 */ - SDL_SCANCODE_UNKNOWN, /* VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?) */ - SDL_SCANCODE_KP_DIVIDE, /* VirtualKey.Divide -- 111 */ - SDL_SCANCODE_F1, /* VirtualKey.F1 -- 112 */ - SDL_SCANCODE_F2, /* VirtualKey.F2 -- 113 */ - SDL_SCANCODE_F3, /* VirtualKey.F3 -- 114 */ - SDL_SCANCODE_F4, /* VirtualKey.F4 -- 115 */ - SDL_SCANCODE_F5, /* VirtualKey.F5 -- 116 */ - SDL_SCANCODE_F6, /* VirtualKey.F6 -- 117 */ - SDL_SCANCODE_F7, /* VirtualKey.F7 -- 118 */ - SDL_SCANCODE_F8, /* VirtualKey.F8 -- 119 */ - SDL_SCANCODE_F9, /* VirtualKey.F9 -- 120 */ - SDL_SCANCODE_F10, /* VirtualKey.F10 -- 121 */ - SDL_SCANCODE_F11, /* VirtualKey.F11 -- 122 */ - SDL_SCANCODE_F12, /* VirtualKey.F12 -- 123 */ - SDL_SCANCODE_F13, /* VirtualKey.F13 -- 124 */ - SDL_SCANCODE_F14, /* VirtualKey.F14 -- 125 */ - SDL_SCANCODE_F15, /* VirtualKey.F15 -- 126 */ - SDL_SCANCODE_F16, /* VirtualKey.F16 -- 127 */ - SDL_SCANCODE_F17, /* VirtualKey.F17 -- 128 */ - SDL_SCANCODE_F18, /* VirtualKey.F18 -- 129 */ - SDL_SCANCODE_F19, /* VirtualKey.F19 -- 130 */ - SDL_SCANCODE_F20, /* VirtualKey.F20 -- 131 */ - SDL_SCANCODE_F21, /* VirtualKey.F21 -- 132 */ - SDL_SCANCODE_F22, /* VirtualKey.F22 -- 133 */ - SDL_SCANCODE_F23, /* VirtualKey.F23 -- 134 */ - SDL_SCANCODE_F24, /* VirtualKey.F24 -- 135 */ - SDL_SCANCODE_UNKNOWN, /* -- 136 */ - SDL_SCANCODE_UNKNOWN, /* -- 137 */ - SDL_SCANCODE_UNKNOWN, /* -- 138 */ - SDL_SCANCODE_UNKNOWN, /* -- 139 */ - SDL_SCANCODE_UNKNOWN, /* -- 140 */ - SDL_SCANCODE_UNKNOWN, /* -- 141 */ - SDL_SCANCODE_UNKNOWN, /* -- 142 */ - SDL_SCANCODE_UNKNOWN, /* -- 143 */ - SDL_SCANCODE_NUMLOCKCLEAR, /* VirtualKey.NumberKeyLock -- 144 */ - SDL_SCANCODE_SCROLLLOCK, /* VirtualKey.Scroll -- 145 */ - SDL_SCANCODE_UNKNOWN, /* -- 146 */ - SDL_SCANCODE_UNKNOWN, /* -- 147 */ - SDL_SCANCODE_UNKNOWN, /* -- 148 */ - SDL_SCANCODE_UNKNOWN, /* -- 149 */ - SDL_SCANCODE_UNKNOWN, /* -- 150 */ - SDL_SCANCODE_UNKNOWN, /* -- 151 */ - SDL_SCANCODE_UNKNOWN, /* -- 152 */ - SDL_SCANCODE_UNKNOWN, /* -- 153 */ - SDL_SCANCODE_UNKNOWN, /* -- 154 */ - SDL_SCANCODE_UNKNOWN, /* -- 155 */ - SDL_SCANCODE_UNKNOWN, /* -- 156 */ - SDL_SCANCODE_UNKNOWN, /* -- 157 */ - SDL_SCANCODE_UNKNOWN, /* -- 158 */ - SDL_SCANCODE_UNKNOWN, /* -- 159 */ - SDL_SCANCODE_LSHIFT, /* VirtualKey.LeftShift -- 160 */ - SDL_SCANCODE_RSHIFT, /* VirtualKey.RightShift -- 161 */ - SDL_SCANCODE_LCTRL, /* VirtualKey.LeftControl -- 162 */ - SDL_SCANCODE_RCTRL, /* VirtualKey.RightControl -- 163 */ - SDL_SCANCODE_MENU, /* VirtualKey.LeftMenu -- 164 */ - SDL_SCANCODE_MENU, /* VirtualKey.RightMenu -- 165 */ - SDL_SCANCODE_AC_BACK, /* VirtualKey.GoBack -- 166 : The go back key. */ - SDL_SCANCODE_AC_FORWARD, /* VirtualKey.GoForward -- 167 : The go forward key. */ - SDL_SCANCODE_AC_REFRESH, /* VirtualKey.Refresh -- 168 : The refresh key. */ - SDL_SCANCODE_AC_STOP, /* VirtualKey.Stop -- 169 : The stop key. */ - SDL_SCANCODE_AC_SEARCH, /* VirtualKey.Search -- 170 : The search key. */ - SDL_SCANCODE_AC_BOOKMARKS, /* VirtualKey.Favorites -- 171 : The favorites key. */ - SDL_SCANCODE_AC_HOME /* VirtualKey.GoHome -- 172 : The go home key. */ -}; - -/* Attempt to translate a keycode that isn't listed in WinRT's VirtualKey enum. - */ -static SDL_Scancode WINRT_TranslateUnofficialKeycode(int keycode) +static SDL_Scancode WINRT_TranslateKeycode(Windows::UI::Core::KeyEventArgs ^ args) { - switch (keycode) { - case 173: - return SDL_SCANCODE_MUTE; /* VK_VOLUME_MUTE */ - case 174: - return SDL_SCANCODE_VOLUMEDOWN; /* VK_VOLUME_DOWN */ - case 175: - return SDL_SCANCODE_VOLUMEUP; /* VK_VOLUME_UP */ - case 176: - return SDL_SCANCODE_AUDIONEXT; /* VK_MEDIA_NEXT_TRACK */ - case 177: - return SDL_SCANCODE_AUDIOPREV; /* VK_MEDIA_PREV_TRACK */ - // case 178: return ; /* VK_MEDIA_STOP */ - case 179: - return SDL_SCANCODE_AUDIOPLAY; /* VK_MEDIA_PLAY_PAUSE */ - case 180: - return SDL_SCANCODE_MAIL; /* VK_LAUNCH_MAIL */ - case 181: - return SDL_SCANCODE_MEDIASELECT; /* VK_LAUNCH_MEDIA_SELECT */ - // case 182: return ; /* VK_LAUNCH_APP1 */ - case 183: - return SDL_SCANCODE_CALCULATOR; /* VK_LAUNCH_APP2 */ - // case 184: return ; /* ... reserved ... */ - // case 185: return ; /* ... reserved ... */ - case 186: - return SDL_SCANCODE_SEMICOLON; /* VK_OEM_1, ';:' key on US standard keyboards */ - case 187: - return SDL_SCANCODE_EQUALS; /* VK_OEM_PLUS */ - case 188: - return SDL_SCANCODE_COMMA; /* VK_OEM_COMMA */ - case 189: - return SDL_SCANCODE_MINUS; /* VK_OEM_MINUS */ - case 190: - return SDL_SCANCODE_PERIOD; /* VK_OEM_PERIOD */ - case 191: - return SDL_SCANCODE_SLASH; /* VK_OEM_2, '/?' key on US standard keyboards */ - case 192: - return SDL_SCANCODE_GRAVE; /* VK_OEM_3, '`~' key on US standard keyboards */ - // ? - // ... reserved or unassigned ... - // ? - case 219: - return SDL_SCANCODE_LEFTBRACKET; /* VK_OEM_4, '[{' key on US standard keyboards */ - case 220: - return SDL_SCANCODE_BACKSLASH; /* VK_OEM_5, '\|' key on US standard keyboards */ - case 221: - return SDL_SCANCODE_RIGHTBRACKET; /* VK_OEM_6, ']}' key on US standard keyboards */ - case 222: - return SDL_SCANCODE_APOSTROPHE; /* VK_OEM_7, 'single/double quote' on US standard keyboards */ - default: - break; + SDL_Scancode code; + Uint8 index; + Uint16 scanCode = args->KeyStatus.ScanCode | (args->KeyStatus.IsExtendedKey ? 0xe000 : 0); + + /* Pause/Break key have a special scan code with 0xe1 prefix + * that is not properly reported under UWP. + * Use Pause scan code that is used in Win32. */ + if (args->VirtualKey == Windows::System::VirtualKey::Pause) { + scanCode = 0xe046; } - return SDL_SCANCODE_UNKNOWN; -} - -static SDL_Scancode WINRT_TranslateKeycode(int keycode, unsigned int nativeScancode) -{ - // TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints - - SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; - /* HACK ALERT: At least one VirtualKey constant (Shift) with a left/right - * designation might not get reported with its correct handedness, however - * its hardware scan code can fill in the gaps. If this is detected, - * use the hardware scan code to try telling if the left, or the right - * side's key was used. - * - * If Microsoft ever allows MapVirtualKey or MapVirtualKeyEx to be used - * in WinRT apps, or something similar to these (it doesn't appear to be, - * at least not for Windows [Phone] 8/8.1, as of Oct 24, 2014), then this - * hack might become deprecated, or obsolete. - */ - if (nativeScancode < SDL_arraysize(windows_scancode_table)) { - switch (keycode) { - case 16: // VirtualKey.Shift - switch (windows_scancode_table[nativeScancode]) { - case SDL_SCANCODE_LSHIFT: - case SDL_SCANCODE_RSHIFT: - return windows_scancode_table[nativeScancode]; - } - break; - - // Add others, as necessary. - // - // Unfortunately, this hack doesn't seem to work in determining - // handedness with Control keys. + /* Pack scan code into one byte to make the index. */ + index = LOBYTE(scanCode) | (HIBYTE(scanCode) ? 0x80 : 0x00); + code = windows_scancode_table[index]; - default: - break; - } - } - - /* Try to get a documented, WinRT, 'VirtualKey' next (as documented at - http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ). - If that fails, fall back to a Win32 virtual key. - If that fails, attempt to fall back to a scancode-derived key. - */ - if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) { - scancode = WinRT_Official_Keycodes[keycode]; - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - scancode = WINRT_TranslateUnofficialKeycode(keycode); - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - if (nativeScancode < SDL_arraysize(windows_scancode_table)) { - scancode = windows_scancode_table[nativeScancode]; - } - } - /* - if (scancode == SDL_SCANCODE_UNKNOWN) { - SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode); - } - */ - return scancode; + return code; } void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args) { - SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode); + SDL_Scancode sdlScancode = WINRT_TranslateKeycode(args); + #if 0 SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, " @@ -356,7 +82,7 @@ void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args) void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args) { - SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode); + SDL_Scancode sdlScancode = WINRT_TranslateKeycode(args); #if 0 SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, " From 9a206adbee1af90430f36177a332417d9c7c230d Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Tue, 28 Nov 2023 20:23:57 +0200 Subject: [PATCH 454/725] UWP: Use Windows.UI.Core.CoreDispatcher.AcceleratorKeyActivated event for keyboard Only in this case we can see Left Alt and Right Alt keys. Stole the idea from DirectXTK12 repo: https://github.com/microsoft/DirectXTK12/blob/main/Src/Keyboard.cpp --- src/core/winrt/SDL_winrtapp_direct3d.cpp | 16 ++---- src/core/winrt/SDL_winrtapp_direct3d.h | 3 +- src/video/winrt/SDL_winrtevents_c.h | 3 +- src/video/winrt/SDL_winrtkeyboard.cpp | 73 ++++++++---------------- 4 files changed, 29 insertions(+), 66 deletions(-) diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index 167e5a9a0be4b..f451203e25b50 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -296,11 +296,8 @@ void SDL_WinRTApp::SetWindow(CoreWindow ^ window) ref new TypedEventHandler(this, &SDL_WinRTApp::OnMouseMoved); #endif - window->KeyDown += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnKeyDown); - - window->KeyUp += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnKeyUp); + window->Dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &SDL_WinRTApp::OnAcceleratorKeyActivated); window->CharacterReceived += ref new TypedEventHandler(this, &SDL_WinRTApp::OnCharacterReceived); @@ -720,14 +717,9 @@ void SDL_WinRTApp::OnMouseMoved(MouseDevice ^ mouseDevice, MouseEventArgs ^ args WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args); } -void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args) -{ - WINRT_ProcessKeyDownEvent(args); -} - -void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args) +void SDL_WinRTApp::OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ sender, Windows::UI::Core::AcceleratorKeyEventArgs ^ args) { - WINRT_ProcessKeyUpEvent(args); + WINRT_ProcessAcceleratorKeyActivated(args); } void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args) diff --git a/src/core/winrt/SDL_winrtapp_direct3d.h b/src/core/winrt/SDL_winrtapp_direct3d.h index 30867a69e2647..a8795ff09c88a 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.h +++ b/src/core/winrt/SDL_winrtapp_direct3d.h @@ -71,8 +71,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo void OnPointerEntered(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); void OnPointerExited(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); void OnMouseMoved(Windows::Devices::Input::MouseDevice ^ mouseDevice, Windows::Devices::Input::MouseEventArgs ^ args); - void OnKeyDown(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args); - void OnKeyUp(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args); + void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ sender, Windows::UI::Core::AcceleratorKeyEventArgs ^ args); void OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args); #if NTDDI_VERSION >= NTDDI_WIN10 diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h index f5871caf34b47..7330c7442dc7a 100644 --- a/src/video/winrt/SDL_winrtevents_c.h +++ b/src/video/winrt/SDL_winrtevents_c.h @@ -63,8 +63,7 @@ extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::U extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::Input::MouseEventArgs ^ args); /* Keyboard */ -extern void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args); -extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args); +extern void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEventArgs ^ args); extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args); #if NTDDI_VERSION >= NTDDI_WIN10 diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index f19f17e60331f..0524db48f35ab 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -34,16 +34,16 @@ extern "C" { #include "../../events/SDL_keyboard_c.h" } -static SDL_Scancode WINRT_TranslateKeycode(Windows::UI::Core::KeyEventArgs ^ args) +static SDL_Scancode WINRT_TranslateKeycode(Windows::System::VirtualKey virtualKey, const Windows::UI::Core::CorePhysicalKeyStatus& keyStatus) { SDL_Scancode code; Uint8 index; - Uint16 scanCode = args->KeyStatus.ScanCode | (args->KeyStatus.IsExtendedKey ? 0xe000 : 0); + Uint16 scanCode = keyStatus.ScanCode | (keyStatus.IsExtendedKey ? 0xe000 : 0); /* Pause/Break key have a special scan code with 0xe1 prefix * that is not properly reported under UWP. * Use Pause scan code that is used in Win32. */ - if (args->VirtualKey == Windows::System::VirtualKey::Pause) { + if (virtualKey == Windows::System::VirtualKey::Pause) { scanCode = 0xe046; } @@ -54,55 +54,28 @@ static SDL_Scancode WINRT_TranslateKeycode(Windows::UI::Core::KeyEventArgs ^ arg return code; } -void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args) +void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEventArgs ^ args) { - SDL_Scancode sdlScancode = WINRT_TranslateKeycode(args); - -#if 0 - SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); - SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, " - "repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, " - "sdl scan code=%d (%s), sdl key code=%d (%s)\n", - (args->Handled ? "1" : "0"), - (args->KeyStatus.IsExtendedKey ? "1" : "0"), - (args->KeyStatus.IsKeyReleased ? "1" : "0"), - (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), - args->KeyStatus.RepeatCount, - args->KeyStatus.ScanCode, - (args->KeyStatus.WasKeyDown ? "1" : "0"), - args->VirtualKey, - sdlScancode, - SDL_GetScancodeName(sdlScancode), - keycode, - SDL_GetKeyName(keycode)); - //args->Handled = true; -#endif - SDL_SendKeyboardKey(0, SDL_PRESSED, sdlScancode); -} + using namespace Windows::UI::Core; -void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args) -{ - SDL_Scancode sdlScancode = WINRT_TranslateKeycode(args); -#if 0 - SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); - SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, " - "repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, " - "sdl scan code=%d (%s), sdl key code=%d (%s)\n", - (args->Handled ? "1" : "0"), - (args->KeyStatus.IsExtendedKey ? "1" : "0"), - (args->KeyStatus.IsKeyReleased ? "1" : "0"), - (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), - args->KeyStatus.RepeatCount, - args->KeyStatus.ScanCode, - (args->KeyStatus.WasKeyDown ? "1" : "0"), - args->VirtualKey, - sdlScancode, - SDL_GetScancodeName(sdlScancode), - keycode, - SDL_GetKeyName(keycode)); - //args->Handled = true; -#endif - SDL_SendKeyboardKey(0, SDL_RELEASED, sdlScancode); + Uint8 state; + SDL_Scancode code; + + switch (args->EventType) { + case CoreAcceleratorKeyEventType::SystemKeyDown: + case CoreAcceleratorKeyEventType::KeyDown: + state = SDL_PRESSED; + break; + case CoreAcceleratorKeyEventType::SystemKeyUp: + case CoreAcceleratorKeyEventType::KeyUp: + state = SDL_RELEASED; + break; + default: + return; + } + + code = WINRT_TranslateKeycode(args->VirtualKey, args->KeyStatus); + SDL_SendKeyboardKey(0, state, code); } void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args) From 1e12d7cfb69b0d8a296648027e99880920259d65 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 28 Nov 2023 11:38:35 -0800 Subject: [PATCH 455/725] Make sure we don't pass UTF-8 to SDL_iscntrl() This function is only valid for values <= 127. Closes https://github.com/libsdl-org/SDL/pull/8637 --- src/events/SDL_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 2a92707d34112..0f7adea2d6589 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1063,7 +1063,7 @@ int SDL_SendKeyboardText(const char *text) int posted; /* Don't post text events for unprintable characters */ - if (SDL_iscntrl((int)*text)) { + if (!(*text & 0x80) && SDL_iscntrl(*text)) { return 0; } From 3e6513c77390969cd870726690bf89e39fe91e60 Mon Sep 17 00:00:00 2001 From: shenleban tongying Date: Tue, 28 Nov 2023 15:00:04 -0500 Subject: [PATCH 456/725] document the purpose of SDL_SetTextInputRect --- include/SDL3/SDL_keyboard.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index d51af2921a2e7..b56f5e85d9bc6 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -300,8 +300,10 @@ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); extern DECLSPEC SDL_bool SDLCALL SDL_TextInputShown(void); /** - * Set the rectangle used to type Unicode text inputs. - * + * Set the rectangle used to type Unicode text inputs. Native input methods + * will place a window with word suggestions near it, without covering the + * text being inputted. + * * To start text input in a given location, this function is intended to be * called before SDL_StartTextInput, although some platforms support moving * the rectangle even while text input (and a composition) is active. From 411c70abb19a19ec5368a060b48a5fead2ad67bf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 28 Nov 2023 12:20:43 -0800 Subject: [PATCH 457/725] Fix the target membership of SDL_pen.h (thanks kanjitalk755!) Closes https://github.com/libsdl-org/SDL/pull/8599 --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 6153aa020f9ae..a5f81e68d4683 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -52,7 +52,7 @@ 566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; }; 566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; }; 56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */; }; - 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A212A7902CF0021E9A6 /* SDL_pen.h */; }; + 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A212A7902CF0021E9A6 /* SDL_pen.h */; settings = {ATTRIBUTES = (Public, ); }; }; 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */; }; 63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63134A242A7902FD0021E9A6 /* SDL_pen.c */; }; 75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = 75E09158241EA924004729E1 /* SDL_virtualjoystick.c */; }; From 7b628ea4d53c5b85954088570105764f20b6ff02 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Mon, 27 Nov 2023 16:15:24 +0200 Subject: [PATCH 458/725] Win32: Simplify Unicode text input code --- src/video/windows/SDL_windowsevents.c | 77 ++++++--------------------- 1 file changed, 17 insertions(+), 60 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index d5381dd77cf0a..dc56b0002b397 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -98,12 +98,6 @@ #ifndef IS_HIGH_SURROGATE #define IS_HIGH_SURROGATE(x) (((x) >= 0xd800) && ((x) <= 0xdbff)) #endif -#ifndef IS_LOW_SURROGATE -#define IS_LOW_SURROGATE(x) (((x) >= 0xdc00) && ((x) <= 0xdfff)) -#endif -#ifndef IS_SURROGATE_PAIR -#define IS_SURROGATE_PAIR(h, l) (IS_HIGH_SURROGATE(h) && IS_LOW_SURROGATE(l)) -#endif #ifndef USER_TIMER_MINIMUM #define USER_TIMER_MINIMUM 0x0000000A @@ -394,39 +388,6 @@ static void WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus) } #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ -static BOOL WIN_ConvertUTF32toUTF8(UINT32 codepoint, char *text) -{ - if (codepoint <= 0x7F) { - text[0] = (char)codepoint; - text[1] = '\0'; - } else if (codepoint <= 0x7FF) { - text[0] = 0xC0 | (char)((codepoint >> 6) & 0x1F); - text[1] = 0x80 | (char)(codepoint & 0x3F); - text[2] = '\0'; - } else if (codepoint <= 0xFFFF) { - text[0] = 0xE0 | (char)((codepoint >> 12) & 0x0F); - text[1] = 0x80 | (char)((codepoint >> 6) & 0x3F); - text[2] = 0x80 | (char)(codepoint & 0x3F); - text[3] = '\0'; - } else if (codepoint <= 0x10FFFF) { - text[0] = 0xF0 | (char)((codepoint >> 18) & 0x0F); - text[1] = 0x80 | (char)((codepoint >> 12) & 0x3F); - text[2] = 0x80 | (char)((codepoint >> 6) & 0x3F); - text[3] = 0x80 | (char)(codepoint & 0x3F); - text[4] = '\0'; - } else { - return SDL_FALSE; - } - return SDL_TRUE; -} - -static BOOL WIN_ConvertUTF16toUTF8(UINT32 high_surrogate, UINT32 low_surrogate, char *text) -{ - const UINT32 SURROGATE_OFFSET = 0x10000U - (0xD800 << 10) - 0xDC00; - const UINT32 codepoint = (high_surrogate << 10) + low_surrogate + SURROGATE_OFFSET; - return WIN_ConvertUTF32toUTF8(codepoint, text); -} - static SDL_bool ShouldGenerateWindowCloseOnAltF4(void) { return !SDL_GetHintBoolean(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, SDL_FALSE); @@ -885,7 +846,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) returnCode = 1; } else { char text[5]; - if (WIN_ConvertUTF32toUTF8((UINT32)wParam, text)) { + if (SDL_UCS4ToUTF8((Uint32)wParam, text) != text) { SDL_SendKeyboardText(text); } returnCode = 0; @@ -893,31 +854,27 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_CHAR: - /* When a user enters a Unicode code point defined in the Basic Multilingual Plane, Windows sends a WM_CHAR - message with the code point encoded as UTF-16. When a user enters a Unicode code point from a Supplementary - Plane, Windows sends the code point in two separate WM_CHAR messages: The first message includes the UTF-16 - High Surrogate and the second the UTF-16 Low Surrogate. The High and Low Surrogates cannot be individually - converted to valid UTF-8, therefore, we must save the High Surrogate from the first WM_CHAR message and - concatenate it with the Low Surrogate from the second WM_CHAR message. At that point, we have a valid - UTF-16 surrogate pair ready to re-encode as UTF-8. */ + /* Characters outside Unicode Basic Multilingual Plane (BMP) + * are coded as so called "surrogate pair" in two separate character events. + * Cache high surrogate until next character event. */ if (IS_HIGH_SURROGATE(wParam)) { data->high_surrogate = (WCHAR)wParam; - } else if (IS_SURROGATE_PAIR(data->high_surrogate, wParam)) { - /* The code point is in a Supplementary Plane. - Here wParam is the Low Surrogate. */ - char text[5]; - if (WIN_ConvertUTF16toUTF8((UINT32)data->high_surrogate, (UINT32)wParam, text)) { - SDL_SendKeyboardText(text); - } - data->high_surrogate = 0; } else { - /* The code point is in the Basic Multilingual Plane. - It's numerically equal to UTF-32. */ - char text[5]; - if (WIN_ConvertUTF32toUTF8((UINT32)wParam, text)) { - SDL_SendKeyboardText(text); + WCHAR utf16[] = { + data->high_surrogate ? data->high_surrogate : (WCHAR)wParam, + data->high_surrogate ? (WCHAR)wParam : L'\0', + L'\0' + }; + + char utf8[5]; + int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + if (result > 0) { + SDL_SendKeyboardText(utf8); } + + data->high_surrogate = L'\0'; } + returnCode = 0; break; From 9faa7977bd9966793cf5ebb5a0c6d646468d8cb6 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Mon, 27 Nov 2023 17:23:17 +0200 Subject: [PATCH 459/725] =?UTF-8?q?=EF=BB=BFUWP:=20Add=20support=20for=20s?= =?UTF-8?q?upplementary=20Unicode=20characters=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Characters outside Basic Multilingual Plane (BMP) are coded as so called "surrogate pair" in two separate UTF-16 character events. --- src/core/winrt/SDL_winrtapp_direct3d.cpp | 2 +- src/video/windows/SDL_windowsevents.c | 2 +- src/video/winrt/SDL_winrtevents_c.h | 2 +- src/video/winrt/SDL_winrtkeyboard.cpp | 41 ++++++++++++++++-------- src/video/winrt/SDL_winrtvideo.cpp | 1 + src/video/winrt/SDL_winrtvideo_cpp.h | 1 + 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index f451203e25b50..64572f33b2bb4 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -724,7 +724,7 @@ void SDL_WinRTApp::OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args) { - WINRT_ProcessCharacterReceivedEvent(args); + WINRT_ProcessCharacterReceivedEvent(WINRT_GlobalSDLWindow, args); } template diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index dc56b0002b397..8624b92dc9d50 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -855,7 +855,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_CHAR: /* Characters outside Unicode Basic Multilingual Plane (BMP) - * are coded as so called "surrogate pair" in two separate character events. + * are coded as so called "surrogate pair" in two separate UTF-16 character events. * Cache high surrogate until next character event. */ if (IS_HIGH_SURROGATE(wParam)) { data->high_surrogate = (WCHAR)wParam; diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h index 7330c7442dc7a..72de3bb8fd2a5 100644 --- a/src/video/winrt/SDL_winrtevents_c.h +++ b/src/video/winrt/SDL_winrtevents_c.h @@ -64,7 +64,7 @@ extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::I /* Keyboard */ extern void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEventArgs ^ args); -extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args); +extern void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core::CharacterReceivedEventArgs ^ args); #if NTDDI_VERSION >= NTDDI_WIN10 extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this); diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index 0524db48f35ab..4a62b0186ce10 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -34,6 +34,8 @@ extern "C" { #include "../../events/SDL_keyboard_c.h" } +#include "SDL_winrtvideo_cpp.h" + static SDL_Scancode WINRT_TranslateKeycode(Windows::System::VirtualKey virtualKey, const Windows::UI::Core::CorePhysicalKeyStatus& keyStatus) { SDL_Scancode code; @@ -78,20 +80,33 @@ void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEvent SDL_SendKeyboardKey(0, state, code); } -void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args) +void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core::CharacterReceivedEventArgs ^ args) { - wchar_t src_ucs2[2]; - char dest_utf8[16]; - int result; - - /* Setup src */ - src_ucs2[0] = args->KeyCode; - src_ucs2[1] = L'\0'; - - /* Convert the text, then send an SDL_EVENT_TEXT_INPUT event. */ - result = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&src_ucs2, -1, (LPSTR)dest_utf8, sizeof(dest_utf8), NULL, NULL); - if (result > 0) { - SDL_SendKeyboardText(dest_utf8); + if (!window) { + return; + } + + SDL_WindowData *data = window->driverdata; + + /* Characters outside Unicode Basic Multilingual Plane (BMP) + * are coded as so called "surrogate pair" in two separate UTF-16 character events. + * Cache high surrogate until next character event. */ + if (IS_HIGH_SURROGATE(args->KeyCode)) { + data->high_surrogate = (WCHAR)args->KeyCode; + } else { + WCHAR utf16[] = { + data->high_surrogate ? data->high_surrogate : (WCHAR)args->KeyCode, + data->high_surrogate ? (WCHAR)args->KeyCode : L'\0', + L'\0' + }; + + char utf8[5]; + int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + if (result > 0) { + SDL_SendKeyboardText(utf8); + } + + data->high_surrogate = L'\0'; } } diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 1399738c7e2b0..8f8cde7e5b1e6 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -595,6 +595,7 @@ int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie } window->driverdata = data; data->sdlWindow = window; + data->high_surrogate = L'\0'; /* To note, when XAML support is enabled, access to the CoreWindow will not be possible, at least not via the SDL/XAML thread. Attempts to access it diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h index 069fff4fb19f5..e8b8c3d47613c 100644 --- a/src/video/winrt/SDL_winrtvideo_cpp.h +++ b/src/video/winrt/SDL_winrtvideo_cpp.h @@ -100,6 +100,7 @@ struct SDL_WindowData #if SDL_WINRT_USE_APPLICATIONVIEW Windows::UI::ViewManagement::ApplicationView ^ appView; #endif + WCHAR high_surrogate; }; #endif // ifdef __cplusplus_winrt From fea6e7afb1c13326f463aef47ecd26396d1e3a2f Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 28 Nov 2023 18:49:01 +0100 Subject: [PATCH 460/725] cmake: copy sources to binary directory in separate target Don't do it in POST_BUILD to avoid multiple parallel builds stepping on each others toes. Also don't use copy_if_different, but unconditionally copy it. The build system should take care of dependencies. --- test/CMakeLists.txt | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9b917c9c05ffc..98fc28c95cd6d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,11 +32,35 @@ add_library(sdltests_utils OBJECT target_link_libraries(sdltests_utils PRIVATE SDL3::Headers) file(GLOB RESOURCE_FILES *.bmp *.wav *.hex moose.dat utf8.txt) + +if(CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(test_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + endif() +else() + set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}") +endif() +if(NOT CMAKE_VERSION VERSION_LESS 3.20) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + set(test_bin_dir "${test_bin_dir}$<$:/$>") +endif() + set(RESOURCE_FILE_NAMES) -foreach(RESOURCE_FILE IN LISTS RESOURCE_FILES) - get_filename_component(res_file_name ${RESOURCE_FILE} NAME) +set(RESOURCE_FILES_BINDIR) +foreach(resource_file IN LISTS RESOURCE_FILES) + get_filename_component(res_file_name ${resource_file} NAME) list(APPEND RESOURCE_FILE_NAMES "${res_file_name}") + set(resource_file_bindir "${test_bin_dir}/${res_file_name}") + add_custom_command(OUTPUT "${resource_file_bindir}" + COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}" + DEPENDS "${resource_file}" + ) + list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}") endforeach() +add_custom_target(copy-sdl-test-resources + DEPENDS "${RESOURCE_FILES_BINDIR}" +) define_property(TARGET PROPERTY SDL_NONINTERACTIVE BRIEF_DOCS "If true, target is a non-interactive test executable." FULL_DOCS "If true, target is a noninteractive test executable.") define_property(TARGET PROPERTY SDL_NONINTERACTIVE_ARGUMENTS BRIEF_DOCS "Argument(s) to run executable in non-interactive mode." FULL_DOCS "Argument(s) to run executable in non-interactive mode.") @@ -134,8 +158,7 @@ macro(add_sdl_test_executable TARGET) ) add_dependencies(${TARGET} zzz-resources-copy-${TARGET}) else() - add_custom_command(TARGET ${TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${RESOURCE_FILES} $) + add_dependencies(${TARGET} copy-sdl-test-resources) endif() if(APPLE) # Make sure resource files get installed into macOS/iOS .app bundles. From 63d4bd4e57ec06f6c6bf8314aa2eb4778a499856 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 29 Nov 2023 00:39:24 +0300 Subject: [PATCH 461/725] SDL_SendKeyboardText: remove workaround from 1e12d7c, fix use of iscntrl --- src/events/SDL_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 0f7adea2d6589..f01b90a08cec2 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1063,7 +1063,7 @@ int SDL_SendKeyboardText(const char *text) int posted; /* Don't post text events for unprintable characters */ - if (!(*text & 0x80) && SDL_iscntrl(*text)) { + if (SDL_iscntrl((unsigned char)*text)) { return 0; } From df05d5eff45d15eff45cdae9f65e2ab4c3fd8e07 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Tue, 28 Nov 2023 22:15:18 +0000 Subject: [PATCH 462/725] Fix scroll wheel handling in testmouse --- test/testmouse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testmouse.c b/test/testmouse.c index b7852e7442d70..18efbc0eb67b4 100644 --- a/test/testmouse.c +++ b/test/testmouse.c @@ -125,10 +125,10 @@ static void loop(void *arg) /* "positive to the right and negative to the left" */ wheel_x += event.wheel.x * 10.0f; } - if (event.wheel.x != 0.0f) { + if (event.wheel.y != 0.0f) { wheel_y_active = SDL_TRUE; /* "positive away from the user and negative towards the user" */ - wheel_y -= event.wheel.x * 10.0f; + wheel_y -= event.wheel.y * 10.0f; } break; From c5daf8adb172f86bc04ede93385a7a06991a1c32 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 10:33:31 -0500 Subject: [PATCH 463/725] testcontroller: Don't query the mapping list until after they are available. The included ones need to wait until SDL_Init has run, or you'll get an empty list, and we might also be adding more from an external gamecontrollerdb.txt file, too. --- test/testcontroller.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index 3dbafb59603ad..e7d7260bc6e08 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1876,6 +1876,7 @@ int main(int argc, char *argv[]) int screen_width, screen_height; SDL_Rect area; int gamepad_index = -1; + SDL_bool show_mappings = SDL_FALSE; SDLTest_CommonState *state; /* Initialize test framework */ @@ -1902,16 +1903,7 @@ int main(int argc, char *argv[]) consumed = SDLTest_CommonArg(state, i); if (!consumed) { if (SDL_strcmp(argv[i], "--mappings") == 0) { - int map_i; - SDL_Log("Supported mappings:\n"); - for (map_i = 0; map_i < SDL_GetNumGamepadMappings(); ++map_i) { - char *mapping = SDL_GetGamepadMappingForIndex(map_i); - if (mapping) { - SDL_Log("\t%s\n", mapping); - SDL_free(mapping); - } - } - SDL_Log("\n"); + show_mappings = SDL_TRUE; consumed = 1; } else if (SDL_strcmp(argv[i], "--virtual") == 0) { OpenVirtualGamepad(); @@ -1944,6 +1936,19 @@ int main(int argc, char *argv[]) SDL_AddGamepadMappingsFromFile("gamecontrollerdb.txt"); + if (show_mappings) { + int map_i; + SDL_Log("Supported mappings:\n"); + for (map_i = 0; map_i < SDL_GetNumGamepadMappings(); ++map_i) { + char *mapping = SDL_GetGamepadMappingForIndex(map_i); + if (mapping) { + SDL_Log("\t%s\n", mapping); + SDL_free(mapping); + } + } + SDL_Log("\n"); + } + /* Create a window to display gamepad state */ content_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); if (content_scale == 0.0f) { From f32575dfabecac37892e3abfe31b08b9e348a9d7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 11:19:31 -0500 Subject: [PATCH 464/725] docs: Convert everything to Unix-style endlines. Fixes #8640. --- README.md | 36 +- docs/README-android.md | 1126 +++++++------- docs/README-cmake.md | 656 ++++---- docs/README-contributing.md | 194 +-- docs/README-dynapi.md | 276 ++-- docs/README-emscripten.md | 730 ++++----- docs/README-gdk.md | 318 ++-- docs/README-git.md | 38 +- docs/README-hg.md | 14 +- docs/README-highdpi.md | 16 +- docs/README-ios.md | 544 +++---- docs/README-kmsbsd.md | 54 +- docs/README-linux.md | 176 +-- docs/README-macos.md | 504 +++--- docs/README-main-functions.md | 388 ++--- docs/README-migration.md | 2712 ++++++++++++++++----------------- docs/README-n3ds.md | 56 +- docs/README-ngage.md | 88 +- docs/README-platforms.md | 16 +- docs/README-porting.md | 130 +- docs/README-ps2.md | 102 +- docs/README-psp.md | 72 +- docs/README-raspberrypi.md | 360 ++--- docs/README-riscos.md | 70 +- docs/README-touch.md | 162 +- docs/README-versions.md | 120 +- docs/README-visualc.md | 226 +-- docs/README-vita.md | 66 +- docs/README-wayland.md | 90 +- docs/README-windows.md | 132 +- docs/README-winrt.md | 1046 ++++++------- docs/README.md | 114 +- 32 files changed, 5316 insertions(+), 5316 deletions(-) diff --git a/README.md b/README.md index ce500fa57c543..4d4741b0edb12 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ - -# Simple DirectMedia Layer (SDL) Version 3.0 - -https://www.libsdl.org/ - -Simple DirectMedia Layer is a cross-platform development library designed -to provide low level access to audio, keyboard, mouse, joystick, and graphics -hardware via OpenGL and Direct3D. It is used by video playback software, -emulators, and popular games including Valve's award winning catalog -and many Humble Bundle games. - -More extensive documentation is available in the docs directory, starting -with [README.md](docs/README.md). If you are migrating to SDL 3.0 from SDL 2.0, -the changes are extensively documented in [README-migration.md](docs/README-migration.md). - -Enjoy! - -Sam Lantinga (slouken@libsdl.org) + +# Simple DirectMedia Layer (SDL) Version 3.0 + +https://www.libsdl.org/ + +Simple DirectMedia Layer is a cross-platform development library designed +to provide low level access to audio, keyboard, mouse, joystick, and graphics +hardware via OpenGL and Direct3D. It is used by video playback software, +emulators, and popular games including Valve's award winning catalog +and many Humble Bundle games. + +More extensive documentation is available in the docs directory, starting +with [README.md](docs/README.md). If you are migrating to SDL 3.0 from SDL 2.0, +the changes are extensively documented in [README-migration.md](docs/README-migration.md). + +Enjoy! + +Sam Lantinga (slouken@libsdl.org) diff --git a/docs/README-android.md b/docs/README-android.md index 2eaee31bdd2a3..588b43d0e945e 100644 --- a/docs/README-android.md +++ b/docs/README-android.md @@ -1,563 +1,563 @@ -Android -================================================================================ - -Matt Styles wrote a tutorial on building SDL for Android with Visual Studio: -http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html - -The rest of this README covers the Android gradle style build process. - - -Requirements -================================================================================ - -Android SDK (version 34 or later) -https://developer.android.com/sdk/index.html - -Android NDK r15c or later -https://developer.android.com/tools/sdk/ndk/index.html - -Minimum API level supported by SDL: 19 (Android 4.4) - - -How the port works -================================================================================ - -- Android applications are Java-based, optionally with parts written in C -- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to - the SDL library -- This means that your application C code must be placed inside an Android - Java project, along with some C support code that communicates with Java -- This eventually produces a standard Android .apk package - -The Android Java code implements an "Activity" and can be found in: -android-project/app/src/main/java/org/libsdl/app/SDLActivity.java - -The Java code loads your game code, the SDL shared library, and -dispatches to native functions implemented in the SDL library: -src/core/android/SDL_android.c - - -Building an app -================================================================================ - -For simple projects you can use the script located at build-scripts/androidbuild.sh - -There's two ways of using it: - - androidbuild.sh com.yourcompany.yourapp < sources.list - androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c - -sources.list should be a text file with a source file name in each line -Filenames should be specified relative to the current directory, for example if -you are in the build-scripts directory and want to create the testgles.c test, you'll -run: - - ./androidbuild.sh org.libsdl.testgles ../test/testgles.c - -One limitation of this script is that all sources provided will be aggregated into -a single directory, thus all your source files should have a unique name. - -Once the project is complete the script will tell you where the debug APK is located. -If you want to create a signed release APK, you can use the project created by this -utility to generate it. - -Finally, a word of caution: re running androidbuild.sh wipes any changes you may have -done in the build directory for the app! - - - -For more complex projects, follow these instructions: - -1. Get the source code for SDL and copy the 'android-project' directory located at SDL/android-project to a suitable location. Also make sure to rename it to your project name (In these examples: YOURPROJECT). - - (The 'android-project' directory can basically be seen as a sort of starting point for the android-port of your project. It contains the glue code between the Android Java 'frontend' and the SDL code 'backend'. It also contains some standard behaviour, like how events should be handled, which you will be able to change.) - -2. Move or [symlink](https://en.wikipedia.org/wiki/Symbolic_link) the SDL directory into the "YOURPROJECT/app/jni" directory - -(This is needed as the source of SDL has to be compiled by the Android compiler) - -3. Edit "YOURPROJECT/app/jni/src/Android.mk" to include your source files. - -(They should be separated by spaces after the "LOCAL_SRC_FILES := " declaration) - -4a. If you want to use Android Studio, simply open your 'YOURPROJECT' directory and start building. - -4b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device - - -If you already have a project that uses CMake, the instructions change somewhat: - -1. Do points 1 and 2 from the instruction above. -2. Edit "YOURPROJECT/app/build.gradle" to comment out or remove sections containing ndk-build - and uncomment the cmake sections. Add arguments to the CMake invocation as needed. -3. Edit "YOURPROJECT/app/jni/CMakeLists.txt" to include your project (it defaults to - adding the "src" subdirectory). Note that you'll have SDL3 and SDL3-static - as targets in your project, so you should have "target_link_libraries(yourgame SDL3)" - in your CMakeLists.txt file. Also be aware that you should use add_library() instead of - add_executable() for the target containing your "main" function. - -If you wish to use Android Studio, you can skip the last step. - -4. Run './gradlew installDebug' or './gradlew installRelease' in the project directory. It will build and install your .apk on any - connected Android device - -Here's an explanation of the files in the Android project, so you can customize them: - - android-project/app - build.gradle - build info including the application version and SDK - src/main/AndroidManifest.xml - package manifest. Among others, it contains the class name of the main Activity and the package name of the application. - jni/ - directory holding native code - jni/Application.mk - Application JNI settings, including target platform and STL library - jni/Android.mk - Android makefile that can call recursively the Android.mk files in all subdirectories - jni/CMakeLists.txt - Top-level CMake project that adds SDL as a subproject - jni/SDL/ - (symlink to) directory holding the SDL library files - jni/SDL/Android.mk - Android makefile for creating the SDL shared library - jni/src/ - directory holding your C/C++ source - jni/src/Android.mk - Android makefile that you should customize to include your source code and any library references - jni/src/CMakeLists.txt - CMake file that you may customize to include your source code and any library references - src/main/assets/ - directory holding asset files for your application - src/main/res/ - directory holding resources for your application - src/main/res/mipmap-* - directories holding icons for different phone hardware - src/main/res/values/strings.xml - strings used in your application, including the application name - src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application. - - -Customizing your application name -================================================================================ - -To customize your application name, edit AndroidManifest.xml and replace -"org.libsdl.app" with an identifier for your product package. - -Then create a Java class extending SDLActivity and place it in a directory -under src matching your package, e.g. - - src/com/gamemaker/game/MyGame.java - -Here's an example of a minimal class file: - - --- MyGame.java -------------------------- - package com.gamemaker.game; - - import org.libsdl.app.SDLActivity; - - /** - * A sample wrapper class that just calls SDLActivity - */ - - public class MyGame extends SDLActivity { } - - ------------------------------------------ - -Then replace "SDLActivity" in AndroidManifest.xml with the name of your -class, .e.g. "MyGame" - - -Customizing your application icon -================================================================================ - -Conceptually changing your icon is just replacing the "ic_launcher.png" files in -the drawable directories under the res directory. There are several directories -for different screen sizes. - - -Loading assets -================================================================================ - -Any files you put in the "app/src/main/assets" directory of your project -directory will get bundled into the application package and you can load -them using the standard functions in SDL_rwops.h. - -There are also a few Android specific functions that allow you to get other -useful paths for saving and loading data: -* SDL_AndroidGetInternalStoragePath() -* SDL_AndroidGetExternalStorageState() -* SDL_AndroidGetExternalStoragePath() - -See SDL_system.h for more details on these functions. - -The asset packaging system will, by default, compress certain file extensions. -SDL includes two asset file access mechanisms, the preferred one is the so -called "File Descriptor" method, which is faster and doesn't involve the Dalvik -GC, but given this method does not work on compressed assets, there is also the -"Input Stream" method, which is automatically used as a fall back by SDL. You -may want to keep this fact in mind when building your APK, specially when large -files are involved. -For more information on which extensions get compressed by default and how to -disable this behaviour, see for example: - -http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/ - - -Pause / Resume behaviour -================================================================================ - -If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default), -the event loop will block itself when the app is paused (ie, when the user -returns to the main Android dashboard). Blocking is better in terms of battery -use, and it allows your app to spring back to life instantaneously after resume -(versus polling for a resume message). - -Upon resume, SDL will attempt to restore the GL context automatically. -In modern devices (Android 3.0 and up) this will most likely succeed and your -app can continue to operate as it was. - -However, there's a chance (on older hardware, or on systems under heavy load), -where the GL context can not be restored. In that case you have to listen for -a specific message (SDL_EVENT_RENDER_DEVICE_RESET) and restore your textures -manually or quit the app. - -You should not use the SDL renderer API while the app going in background: -- SDL_EVENT_WILL_ENTER_BACKGROUND: - after you read this message, GL context gets backed-up and you should not - use the SDL renderer API. - - When this event is received, you have to set the render target to NULL, if you're using it. - (eg call SDL_SetRenderTarget(renderer, NULL)) - -- SDL_EVENT_DID_ENTER_FOREGROUND: - GL context is restored, and the SDL renderer API is available (unless you - receive SDL_EVENT_RENDER_DEVICE_RESET). - -Activity lifecycle -================================================================================ - -You can control activity re-creation (eg. onCreate()) behaviour. This allows to keep -or re-initialize java and native static datas, see SDL_hints.h: -- SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY - -Mouse / Touch events -================================================================================ - -In some case, SDL generates synthetic mouse (resp. touch) events for touch -(resp. mouse) devices. -To enable/disable this behavior, see SDL_hints.h: -- SDL_HINT_TOUCH_MOUSE_EVENTS -- SDL_HINT_MOUSE_TOUCH_EVENTS - -Misc -================================================================================ - -For some device, it appears to works better setting explicitly GL attributes -before creating a window: - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - -Threads and the Java VM -================================================================================ - -For a quick tour on how Linux native threads interoperate with the Java VM, take -a look here: https://developer.android.com/guide/practices/jni.html - -If you want to use threads in your SDL app, it's strongly recommended that you -do so by creating them using SDL functions. This way, the required attach/detach -handling is managed by SDL automagically. If you have threads created by other -means and they make calls to SDL functions, make sure that you call -Android_JNI_SetupThread() before doing anything else otherwise SDL will attach -your thread automatically anyway (when you make an SDL call), but it'll never -detach it. - - -If you ever want to use JNI in a native thread (created by "SDL_CreateThread()"), -it won't be able to find your java class and method because of the java class loader -which is different for native threads, than for java threads (eg your "main()"). - -the work-around is to find class/method, in you "main()" thread, and to use them -in your native thread. - -see: -https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class - -Using STL -================================================================================ - -You can use STL in your project by creating an Application.mk file in the jni -folder and adding the following line: - - APP_STL := c++_shared - -For more information go here: - https://developer.android.com/ndk/guides/cpp-support - - -Using the emulator -================================================================================ - -There are some good tips and tricks for getting the most out of the -emulator here: https://developer.android.com/tools/devices/emulator.html - -Especially useful is the info on setting up OpenGL ES 2.0 emulation. - -Notice that this software emulator is incredibly slow and needs a lot of disk space. -Using a real device works better. - - -Troubleshooting -================================================================================ - -You can see if adb can see any devices with the following command: - - adb devices - -You can see the output of log messages on the default device with: - - adb logcat - -You can push files to the device with: - - adb push local_file remote_path_and_file - -You can push files to the SD Card at /sdcard, for example: - - adb push moose.dat /sdcard/moose.dat - -You can see the files on the SD card with a shell command: - - adb shell ls /sdcard/ - -You can start a command shell on the default device with: - - adb shell - -You can remove the library files of your project (and not the SDL lib files) with: - - ndk-build clean - -You can do a build with the following command: - - ndk-build - -You can see the complete command line that ndk-build is using by passing V=1 on the command line: - - ndk-build V=1 - -If your application crashes in native code, you can use ndk-stack to get a symbolic stack trace: - https://developer.android.com/ndk/guides/ndk-stack - -If you want to go through the process manually, you can use addr2line to convert the -addresses in the stack trace to lines in your code. - -For example, if your crash looks like this: - - I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0 - I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4 - I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c - I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c - I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030 - I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so - I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so - I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so - I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so - -You can see that there's a crash in the C library being called from the main code. -I run addr2line with the debug version of my code: - - arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so - -and then paste in the number after "pc" in the call stack, from the line that I care about: -000014bc - -I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23. - -You can add logging to your code to help show what's happening: - - #include - - __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x); - -If you need to build without optimization turned on, you can create a file called -"Application.mk" in the jni directory, with the following line in it: - - APP_OPTIM := debug - - -Memory debugging -================================================================================ - -The best (and slowest) way to debug memory issues on Android is valgrind. -Valgrind has support for Android out of the box, just grab code using: - - svn co svn://svn.valgrind.org/valgrind/trunk valgrind - -... and follow the instructions in the file README.android to build it. - -One thing I needed to do on macOS was change the path to the toolchain, -and add ranlib to the environment variables: -export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib - -Once valgrind is built, you can create a wrapper script to launch your -application with it, changing org.libsdl.app to your package identifier: - - --- start_valgrind_app ------------------- - #!/system/bin/sh - export TMPDIR=/data/data/org.libsdl.app - exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $* - ------------------------------------------ - -Then push it to the device: - - adb push start_valgrind_app /data/local - -and make it executable: - - adb shell chmod 755 /data/local/start_valgrind_app - -and tell Android to use the script to launch your application: - - adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app" - -If the setprop command says "could not set property", it's likely that -your package name is too long and you should make it shorter by changing -AndroidManifest.xml and the path to your class file in android-project/src - -You can then launch your application normally and waaaaaaaiiittt for it. -You can monitor the startup process with the logcat command above, and -when it's done (or even while it's running) you can grab the valgrind -output file: - - adb pull /sdcard/valgrind.log - -When you're done instrumenting with valgrind, you can disable the wrapper: - - adb shell setprop wrap.org.libsdl.app "" - - -Graphics debugging -================================================================================ - -If you are developing on a compatible Tegra-based tablet, NVidia provides -Tegra Graphics Debugger at their website. Because SDL3 dynamically loads EGL -and GLES libraries, you must follow their instructions for installing the -interposer library on a rooted device. The non-rooted instructions are not -compatible with applications that use SDL3 for video. - -The Tegra Graphics Debugger is available from NVidia here: -https://developer.nvidia.com/tegra-graphics-debugger - - -Why is API level 19 the minimum required? -================================================================================ - -The latest NDK toolchain doesn't support targeting earlier than API level 19. -As of this writing, according to https://www.composables.com/tools/distribution-chart -about 99.7% of the Android devices accessing Google Play support API level 19 or -higher (August 2023). - - -A note regarding the use of the "dirty rectangles" rendering technique -================================================================================ - -If your app uses a variation of the "dirty rectangles" rendering technique, -where you only update a portion of the screen on each frame, you may notice a -variety of visual glitches on Android, that are not present on other platforms. -This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2 -contexts, in particular the use of the eglSwapBuffers function. As stated in the -documentation for the function "The contents of ancillary buffers are always -undefined after calling eglSwapBuffers". -Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED -is not possible for SDL as it requires EGL 1.4, available only on the API level -17+, so the only workaround available on this platform is to redraw the entire -screen each frame. - -Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html - - -Ending your application -================================================================================ - -Two legitimate ways: - -- return from your main() function. Java side will automatically terminate the -Activity by calling Activity.finish(). - -- Android OS can decide to terminate your application by calling onDestroy() -(see Activity life cycle). Your application will receive an SDL_EVENT_QUIT you -can handle to save things and quit. - -Don't call exit() as it stops the activity badly. - -NB: "Back button" can be handled as a SDL_EVENT_KEY_DOWN/UP events, with Keycode -SDLK_AC_BACK, for any purpose. - -Known issues -================================================================================ - -- The number of buttons reported for each joystick is hardcoded to be 36, which -is the current maximum number of buttons Android can report. - -Building the SDL tests -================================================================================ - -SDL's CMake build system can create APK's for the tests. -It can build all tests with a single command without a dependency on gradle or Android Studio. -The APK's are signed with a debug certificate. -The only caveat is that the APK's support a single architecture. - -### Requirements -- SDL source tree -- CMake -- ninja or make -- Android Platform SDK -- Android NDK -- Android Build tools -- Java JDK (version should be compatible with Android) -- keytool (usually provided with the Java JDK), used for generating a debug certificate -- zip - -### CMake configuration - -When configuring the CMake project, you need to use the Android NDK CMake toolchain, and pass the Android home path through `SDL_ANDROID_HOME`. -``` -cmake .. -DCMAKE_TOOLCHAIN_FILE= -DANDROID_ABI= -DSDL_ANDROID_HOME= -DANDROID_PLATFORM=23 -DSDL_TESTS=ON -``` - -Remarks: -- `android.toolchain.cmake` can usually be found at `$ANDROID_HOME/ndk/x.y.z/build/cmake/android.toolchain.cmake` -- `ANDROID_ABI` should be one of `arm64-v8a`, `armeabi-v7a`, `x86` or `x86_64`. -- When CMake is unable to find required paths, use `cmake-gui` to override required `SDL_ANDROID_` CMake cache variables. - -### Building the APK's - -For the `testsprite` executable, the `testsprite-apk` target will build the associated APK: -``` -cmake --build . --target testsprite-apk -``` - -APK's of all tests can be built with the `sdl-test-apks` target: -``` -cmake --build . --target sdl-test-apks -``` - -### Installation/removal of the tests - -`testsprite.apk` APK can be installed on your Android machine using the `install-testsprite` target: -``` -cmake --build . --target install-testsprite -``` - -APK's of all tests can be installed with the `install-sdl-test-apks` target: -``` -cmake --build . --target install-sdl-test-apks -``` - -All SDL tests can be uninstalled with the `uninstall-sdl-test-apks` target: -``` -cmake --build . --target uninstall-sdl-test-apks -``` - -### Starting the tests - -After installation, the tests can be started using the Android Launcher GUI. -Alternatively, they can also be started using CMake targets. - -This command will start the testsprite executable: -``` -cmake --build . --target start-testsprite -``` - -There is also a convenience target which will build, install and start a test: -``` -cmake --build . --target build-install-start-testsprite -``` - -Not all tests provide a GUI. For those, you can use `adb logcat` to read the output of stdout. +Android +================================================================================ + +Matt Styles wrote a tutorial on building SDL for Android with Visual Studio: +http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html + +The rest of this README covers the Android gradle style build process. + + +Requirements +================================================================================ + +Android SDK (version 34 or later) +https://developer.android.com/sdk/index.html + +Android NDK r15c or later +https://developer.android.com/tools/sdk/ndk/index.html + +Minimum API level supported by SDL: 19 (Android 4.4) + + +How the port works +================================================================================ + +- Android applications are Java-based, optionally with parts written in C +- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to + the SDL library +- This means that your application C code must be placed inside an Android + Java project, along with some C support code that communicates with Java +- This eventually produces a standard Android .apk package + +The Android Java code implements an "Activity" and can be found in: +android-project/app/src/main/java/org/libsdl/app/SDLActivity.java + +The Java code loads your game code, the SDL shared library, and +dispatches to native functions implemented in the SDL library: +src/core/android/SDL_android.c + + +Building an app +================================================================================ + +For simple projects you can use the script located at build-scripts/androidbuild.sh + +There's two ways of using it: + + androidbuild.sh com.yourcompany.yourapp < sources.list + androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c + +sources.list should be a text file with a source file name in each line +Filenames should be specified relative to the current directory, for example if +you are in the build-scripts directory and want to create the testgles.c test, you'll +run: + + ./androidbuild.sh org.libsdl.testgles ../test/testgles.c + +One limitation of this script is that all sources provided will be aggregated into +a single directory, thus all your source files should have a unique name. + +Once the project is complete the script will tell you where the debug APK is located. +If you want to create a signed release APK, you can use the project created by this +utility to generate it. + +Finally, a word of caution: re running androidbuild.sh wipes any changes you may have +done in the build directory for the app! + + + +For more complex projects, follow these instructions: + +1. Get the source code for SDL and copy the 'android-project' directory located at SDL/android-project to a suitable location. Also make sure to rename it to your project name (In these examples: YOURPROJECT). + + (The 'android-project' directory can basically be seen as a sort of starting point for the android-port of your project. It contains the glue code between the Android Java 'frontend' and the SDL code 'backend'. It also contains some standard behaviour, like how events should be handled, which you will be able to change.) + +2. Move or [symlink](https://en.wikipedia.org/wiki/Symbolic_link) the SDL directory into the "YOURPROJECT/app/jni" directory + +(This is needed as the source of SDL has to be compiled by the Android compiler) + +3. Edit "YOURPROJECT/app/jni/src/Android.mk" to include your source files. + +(They should be separated by spaces after the "LOCAL_SRC_FILES := " declaration) + +4a. If you want to use Android Studio, simply open your 'YOURPROJECT' directory and start building. + +4b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device + + +If you already have a project that uses CMake, the instructions change somewhat: + +1. Do points 1 and 2 from the instruction above. +2. Edit "YOURPROJECT/app/build.gradle" to comment out or remove sections containing ndk-build + and uncomment the cmake sections. Add arguments to the CMake invocation as needed. +3. Edit "YOURPROJECT/app/jni/CMakeLists.txt" to include your project (it defaults to + adding the "src" subdirectory). Note that you'll have SDL3 and SDL3-static + as targets in your project, so you should have "target_link_libraries(yourgame SDL3)" + in your CMakeLists.txt file. Also be aware that you should use add_library() instead of + add_executable() for the target containing your "main" function. + +If you wish to use Android Studio, you can skip the last step. + +4. Run './gradlew installDebug' or './gradlew installRelease' in the project directory. It will build and install your .apk on any + connected Android device + +Here's an explanation of the files in the Android project, so you can customize them: + + android-project/app + build.gradle - build info including the application version and SDK + src/main/AndroidManifest.xml - package manifest. Among others, it contains the class name of the main Activity and the package name of the application. + jni/ - directory holding native code + jni/Application.mk - Application JNI settings, including target platform and STL library + jni/Android.mk - Android makefile that can call recursively the Android.mk files in all subdirectories + jni/CMakeLists.txt - Top-level CMake project that adds SDL as a subproject + jni/SDL/ - (symlink to) directory holding the SDL library files + jni/SDL/Android.mk - Android makefile for creating the SDL shared library + jni/src/ - directory holding your C/C++ source + jni/src/Android.mk - Android makefile that you should customize to include your source code and any library references + jni/src/CMakeLists.txt - CMake file that you may customize to include your source code and any library references + src/main/assets/ - directory holding asset files for your application + src/main/res/ - directory holding resources for your application + src/main/res/mipmap-* - directories holding icons for different phone hardware + src/main/res/values/strings.xml - strings used in your application, including the application name + src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application. + + +Customizing your application name +================================================================================ + +To customize your application name, edit AndroidManifest.xml and replace +"org.libsdl.app" with an identifier for your product package. + +Then create a Java class extending SDLActivity and place it in a directory +under src matching your package, e.g. + + src/com/gamemaker/game/MyGame.java + +Here's an example of a minimal class file: + + --- MyGame.java -------------------------- + package com.gamemaker.game; + + import org.libsdl.app.SDLActivity; + + /** + * A sample wrapper class that just calls SDLActivity + */ + + public class MyGame extends SDLActivity { } + + ------------------------------------------ + +Then replace "SDLActivity" in AndroidManifest.xml with the name of your +class, .e.g. "MyGame" + + +Customizing your application icon +================================================================================ + +Conceptually changing your icon is just replacing the "ic_launcher.png" files in +the drawable directories under the res directory. There are several directories +for different screen sizes. + + +Loading assets +================================================================================ + +Any files you put in the "app/src/main/assets" directory of your project +directory will get bundled into the application package and you can load +them using the standard functions in SDL_rwops.h. + +There are also a few Android specific functions that allow you to get other +useful paths for saving and loading data: +* SDL_AndroidGetInternalStoragePath() +* SDL_AndroidGetExternalStorageState() +* SDL_AndroidGetExternalStoragePath() + +See SDL_system.h for more details on these functions. + +The asset packaging system will, by default, compress certain file extensions. +SDL includes two asset file access mechanisms, the preferred one is the so +called "File Descriptor" method, which is faster and doesn't involve the Dalvik +GC, but given this method does not work on compressed assets, there is also the +"Input Stream" method, which is automatically used as a fall back by SDL. You +may want to keep this fact in mind when building your APK, specially when large +files are involved. +For more information on which extensions get compressed by default and how to +disable this behaviour, see for example: + +http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/ + + +Pause / Resume behaviour +================================================================================ + +If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default), +the event loop will block itself when the app is paused (ie, when the user +returns to the main Android dashboard). Blocking is better in terms of battery +use, and it allows your app to spring back to life instantaneously after resume +(versus polling for a resume message). + +Upon resume, SDL will attempt to restore the GL context automatically. +In modern devices (Android 3.0 and up) this will most likely succeed and your +app can continue to operate as it was. + +However, there's a chance (on older hardware, or on systems under heavy load), +where the GL context can not be restored. In that case you have to listen for +a specific message (SDL_EVENT_RENDER_DEVICE_RESET) and restore your textures +manually or quit the app. + +You should not use the SDL renderer API while the app going in background: +- SDL_EVENT_WILL_ENTER_BACKGROUND: + after you read this message, GL context gets backed-up and you should not + use the SDL renderer API. + + When this event is received, you have to set the render target to NULL, if you're using it. + (eg call SDL_SetRenderTarget(renderer, NULL)) + +- SDL_EVENT_DID_ENTER_FOREGROUND: + GL context is restored, and the SDL renderer API is available (unless you + receive SDL_EVENT_RENDER_DEVICE_RESET). + +Activity lifecycle +================================================================================ + +You can control activity re-creation (eg. onCreate()) behaviour. This allows to keep +or re-initialize java and native static datas, see SDL_hints.h: +- SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY + +Mouse / Touch events +================================================================================ + +In some case, SDL generates synthetic mouse (resp. touch) events for touch +(resp. mouse) devices. +To enable/disable this behavior, see SDL_hints.h: +- SDL_HINT_TOUCH_MOUSE_EVENTS +- SDL_HINT_MOUSE_TOUCH_EVENTS + +Misc +================================================================================ + +For some device, it appears to works better setting explicitly GL attributes +before creating a window: + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + +Threads and the Java VM +================================================================================ + +For a quick tour on how Linux native threads interoperate with the Java VM, take +a look here: https://developer.android.com/guide/practices/jni.html + +If you want to use threads in your SDL app, it's strongly recommended that you +do so by creating them using SDL functions. This way, the required attach/detach +handling is managed by SDL automagically. If you have threads created by other +means and they make calls to SDL functions, make sure that you call +Android_JNI_SetupThread() before doing anything else otherwise SDL will attach +your thread automatically anyway (when you make an SDL call), but it'll never +detach it. + + +If you ever want to use JNI in a native thread (created by "SDL_CreateThread()"), +it won't be able to find your java class and method because of the java class loader +which is different for native threads, than for java threads (eg your "main()"). + +the work-around is to find class/method, in you "main()" thread, and to use them +in your native thread. + +see: +https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class + +Using STL +================================================================================ + +You can use STL in your project by creating an Application.mk file in the jni +folder and adding the following line: + + APP_STL := c++_shared + +For more information go here: + https://developer.android.com/ndk/guides/cpp-support + + +Using the emulator +================================================================================ + +There are some good tips and tricks for getting the most out of the +emulator here: https://developer.android.com/tools/devices/emulator.html + +Especially useful is the info on setting up OpenGL ES 2.0 emulation. + +Notice that this software emulator is incredibly slow and needs a lot of disk space. +Using a real device works better. + + +Troubleshooting +================================================================================ + +You can see if adb can see any devices with the following command: + + adb devices + +You can see the output of log messages on the default device with: + + adb logcat + +You can push files to the device with: + + adb push local_file remote_path_and_file + +You can push files to the SD Card at /sdcard, for example: + + adb push moose.dat /sdcard/moose.dat + +You can see the files on the SD card with a shell command: + + adb shell ls /sdcard/ + +You can start a command shell on the default device with: + + adb shell + +You can remove the library files of your project (and not the SDL lib files) with: + + ndk-build clean + +You can do a build with the following command: + + ndk-build + +You can see the complete command line that ndk-build is using by passing V=1 on the command line: + + ndk-build V=1 + +If your application crashes in native code, you can use ndk-stack to get a symbolic stack trace: + https://developer.android.com/ndk/guides/ndk-stack + +If you want to go through the process manually, you can use addr2line to convert the +addresses in the stack trace to lines in your code. + +For example, if your crash looks like this: + + I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0 + I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4 + I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c + I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c + I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030 + I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so + I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so + I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so + I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so + +You can see that there's a crash in the C library being called from the main code. +I run addr2line with the debug version of my code: + + arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so + +and then paste in the number after "pc" in the call stack, from the line that I care about: +000014bc + +I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23. + +You can add logging to your code to help show what's happening: + + #include + + __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x); + +If you need to build without optimization turned on, you can create a file called +"Application.mk" in the jni directory, with the following line in it: + + APP_OPTIM := debug + + +Memory debugging +================================================================================ + +The best (and slowest) way to debug memory issues on Android is valgrind. +Valgrind has support for Android out of the box, just grab code using: + + svn co svn://svn.valgrind.org/valgrind/trunk valgrind + +... and follow the instructions in the file README.android to build it. + +One thing I needed to do on macOS was change the path to the toolchain, +and add ranlib to the environment variables: +export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib + +Once valgrind is built, you can create a wrapper script to launch your +application with it, changing org.libsdl.app to your package identifier: + + --- start_valgrind_app ------------------- + #!/system/bin/sh + export TMPDIR=/data/data/org.libsdl.app + exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $* + ------------------------------------------ + +Then push it to the device: + + adb push start_valgrind_app /data/local + +and make it executable: + + adb shell chmod 755 /data/local/start_valgrind_app + +and tell Android to use the script to launch your application: + + adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app" + +If the setprop command says "could not set property", it's likely that +your package name is too long and you should make it shorter by changing +AndroidManifest.xml and the path to your class file in android-project/src + +You can then launch your application normally and waaaaaaaiiittt for it. +You can monitor the startup process with the logcat command above, and +when it's done (or even while it's running) you can grab the valgrind +output file: + + adb pull /sdcard/valgrind.log + +When you're done instrumenting with valgrind, you can disable the wrapper: + + adb shell setprop wrap.org.libsdl.app "" + + +Graphics debugging +================================================================================ + +If you are developing on a compatible Tegra-based tablet, NVidia provides +Tegra Graphics Debugger at their website. Because SDL3 dynamically loads EGL +and GLES libraries, you must follow their instructions for installing the +interposer library on a rooted device. The non-rooted instructions are not +compatible with applications that use SDL3 for video. + +The Tegra Graphics Debugger is available from NVidia here: +https://developer.nvidia.com/tegra-graphics-debugger + + +Why is API level 19 the minimum required? +================================================================================ + +The latest NDK toolchain doesn't support targeting earlier than API level 19. +As of this writing, according to https://www.composables.com/tools/distribution-chart +about 99.7% of the Android devices accessing Google Play support API level 19 or +higher (August 2023). + + +A note regarding the use of the "dirty rectangles" rendering technique +================================================================================ + +If your app uses a variation of the "dirty rectangles" rendering technique, +where you only update a portion of the screen on each frame, you may notice a +variety of visual glitches on Android, that are not present on other platforms. +This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2 +contexts, in particular the use of the eglSwapBuffers function. As stated in the +documentation for the function "The contents of ancillary buffers are always +undefined after calling eglSwapBuffers". +Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED +is not possible for SDL as it requires EGL 1.4, available only on the API level +17+, so the only workaround available on this platform is to redraw the entire +screen each frame. + +Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html + + +Ending your application +================================================================================ + +Two legitimate ways: + +- return from your main() function. Java side will automatically terminate the +Activity by calling Activity.finish(). + +- Android OS can decide to terminate your application by calling onDestroy() +(see Activity life cycle). Your application will receive an SDL_EVENT_QUIT you +can handle to save things and quit. + +Don't call exit() as it stops the activity badly. + +NB: "Back button" can be handled as a SDL_EVENT_KEY_DOWN/UP events, with Keycode +SDLK_AC_BACK, for any purpose. + +Known issues +================================================================================ + +- The number of buttons reported for each joystick is hardcoded to be 36, which +is the current maximum number of buttons Android can report. + +Building the SDL tests +================================================================================ + +SDL's CMake build system can create APK's for the tests. +It can build all tests with a single command without a dependency on gradle or Android Studio. +The APK's are signed with a debug certificate. +The only caveat is that the APK's support a single architecture. + +### Requirements +- SDL source tree +- CMake +- ninja or make +- Android Platform SDK +- Android NDK +- Android Build tools +- Java JDK (version should be compatible with Android) +- keytool (usually provided with the Java JDK), used for generating a debug certificate +- zip + +### CMake configuration + +When configuring the CMake project, you need to use the Android NDK CMake toolchain, and pass the Android home path through `SDL_ANDROID_HOME`. +``` +cmake .. -DCMAKE_TOOLCHAIN_FILE= -DANDROID_ABI= -DSDL_ANDROID_HOME= -DANDROID_PLATFORM=23 -DSDL_TESTS=ON +``` + +Remarks: +- `android.toolchain.cmake` can usually be found at `$ANDROID_HOME/ndk/x.y.z/build/cmake/android.toolchain.cmake` +- `ANDROID_ABI` should be one of `arm64-v8a`, `armeabi-v7a`, `x86` or `x86_64`. +- When CMake is unable to find required paths, use `cmake-gui` to override required `SDL_ANDROID_` CMake cache variables. + +### Building the APK's + +For the `testsprite` executable, the `testsprite-apk` target will build the associated APK: +``` +cmake --build . --target testsprite-apk +``` + +APK's of all tests can be built with the `sdl-test-apks` target: +``` +cmake --build . --target sdl-test-apks +``` + +### Installation/removal of the tests + +`testsprite.apk` APK can be installed on your Android machine using the `install-testsprite` target: +``` +cmake --build . --target install-testsprite +``` + +APK's of all tests can be installed with the `install-sdl-test-apks` target: +``` +cmake --build . --target install-sdl-test-apks +``` + +All SDL tests can be uninstalled with the `uninstall-sdl-test-apks` target: +``` +cmake --build . --target uninstall-sdl-test-apks +``` + +### Starting the tests + +After installation, the tests can be started using the Android Launcher GUI. +Alternatively, they can also be started using CMake targets. + +This command will start the testsprite executable: +``` +cmake --build . --target start-testsprite +``` + +There is also a convenience target which will build, install and start a test: +``` +cmake --build . --target build-install-start-testsprite +``` + +Not all tests provide a GUI. For those, you can use `adb logcat` to read the output of stdout. diff --git a/docs/README-cmake.md b/docs/README-cmake.md index 4accbcf58efcb..337a41ab089ad 100644 --- a/docs/README-cmake.md +++ b/docs/README-cmake.md @@ -1,328 +1,328 @@ -# CMake - -[www.cmake.org](https://www.cmake.org/) - -The CMake build system is supported on the following platforms: - -* FreeBSD -* Linux -* Microsoft Visual C -* MinGW and Msys -* macOS, iOS, and tvOS, with support for XCode -* Android -* Emscripten -* FreeBSD -* Haiku -* Nintendo 3DS -* Playstation 2 -* Playstation Vita -* QNX 7.x/8.x -* RiscOS - -## Building SDL - -Assuming the source tree of SDL is located at `~/sdl`, -this will configure and build SDL in the `~/build` directory: -```sh -cmake -S ~/sdl -B ~/build -cmake --build ~/build -``` - -Installation can be done using: -```sh -cmake --install ~/build --prefix /usr/local # '--install' requires CMake 3.15, or newer -``` - -This will install SDL to /usr/local. - -### Building SDL tests - -You can build the SDL test programs by adding `-DSDL_TESTS=ON` to the first cmake command above: -```sh -cmake -S ~/sdl -B ~/build -DSDL_TEST_LIBRARY=ON -DSDL_TESTS=ON -``` -and then building normally. In this example, the test programs will be built and can be run from `~/build/tests/`. - -## Including SDL in your project - -SDL can be included in your project in 2 major ways: -- using a system SDL library, provided by your (*nix) distribution or a package manager -- using a vendored SDL library: this is SDL copied or symlinked in a subfolder. - -The following CMake script supports both, depending on the value of `MYGAME_VENDORED`. - -```cmake -cmake_minimum_required(VERSION 3.5) -project(mygame) - -# Create an option to switch between a system sdl library and a vendored SDL library -option(MYGAME_VENDORED "Use vendored libraries" OFF) - -if(MYGAME_VENDORED) - # This assumes you have added SDL as a submodule in vendored/SDL - add_subdirectory(vendored/SDL EXCLUDE_FROM_ALL) -else() - # 1. Look for a SDL3 package, - # 2. look for the SDL3-shared component, and - # 3. fail if the shared component cannot be found. - find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared) -endif() - -# Create your game executable target as usual -add_executable(mygame WIN32 mygame.c) - -# Link to the actual SDL3 library. -target_link_libraries(mygame PRIVATE SDL3::SDL3) -``` - -### A system SDL library - -For CMake to find SDL, it must be installed in [a default location CMake is looking for](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure). - -The following components are available, to be used as an argument of `find_package`. - -| Component name | Description | -|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| SDL3-shared | The SDL3 shared library, available through the `SDL3::SDL3-shared` target | -| SDL3-static | The SDL3 static library, available through the `SDL3::SDL3-static` target | -| SDL3_test | The SDL3_test static library, available through the `SDL3::SDL3_test` target | -| SDL3 | The SDL3 library, available through the `SDL3::SDL3` target. This is an alias of `SDL3::SDL3-shared` or `SDL3::SDL3-static`. This component is always available. | -| Headers | The SDL3 headers, available through the `SDL3::Headers` target. This component is always available. | - - -### Using a vendored SDL - -This only requires a copy of SDL in a subdirectory + `add_subdirectory`. -Alternatively, use [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html). -Depending on the configuration, the same targets as a system SDL package are available. - -## CMake configuration options - -### Build optimized library - -By default, CMake provides 4 build types: `Debug`, `Release`, `RelWithDebInfo` and `MinSizeRel`. -The main difference(s) between these are the optimization options and the generation of debug info. -To configure SDL as an optimized `Release` library, configure SDL with: -```sh -cmake ~/SDL -DCMAKE_BUILD_TYPE=Release -``` -To build it, run: -```sh -cmake --build . --config Release -``` - -### Shared or static - -By default, only a shared SDL library is built and installed. -The options `-DSDL_SHARED=` and `-DSDL_STATIC=` accept boolean values to change this. - -### Pass custom compile options to the compiler - -- Use [`CMAKE__FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS.html) to pass extra -flags to the compiler. -- Use [`CMAKE_EXE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS.html) to pass extra option to the linker for executables. -- Use [`CMAKE_SHARED_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS.html) to pass extra options to the linker for shared libraries. - -#### Examples - -- build a SDL library optimized for (more) modern x64 microprocessor architectures. - - With gcc or clang: - ```sh - cmake ~/sdl -DCMAKE_C_FLAGS="-march=x86-64-v3" -DCMAKE_CXX_FLAGS="-march=x86-64-v3" - ``` - With Visual C: - ```sh - cmake .. -DCMAKE_C_FLAGS="/ARCH:AVX2" -DCMAKE_CXX_FLAGS="/ARCH:AVX2" - ``` - -### iOS/tvOS - -CMake 3.14+ natively includes support for iOS and tvOS. SDL binaries may be built -using Xcode or Make, possibly among other build-systems. - -When using a recent version of CMake (3.14+), it should be possible to: - -- build SDL for iOS, both static and dynamic -- build SDL test apps (as iOS/tvOS .app bundles) -- generate a working SDL_build_config.h for iOS (using SDL_build_config.h.cmake as a basis) - -To use, set the following CMake variables when running CMake's configuration stage: - -- `CMAKE_SYSTEM_NAME=` (either `iOS` or `tvOS`) -- `CMAKE_OSX_SYSROOT=` (examples: `iphoneos`, `iphonesimulator`, `iphoneos12.4`, `/full/path/to/iPhoneOS.sdk`, - `appletvos`, `appletvsimulator`, `appletvos12.4`, `/full/path/to/AppleTVOS.sdk`, etc.) -- `CMAKE_OSX_ARCHITECTURES=` (example: "arm64;armv7s;x86_64") - - -#### Examples - -- for iOS-Simulator, using the latest, installed SDK: - - ```bash - cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 - ``` - -- for iOS-Device, using the latest, installed SDK, 64-bit only - - ```bash - cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES=arm64 - ``` - -- for iOS-Device, using the latest, installed SDK, mixed 32/64 bit - - ```cmake - cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES="arm64;armv7s" - ``` - -- for iOS-Device, using a specific SDK revision (iOS 12.4, in this example): - - ```cmake - cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos12.4 -DCMAKE_OSX_ARCHITECTURES=arm64 - ``` - -- for iOS-Simulator, using the latest, installed SDK, and building SDL test apps (as .app bundles): - - ```cmake - cmake ~/sdl -DSDL_TESTS=1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 - ``` - -- for tvOS-Simulator, using the latest, installed SDK: - - ```cmake - cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 - ``` - -- for tvOS-Device, using the latest, installed SDK: - - ```cmake - cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_ARCHITECTURES=arm64` - ``` - -- for QNX/aarch64, using the latest, installed SDK: - - ```cmake - cmake ~/sdl -DCMAKE_TOOLCHAIN_FILE=~/sdl/build-scripts/cmake-toolchain-qnx-aarch64le.cmake -DSDL_X11=0 - ``` - -## SDL-specific CMake options - -SDL can be customized through (platform-specific) CMake options. -The following table shows generic options that are available for most platforms. -At the end of SDL CMake configuration, a table shows all CMake options along with its detected value. - -| CMake option | Valid values | Description | -|-------------------------------|--------------|-----------------------------------------------------------------------------------------------------| -| `-DSDL_SHARED=` | `ON`/`OFF` | Build SDL shared library (not all platforms support this) (`libSDL3.so`/`libSDL3.dylib`/`SDL3.dll`) | -| `-DSDL_STATIC=` | `ON`/`OFF` | Build SDL static library (`libSDL3.a`/`SDL3-static.lib`) | -| `-DSDL_TEST_LIBRARY=` | `ON`/`OFF` | Build SDL test library (`libSDL3_test.a`/`SDL3_test.lib`) | -| `-DSDL_TESTS=` | `ON`/`OFF` | Build SDL test programs (**requires `-DSDL_TEST_LIBRARY=ON`**) | -| `-DSDL_DISABLE_INSTALL=` | `ON`/`OFF` | Don't create a SDL install target | -| `-DSDL_DISABLE_INSTALL_DOCS=` | `ON`/`OFF` | Don't install the SDL documentation | -| `-DSDL_INSTALL_TESTS=` | `ON`/`OFF` | Install the SDL test programs | - -## Help, it doesn't work! - -Below, a SDL3 CMake project can be found that builds 99.9% of time (assuming you have internet connectivity). -When you have a problem with building or using SDL, please modify it until it reproduces your issue. - -```cmake -cmake_minimum_required(VERSION 3.16) -project(sdl_issue) - -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# !!!!!! !!!!!! -# !!!!!! This CMake script is not using "CMake best practices". !!!!!! -# !!!!!! Don't use it in your project. !!!!!! -# !!!!!! !!!!!! -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -# 1. Try system SDL3 package first -find_package(SDL3 QUIET) -if(SDL3_FOUND) - message(STATUS "Using SDL3 via find_package") -endif() - -# 2. Try using a vendored SDL library -if(NOT SDL3_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL/CMakeLists.txt") - add_subdirectory(SDL) - message(STATUS "Using SDL3 via add_subdirectory") - set(SDL3_FOUND TRUE) -endif() - -# 3. Download SDL, and use that. -if(NOT SDL3_FOUND) - include(FetchContent) - set(SDL_SHARED TRUE CACHE BOOL "Build a SDL shared library (if available)") - set(SDL_STATIC TRUE CACHE BOOL "Build a SDL static library (if available)") - FetchContent_Declare( - SDL - GIT_REPOSITORY https://github.com/libsdl-org/SDL.git - GIT_TAG main # Replace this with a particular git tag or git hash - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - ) - message(STATUS "Using SDL3 via FetchContent") - FetchContent_MakeAvailable(SDL) - set_property(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_deps/sdl-src" PROPERTY EXCLUDE_FROM_ALL TRUE) -endif() - -file(WRITE main.c [===========================================[ -/** - * Modify this source such that it reproduces your problem. - */ - -/* START of source modifications */ - -#include - -int main(int argc, char *argv[]) { - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { - SDL_Log("SDL_Init failed (%s)", SDL_GetError()); - return 1; - } - - SDL_Window *window = NULL; - SDL_Renderer *renderer = NULL; - - if (SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer) < 0) { - SDL_Log("SDL_CreateWindowAndRenderer failed (%s)", SDL_GetError()); - SDL_Quit(); - return 1; - } - SDL_SetWindowTitle(window, "SDL issue"); - - while (1) { - int finished = 0; - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_EVENT_QUIT) { - finished = 1; - break; - } - } - if (finished) { - break; - } - - SDL_SetRenderDrawColor(renderer, 80, 80, 80, SDL_ALPHA_OPAQUE); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - } - - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - - SDL_Quit(); -} - -/* END of source modifications */ - -]===========================================]) - -add_executable(sdl_issue main.c) - -target_link_libraries(sdl_issue PRIVATE SDL3::SDL3) -# target_link_libraries(sdl_issue PRIVATE SDL3::SDL3-shared) -# target_link_libraries(sdl_issue PRIVATE SDL3::SDL3-static) -``` +# CMake + +[www.cmake.org](https://www.cmake.org/) + +The CMake build system is supported on the following platforms: + +* FreeBSD +* Linux +* Microsoft Visual C +* MinGW and Msys +* macOS, iOS, and tvOS, with support for XCode +* Android +* Emscripten +* FreeBSD +* Haiku +* Nintendo 3DS +* Playstation 2 +* Playstation Vita +* QNX 7.x/8.x +* RiscOS + +## Building SDL + +Assuming the source tree of SDL is located at `~/sdl`, +this will configure and build SDL in the `~/build` directory: +```sh +cmake -S ~/sdl -B ~/build +cmake --build ~/build +``` + +Installation can be done using: +```sh +cmake --install ~/build --prefix /usr/local # '--install' requires CMake 3.15, or newer +``` + +This will install SDL to /usr/local. + +### Building SDL tests + +You can build the SDL test programs by adding `-DSDL_TESTS=ON` to the first cmake command above: +```sh +cmake -S ~/sdl -B ~/build -DSDL_TEST_LIBRARY=ON -DSDL_TESTS=ON +``` +and then building normally. In this example, the test programs will be built and can be run from `~/build/tests/`. + +## Including SDL in your project + +SDL can be included in your project in 2 major ways: +- using a system SDL library, provided by your (*nix) distribution or a package manager +- using a vendored SDL library: this is SDL copied or symlinked in a subfolder. + +The following CMake script supports both, depending on the value of `MYGAME_VENDORED`. + +```cmake +cmake_minimum_required(VERSION 3.5) +project(mygame) + +# Create an option to switch between a system sdl library and a vendored SDL library +option(MYGAME_VENDORED "Use vendored libraries" OFF) + +if(MYGAME_VENDORED) + # This assumes you have added SDL as a submodule in vendored/SDL + add_subdirectory(vendored/SDL EXCLUDE_FROM_ALL) +else() + # 1. Look for a SDL3 package, + # 2. look for the SDL3-shared component, and + # 3. fail if the shared component cannot be found. + find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared) +endif() + +# Create your game executable target as usual +add_executable(mygame WIN32 mygame.c) + +# Link to the actual SDL3 library. +target_link_libraries(mygame PRIVATE SDL3::SDL3) +``` + +### A system SDL library + +For CMake to find SDL, it must be installed in [a default location CMake is looking for](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure). + +The following components are available, to be used as an argument of `find_package`. + +| Component name | Description | +|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| SDL3-shared | The SDL3 shared library, available through the `SDL3::SDL3-shared` target | +| SDL3-static | The SDL3 static library, available through the `SDL3::SDL3-static` target | +| SDL3_test | The SDL3_test static library, available through the `SDL3::SDL3_test` target | +| SDL3 | The SDL3 library, available through the `SDL3::SDL3` target. This is an alias of `SDL3::SDL3-shared` or `SDL3::SDL3-static`. This component is always available. | +| Headers | The SDL3 headers, available through the `SDL3::Headers` target. This component is always available. | + + +### Using a vendored SDL + +This only requires a copy of SDL in a subdirectory + `add_subdirectory`. +Alternatively, use [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html). +Depending on the configuration, the same targets as a system SDL package are available. + +## CMake configuration options + +### Build optimized library + +By default, CMake provides 4 build types: `Debug`, `Release`, `RelWithDebInfo` and `MinSizeRel`. +The main difference(s) between these are the optimization options and the generation of debug info. +To configure SDL as an optimized `Release` library, configure SDL with: +```sh +cmake ~/SDL -DCMAKE_BUILD_TYPE=Release +``` +To build it, run: +```sh +cmake --build . --config Release +``` + +### Shared or static + +By default, only a shared SDL library is built and installed. +The options `-DSDL_SHARED=` and `-DSDL_STATIC=` accept boolean values to change this. + +### Pass custom compile options to the compiler + +- Use [`CMAKE__FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS.html) to pass extra +flags to the compiler. +- Use [`CMAKE_EXE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS.html) to pass extra option to the linker for executables. +- Use [`CMAKE_SHARED_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS.html) to pass extra options to the linker for shared libraries. + +#### Examples + +- build a SDL library optimized for (more) modern x64 microprocessor architectures. + + With gcc or clang: + ```sh + cmake ~/sdl -DCMAKE_C_FLAGS="-march=x86-64-v3" -DCMAKE_CXX_FLAGS="-march=x86-64-v3" + ``` + With Visual C: + ```sh + cmake .. -DCMAKE_C_FLAGS="/ARCH:AVX2" -DCMAKE_CXX_FLAGS="/ARCH:AVX2" + ``` + +### iOS/tvOS + +CMake 3.14+ natively includes support for iOS and tvOS. SDL binaries may be built +using Xcode or Make, possibly among other build-systems. + +When using a recent version of CMake (3.14+), it should be possible to: + +- build SDL for iOS, both static and dynamic +- build SDL test apps (as iOS/tvOS .app bundles) +- generate a working SDL_build_config.h for iOS (using SDL_build_config.h.cmake as a basis) + +To use, set the following CMake variables when running CMake's configuration stage: + +- `CMAKE_SYSTEM_NAME=` (either `iOS` or `tvOS`) +- `CMAKE_OSX_SYSROOT=` (examples: `iphoneos`, `iphonesimulator`, `iphoneos12.4`, `/full/path/to/iPhoneOS.sdk`, + `appletvos`, `appletvsimulator`, `appletvos12.4`, `/full/path/to/AppleTVOS.sdk`, etc.) +- `CMAKE_OSX_ARCHITECTURES=` (example: "arm64;armv7s;x86_64") + + +#### Examples + +- for iOS-Simulator, using the latest, installed SDK: + + ```bash + cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 + ``` + +- for iOS-Device, using the latest, installed SDK, 64-bit only + + ```bash + cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES=arm64 + ``` + +- for iOS-Device, using the latest, installed SDK, mixed 32/64 bit + + ```cmake + cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES="arm64;armv7s" + ``` + +- for iOS-Device, using a specific SDK revision (iOS 12.4, in this example): + + ```cmake + cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos12.4 -DCMAKE_OSX_ARCHITECTURES=arm64 + ``` + +- for iOS-Simulator, using the latest, installed SDK, and building SDL test apps (as .app bundles): + + ```cmake + cmake ~/sdl -DSDL_TESTS=1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 + ``` + +- for tvOS-Simulator, using the latest, installed SDK: + + ```cmake + cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=x86_64 + ``` + +- for tvOS-Device, using the latest, installed SDK: + + ```cmake + cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_ARCHITECTURES=arm64` + ``` + +- for QNX/aarch64, using the latest, installed SDK: + + ```cmake + cmake ~/sdl -DCMAKE_TOOLCHAIN_FILE=~/sdl/build-scripts/cmake-toolchain-qnx-aarch64le.cmake -DSDL_X11=0 + ``` + +## SDL-specific CMake options + +SDL can be customized through (platform-specific) CMake options. +The following table shows generic options that are available for most platforms. +At the end of SDL CMake configuration, a table shows all CMake options along with its detected value. + +| CMake option | Valid values | Description | +|-------------------------------|--------------|-----------------------------------------------------------------------------------------------------| +| `-DSDL_SHARED=` | `ON`/`OFF` | Build SDL shared library (not all platforms support this) (`libSDL3.so`/`libSDL3.dylib`/`SDL3.dll`) | +| `-DSDL_STATIC=` | `ON`/`OFF` | Build SDL static library (`libSDL3.a`/`SDL3-static.lib`) | +| `-DSDL_TEST_LIBRARY=` | `ON`/`OFF` | Build SDL test library (`libSDL3_test.a`/`SDL3_test.lib`) | +| `-DSDL_TESTS=` | `ON`/`OFF` | Build SDL test programs (**requires `-DSDL_TEST_LIBRARY=ON`**) | +| `-DSDL_DISABLE_INSTALL=` | `ON`/`OFF` | Don't create a SDL install target | +| `-DSDL_DISABLE_INSTALL_DOCS=` | `ON`/`OFF` | Don't install the SDL documentation | +| `-DSDL_INSTALL_TESTS=` | `ON`/`OFF` | Install the SDL test programs | + +## Help, it doesn't work! + +Below, a SDL3 CMake project can be found that builds 99.9% of time (assuming you have internet connectivity). +When you have a problem with building or using SDL, please modify it until it reproduces your issue. + +```cmake +cmake_minimum_required(VERSION 3.16) +project(sdl_issue) + +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# !!!!!! !!!!!! +# !!!!!! This CMake script is not using "CMake best practices". !!!!!! +# !!!!!! Don't use it in your project. !!!!!! +# !!!!!! !!!!!! +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +# 1. Try system SDL3 package first +find_package(SDL3 QUIET) +if(SDL3_FOUND) + message(STATUS "Using SDL3 via find_package") +endif() + +# 2. Try using a vendored SDL library +if(NOT SDL3_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL/CMakeLists.txt") + add_subdirectory(SDL) + message(STATUS "Using SDL3 via add_subdirectory") + set(SDL3_FOUND TRUE) +endif() + +# 3. Download SDL, and use that. +if(NOT SDL3_FOUND) + include(FetchContent) + set(SDL_SHARED TRUE CACHE BOOL "Build a SDL shared library (if available)") + set(SDL_STATIC TRUE CACHE BOOL "Build a SDL static library (if available)") + FetchContent_Declare( + SDL + GIT_REPOSITORY https://github.com/libsdl-org/SDL.git + GIT_TAG main # Replace this with a particular git tag or git hash + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + ) + message(STATUS "Using SDL3 via FetchContent") + FetchContent_MakeAvailable(SDL) + set_property(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_deps/sdl-src" PROPERTY EXCLUDE_FROM_ALL TRUE) +endif() + +file(WRITE main.c [===========================================[ +/** + * Modify this source such that it reproduces your problem. + */ + +/* START of source modifications */ + +#include + +int main(int argc, char *argv[]) { + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + SDL_Log("SDL_Init failed (%s)", SDL_GetError()); + return 1; + } + + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + + if (SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer) < 0) { + SDL_Log("SDL_CreateWindowAndRenderer failed (%s)", SDL_GetError()); + SDL_Quit(); + return 1; + } + SDL_SetWindowTitle(window, "SDL issue"); + + while (1) { + int finished = 0; + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT) { + finished = 1; + break; + } + } + if (finished) { + break; + } + + SDL_SetRenderDrawColor(renderer, 80, 80, 80, SDL_ALPHA_OPAQUE); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + + SDL_Quit(); +} + +/* END of source modifications */ + +]===========================================]) + +add_executable(sdl_issue main.c) + +target_link_libraries(sdl_issue PRIVATE SDL3::SDL3) +# target_link_libraries(sdl_issue PRIVATE SDL3::SDL3-shared) +# target_link_libraries(sdl_issue PRIVATE SDL3::SDL3-static) +``` diff --git a/docs/README-contributing.md b/docs/README-contributing.md index 63b60cdd655a9..347f0f825a39a 100644 --- a/docs/README-contributing.md +++ b/docs/README-contributing.md @@ -1,97 +1,97 @@ -# Contributing to SDL - -We appreciate your interest in contributing to SDL, this document will describe how to report bugs, contribute code or ideas or edit documentation. - -**Table Of Contents** - -- [Filing a GitHub issue](#filing-a-github-issue) - - [Reporting a bug](#reporting-a-bug) - - [Suggesting enhancements](#suggesting-enhancements) -- [Contributing code](#contributing-code) - - [Forking the project](#forking-the-project) - - [Following the style guide](#following-the-style-guide) - - [Running the tests](#running-the-tests) - - [Opening a pull request](#opening-a-pull-request) -- [Contributing to the documentation](#contributing-to-the-documentation) - - [Editing a function documentation](#editing-a-function-documentation) - - [Editing the wiki](#editing-the-wiki) - -## Filing a GitHub issue - -### Reporting a bug - -If you think you have found a bug and would like to report it, here are the steps you should take: - -- Before opening a new issue, ensure your bug has not already been reported on the [GitHub Issues page](https://github.com/libsdl-org/SDL/issues). -- On the issue tracker, click on [New Issue](https://github.com/libsdl-org/SDL/issues/new). -- Include details about your environment, such as your Operating System and SDL version. -- If possible, provide a small example that reproduces your bug. - -### Suggesting enhancements - -If you want to suggest changes for the project, here are the steps you should take: - -- Check if the suggestion has already been made on: - - the [issue tracker](https://github.com/libsdl-org/SDL/issues); - - the [discourse forum](https://discourse.libsdl.org/); - - or if a [pull request](https://github.com/libsdl-org/SDL/pulls) already exists. -- On the issue tracker, click on [New Issue](https://github.com/libsdl-org/SDL/issues/new). -- Describe what change you would like to happen. - -## Contributing code - -This section will cover how the process of forking the project, making a change and opening a pull request. - -### Forking the project - -The first step consists in making a fork of the project, this is only necessary for the first contribution. - -Head over to https://github.com/libsdl-org/SDL and click on the `Fork` button in the top right corner of your screen, you may leave the fields unchanged and click `Create Fork`. - -You will be redirected to your fork of the repository, click the green `Code` button and copy the git clone link. - -If you had already forked the repository, you may update it from the web page using the `Fetch upstream` button. - -### Following the style guide - -Code formatting is done using a custom `.clang-format` file, you can learn more about how to run it [here](https://clang.llvm.org/docs/ClangFormat.html). - -Some legacy code may not be formatted, as such avoid formatting the whole file at once and only format around your changes. - -For your commit message to be properly displayed on GitHub, it should contain: - -- A short description of the commit of 50 characters or less on the first line. -- If necessary, add a blank line followed by a long description, each line should be 72 characters or less. - -For example: - -``` -Fix crash in SDL_FooBar. - -This addresses the issue #123456 by making sure Foo was successful -before calling Bar. -``` - -### Running the tests - -Tests allow you to verify if your changes did not break any behaviour, here are the steps to follow: - -- Before pushing, run the `testautomation` suite on your machine, there should be no more failing tests after your change than before. -- After pushing to your fork, Continuous Integration (GitHub Actions) will ensure compilation and tests still pass on other systems. - -### Opening a pull request - -- Head over to your fork's GitHub page. -- Click on the `Contribute` button and `Open Pull Request`. -- Fill out the pull request template. -- If any changes are requested, you can add new commits to your fork and they will be automatically added to the pull request. - -## Contributing to the documentation - -### Editing a function documentation - -The wiki documentation for API functions is synchronised from the headers' doxygen comments. As such, all modifications to syntax; function parameters; return value; version; related functions should be done in the header directly. - -### Editing the wiki - -Other changes to the wiki should done directly from https://wiki.libsdl.org/ ... Just click the "edit" link at the bottom of any page! +# Contributing to SDL + +We appreciate your interest in contributing to SDL, this document will describe how to report bugs, contribute code or ideas or edit documentation. + +**Table Of Contents** + +- [Filing a GitHub issue](#filing-a-github-issue) + - [Reporting a bug](#reporting-a-bug) + - [Suggesting enhancements](#suggesting-enhancements) +- [Contributing code](#contributing-code) + - [Forking the project](#forking-the-project) + - [Following the style guide](#following-the-style-guide) + - [Running the tests](#running-the-tests) + - [Opening a pull request](#opening-a-pull-request) +- [Contributing to the documentation](#contributing-to-the-documentation) + - [Editing a function documentation](#editing-a-function-documentation) + - [Editing the wiki](#editing-the-wiki) + +## Filing a GitHub issue + +### Reporting a bug + +If you think you have found a bug and would like to report it, here are the steps you should take: + +- Before opening a new issue, ensure your bug has not already been reported on the [GitHub Issues page](https://github.com/libsdl-org/SDL/issues). +- On the issue tracker, click on [New Issue](https://github.com/libsdl-org/SDL/issues/new). +- Include details about your environment, such as your Operating System and SDL version. +- If possible, provide a small example that reproduces your bug. + +### Suggesting enhancements + +If you want to suggest changes for the project, here are the steps you should take: + +- Check if the suggestion has already been made on: + - the [issue tracker](https://github.com/libsdl-org/SDL/issues); + - the [discourse forum](https://discourse.libsdl.org/); + - or if a [pull request](https://github.com/libsdl-org/SDL/pulls) already exists. +- On the issue tracker, click on [New Issue](https://github.com/libsdl-org/SDL/issues/new). +- Describe what change you would like to happen. + +## Contributing code + +This section will cover how the process of forking the project, making a change and opening a pull request. + +### Forking the project + +The first step consists in making a fork of the project, this is only necessary for the first contribution. + +Head over to https://github.com/libsdl-org/SDL and click on the `Fork` button in the top right corner of your screen, you may leave the fields unchanged and click `Create Fork`. + +You will be redirected to your fork of the repository, click the green `Code` button and copy the git clone link. + +If you had already forked the repository, you may update it from the web page using the `Fetch upstream` button. + +### Following the style guide + +Code formatting is done using a custom `.clang-format` file, you can learn more about how to run it [here](https://clang.llvm.org/docs/ClangFormat.html). + +Some legacy code may not be formatted, as such avoid formatting the whole file at once and only format around your changes. + +For your commit message to be properly displayed on GitHub, it should contain: + +- A short description of the commit of 50 characters or less on the first line. +- If necessary, add a blank line followed by a long description, each line should be 72 characters or less. + +For example: + +``` +Fix crash in SDL_FooBar. + +This addresses the issue #123456 by making sure Foo was successful +before calling Bar. +``` + +### Running the tests + +Tests allow you to verify if your changes did not break any behaviour, here are the steps to follow: + +- Before pushing, run the `testautomation` suite on your machine, there should be no more failing tests after your change than before. +- After pushing to your fork, Continuous Integration (GitHub Actions) will ensure compilation and tests still pass on other systems. + +### Opening a pull request + +- Head over to your fork's GitHub page. +- Click on the `Contribute` button and `Open Pull Request`. +- Fill out the pull request template. +- If any changes are requested, you can add new commits to your fork and they will be automatically added to the pull request. + +## Contributing to the documentation + +### Editing a function documentation + +The wiki documentation for API functions is synchronised from the headers' doxygen comments. As such, all modifications to syntax; function parameters; return value; version; related functions should be done in the header directly. + +### Editing the wiki + +Other changes to the wiki should done directly from https://wiki.libsdl.org/ ... Just click the "edit" link at the bottom of any page! diff --git a/docs/README-dynapi.md b/docs/README-dynapi.md index a0f3412447ddd..665b7c65ea00a 100644 --- a/docs/README-dynapi.md +++ b/docs/README-dynapi.md @@ -1,138 +1,138 @@ -# Dynamic API - -Originally posted on Ryan's Google+ account. - -Background: - -- The Steam Runtime has (at least in theory) a really kick-ass build of SDL, - but developers are shipping their own SDL with individual Steam games. - These games might stop getting updates, but a newer SDL might be needed later. - Certainly we'll always be fixing bugs in SDL, even if a new video target isn't - ever needed, and these fixes won't make it to a game shipping its own SDL. -- Even if we replace the SDL in those games with a compatible one, that is to - say, edit a developer's Steam depot (yuck!), there are developers that are - statically linking SDL that we can't do this for. We can't even force the - dynamic loader to ignore their SDL in this case, of course. -- If you don't ship an SDL with the game in some form, people that disabled the - Steam Runtime, or just tried to run the game from the command line instead of - Steam might find themselves unable to run the game, due to a missing dependency. -- If you want to ship on non-Steam platforms like GOG or Humble Bundle, or target - generic Linux boxes that may or may not have SDL installed, you have to ship - the library or risk a total failure to launch. So now, you might have to have - a non-Steam build plus a Steam build (that is, one with and one without SDL - included), which is inconvenient if you could have had one universal build - that works everywhere. -- We like the zlib license, but the biggest complaint from the open source - community about the license change is the static linking. The LGPL forced this - as a legal, not technical issue, but zlib doesn't care. Even those that aren't - concerned about the GNU freedoms found themselves solving the same problems: - swapping in a newer SDL to an older game often times can save the day. - Static linking stops this dead. - -So here's what we did: - -SDL now has, internally, a table of function pointers. So, this is what SDL_Init -now looks like: - -```c -UInt32 SDL_Init(Uint32 flags) -{ - return jump_table.SDL_Init(flags); -} -``` - -Except that is all done with a bunch of macro magic so we don't have to maintain -every one of these. - -What is jump_table.SDL_init()? Eventually, that's a function pointer of the real -SDL_Init() that you've been calling all this time. But at startup, it looks more -like this: - -```c -Uint32 SDL_Init_DEFAULT(Uint32 flags) -{ - SDL_InitDynamicAPI(); - return jump_table.SDL_Init(flags); -} -``` - -SDL_InitDynamicAPI() fills in jump_table with all the actual SDL function -pointers, which means that this `_DEFAULT` function never gets called again. -First call to any SDL function sets the whole thing up. - -So you might be asking, what was the value in that? Isn't this what the operating -system's dynamic loader was supposed to do for us? Yes, but now we've got this -level of indirection, we can do things like this: - -```bash -export SDL3_DYNAMIC_API=/my/actual/libSDL3.so.0 -./MyGameThatIsStaticallyLinkedToSDL -``` - -And now, this game that is statically linked to SDL, can still be overridden -with a newer, or better, SDL. The statically linked one will only be used as -far as calling into the jump table in this case. But in cases where no override -is desired, the statically linked version will provide its own jump table, -and everyone is happy. - -So now: -- Developers can statically link SDL, and users can still replace it. - (We'd still rather you ship a shared library, though!) -- Developers can ship an SDL with their game, Valve can override it for, say, - new features on SteamOS, or distros can override it for their own needs, - but it'll also just work in the default case. -- Developers can ship the same package to everyone (Humble Bundle, GOG, etc), - and it'll do the right thing. -- End users (and Valve) can update a game's SDL in almost any case, - to keep abandoned games running on newer platforms. -- Everyone develops with SDL exactly as they have been doing all along. - Same headers, same ABI. Just get the latest version to enable this magic. - - -A little more about SDL_InitDynamicAPI(): - -Internally, InitAPI does some locking to make sure everything waits until a -single thread initializes everything (although even SDL_CreateThread() goes -through here before spinning a thread, too), and then decides if it should use -an external SDL library. If not, it sets up the jump table using the current -SDL's function pointers (which might be statically linked into a program, or in -a shared library of its own). If so, it loads that library and looks for and -calls a single function: - -```c -SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); -``` - -That function takes a version number (more on that in a moment), the address of -the jump table, and the size, in bytes, of the table. -Now, we've got policy here: this table's layout never changes; new stuff gets -added to the end. Therefore SDL_DYNAPI_entry() knows that it can provide all -the needed functions if tablesize <= sizeof its own jump table. If tablesize is -bigger (say, SDL 3.0.4 is trying to load SDL 3.0.3), then we know to abort, but -if it's smaller, we know we can provide the entire API that the caller needs. - -The version variable is a failsafe switch. -Right now it's always 1. This number changes when there are major API changes -(so we know if the tablesize might be smaller, or entries in it have changed). -Right now SDL_DYNAPI_entry gives up if the version doesn't match, but it's not -inconceivable to have a small dispatch library that only supplies this one -function and loads different, otherwise-incompatible SDL libraries and has the -right one initialize the jump table based on the version. For something that -must generically catch lots of different versions of SDL over time, like the -Steam Client, this isn't a bad option. - -Finally, I'm sure some people are reading this and thinking, -"I don't want that overhead in my project!" - -To which I would point out that the extra function call through the jump table -probably wouldn't even show up in a profile, but lucky you: this can all be -disabled. You can build SDL without this if you absolutely must, but we would -encourage you not to do that. However, on heavily locked down platforms like -iOS, or maybe when debugging, it makes sense to disable it. The way this is -designed in SDL, you just have to change one #define, and the entire system -vaporizes out, and SDL functions exactly like it always did. Most of it is -macro magic, so the system is contained to one C file and a few headers. -However, this is on by default and you have to edit a header file to turn it -off. Our hopes is that if we make it easy to disable, but not too easy, -everyone will ultimately be able to get what they want, but we've gently -nudged everyone towards what we think is the best solution. +# Dynamic API + +Originally posted on Ryan's Google+ account. + +Background: + +- The Steam Runtime has (at least in theory) a really kick-ass build of SDL, + but developers are shipping their own SDL with individual Steam games. + These games might stop getting updates, but a newer SDL might be needed later. + Certainly we'll always be fixing bugs in SDL, even if a new video target isn't + ever needed, and these fixes won't make it to a game shipping its own SDL. +- Even if we replace the SDL in those games with a compatible one, that is to + say, edit a developer's Steam depot (yuck!), there are developers that are + statically linking SDL that we can't do this for. We can't even force the + dynamic loader to ignore their SDL in this case, of course. +- If you don't ship an SDL with the game in some form, people that disabled the + Steam Runtime, or just tried to run the game from the command line instead of + Steam might find themselves unable to run the game, due to a missing dependency. +- If you want to ship on non-Steam platforms like GOG or Humble Bundle, or target + generic Linux boxes that may or may not have SDL installed, you have to ship + the library or risk a total failure to launch. So now, you might have to have + a non-Steam build plus a Steam build (that is, one with and one without SDL + included), which is inconvenient if you could have had one universal build + that works everywhere. +- We like the zlib license, but the biggest complaint from the open source + community about the license change is the static linking. The LGPL forced this + as a legal, not technical issue, but zlib doesn't care. Even those that aren't + concerned about the GNU freedoms found themselves solving the same problems: + swapping in a newer SDL to an older game often times can save the day. + Static linking stops this dead. + +So here's what we did: + +SDL now has, internally, a table of function pointers. So, this is what SDL_Init +now looks like: + +```c +UInt32 SDL_Init(Uint32 flags) +{ + return jump_table.SDL_Init(flags); +} +``` + +Except that is all done with a bunch of macro magic so we don't have to maintain +every one of these. + +What is jump_table.SDL_init()? Eventually, that's a function pointer of the real +SDL_Init() that you've been calling all this time. But at startup, it looks more +like this: + +```c +Uint32 SDL_Init_DEFAULT(Uint32 flags) +{ + SDL_InitDynamicAPI(); + return jump_table.SDL_Init(flags); +} +``` + +SDL_InitDynamicAPI() fills in jump_table with all the actual SDL function +pointers, which means that this `_DEFAULT` function never gets called again. +First call to any SDL function sets the whole thing up. + +So you might be asking, what was the value in that? Isn't this what the operating +system's dynamic loader was supposed to do for us? Yes, but now we've got this +level of indirection, we can do things like this: + +```bash +export SDL3_DYNAMIC_API=/my/actual/libSDL3.so.0 +./MyGameThatIsStaticallyLinkedToSDL +``` + +And now, this game that is statically linked to SDL, can still be overridden +with a newer, or better, SDL. The statically linked one will only be used as +far as calling into the jump table in this case. But in cases where no override +is desired, the statically linked version will provide its own jump table, +and everyone is happy. + +So now: +- Developers can statically link SDL, and users can still replace it. + (We'd still rather you ship a shared library, though!) +- Developers can ship an SDL with their game, Valve can override it for, say, + new features on SteamOS, or distros can override it for their own needs, + but it'll also just work in the default case. +- Developers can ship the same package to everyone (Humble Bundle, GOG, etc), + and it'll do the right thing. +- End users (and Valve) can update a game's SDL in almost any case, + to keep abandoned games running on newer platforms. +- Everyone develops with SDL exactly as they have been doing all along. + Same headers, same ABI. Just get the latest version to enable this magic. + + +A little more about SDL_InitDynamicAPI(): + +Internally, InitAPI does some locking to make sure everything waits until a +single thread initializes everything (although even SDL_CreateThread() goes +through here before spinning a thread, too), and then decides if it should use +an external SDL library. If not, it sets up the jump table using the current +SDL's function pointers (which might be statically linked into a program, or in +a shared library of its own). If so, it loads that library and looks for and +calls a single function: + +```c +SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); +``` + +That function takes a version number (more on that in a moment), the address of +the jump table, and the size, in bytes, of the table. +Now, we've got policy here: this table's layout never changes; new stuff gets +added to the end. Therefore SDL_DYNAPI_entry() knows that it can provide all +the needed functions if tablesize <= sizeof its own jump table. If tablesize is +bigger (say, SDL 3.0.4 is trying to load SDL 3.0.3), then we know to abort, but +if it's smaller, we know we can provide the entire API that the caller needs. + +The version variable is a failsafe switch. +Right now it's always 1. This number changes when there are major API changes +(so we know if the tablesize might be smaller, or entries in it have changed). +Right now SDL_DYNAPI_entry gives up if the version doesn't match, but it's not +inconceivable to have a small dispatch library that only supplies this one +function and loads different, otherwise-incompatible SDL libraries and has the +right one initialize the jump table based on the version. For something that +must generically catch lots of different versions of SDL over time, like the +Steam Client, this isn't a bad option. + +Finally, I'm sure some people are reading this and thinking, +"I don't want that overhead in my project!" + +To which I would point out that the extra function call through the jump table +probably wouldn't even show up in a profile, but lucky you: this can all be +disabled. You can build SDL without this if you absolutely must, but we would +encourage you not to do that. However, on heavily locked down platforms like +iOS, or maybe when debugging, it makes sense to disable it. The way this is +designed in SDL, you just have to change one #define, and the entire system +vaporizes out, and SDL functions exactly like it always did. Most of it is +macro magic, so the system is contained to one C file and a few headers. +However, this is on by default and you have to edit a header file to turn it +off. Our hopes is that if we make it easy to disable, but not too easy, +everyone will ultimately be able to get what they want, but we've gently +nudged everyone towards what we think is the best solution. diff --git a/docs/README-emscripten.md b/docs/README-emscripten.md index 5826d847bb1b1..31553e069a576 100644 --- a/docs/README-emscripten.md +++ b/docs/README-emscripten.md @@ -1,365 +1,365 @@ -# Emscripten - -## The state of things - -(As of September 2023, but things move quickly and we don't update this -document often.) - -In modern times, all the browsers you probably care about (Chrome, Firefox, -Edge, and Safari, on Windows, macOS, Linux, iOS and Android), support some -reasonable base configurations: - -- WebAssembly (don't bother with asm.js any more) -- WebGL (which will look like OpenGL ES 2 or 3 to your app). -- Threads (see caveats, though!) -- Game controllers -- Autoupdating (so you can assume they have a recent version of the browser) - -All this to say we're at the point where you don't have to make a lot of -concessions to get even a fairly complex SDL-based game up and running. - - -## RTFM - -This document is a quick rundown of some high-level details. The -documentation at [emscripten.org](https://emscripten.org/) is vast -and extremely detailed for a wide variety of topics, and you should at -least skim through it at some point. - - -## Porting your app to Emscripten - -Many many things just need some simple adjustments and they'll compile -like any other C/C++ code, as long as SDL was handling the platform-specific -work for your program. - -First, you probably need this in at least one of your source files: - -```c -#ifdef __EMSCRIPTEN__ -#include -#endif -``` - -Second: assembly language code has to go. Replace it with C. You can even use -[x86 SIMD intrinsic functions in Emscripten](https://emscripten.org/docs/porting/simd.html)! - -Third: Middleware has to go. If you have a third-party library you link -against, you either need an Emscripten port of it, or the source code to it -to compile yourself, or you need to remove it. - -Fourth: You still start in a function called main(), but you need to get out of -it and into a function that gets called repeatedly, and returns quickly, -called a mainloop. - -Somewhere in your program, you probably have something that looks like a more -complicated version of this: - -```c -void main(void) -{ - initialize_the_game(); - while (game_is_still_running) { - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); - } - deinitialize_the_game(); -} -``` - -This will not work on Emscripten, because the main thread needs to be free -to do stuff and can't sit in this loop forever. So Emscripten lets you set up -a [mainloop](https://emscripten.org/docs/porting/emscripten-runtime-environment.html#browser-main-loop). - -```c -static void mainloop(void) /* this will run often, possibly at the monitor's refresh rate */ -{ - if (!game_is_still_running) { - deinitialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_cancel_main_loop(); /* this should "kill" the app. */ - #else - exit(0); - #endif - } - - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); -} - -void main(void) -{ - initialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(mainloop, 0, 1); - #else - while (1) { mainloop(); } - #endif -} -``` - -Basically, `emscripten_set_main_loop(mainloop, 0, 1);` says "run -`mainloop` over and over until I end the program." The function will -run, and return, freeing the main thread for other tasks, and then -run again when it's time. The `1` parameter does some magic to make -your main() function end immediately; this is useful because you -don't want any shutdown code that might be sitting below this code -to actually run if main() were to continue on, since we're just -getting started. - -There's a lot of little details that are beyond the scope of this -document, but that's the biggest intial set of hurdles to porting -your app to the web. - - -## Do you need threads? - -If you plan to use threads, they work on all major browsers now. HOWEVER, -they bring with them a lot of careful considerations. Rendering _must_ -be done on the main thread. This is a general guideline for many -platforms, but a hard requirement on the web. - -Many other things also must happen on the main thread; often times SDL -and Emscripten make efforts to "proxy" work to the main thread that -must be there, but you have to be careful (and read more detailed -documentation than this for the finer points). - -Even when using threads, your main thread needs to set an Emscripten -mainloop that runs quickly and returns, or things will fail to work -correctly. - -You should definitely read [Emscripten's pthreads docs](https://emscripten.org/docs/porting/pthreads.html) -for all the finer points. Mostly SDL's thread API will work as expected, -but is built on pthreads, so it shares the same little incompatibilities -that are documented there, such as where you can use a mutex, and when -a thread will start running, etc. - - -IMPORTANT: You have to decide to either build something that uses -threads or something that doesn't; you can't have one build -that works everywhere. This is an Emscripten (or maybe WebAssembly? -Or just web browsers in general?) limitation. If you aren't using -threads, it's easier to not enable them at all, at build time. - -If you use threads, you _have to_ run from a web server that has -[COOP/COEP headers set correctly](https://web.dev/why-coop-coep/) -or your program will fail to start at all. - -If building with threads, `__EMSCRIPTEN_PTHREADS__` will be defined -for checking with the C preprocessor, so you can build something -different depending on what sort of build you're compiling. - - -## Audio - -Audio works as expected at the API level, but not exactly like other -platforms. - -You'll only see a single default audio device. Audio capture also works; -if the browser pops up a prompt to ask for permission to access the -microphone, the SDL_OpenAudioDevice call will succeed and start producing -silence at a regular interval. Once the user approves the request, real -audio data will flow. If the user denies it, the app is not informed and -will just continue to receive silence. - -Modern web browsers will not permit web pages to produce sound before the -user has interacted with them (clicked or tapped on them, usually); this is -for several reasons, not the least of which being that no one likes when a -random browser tab suddenly starts making noise and the user has to scramble -to figure out which and silence it. - -SDL will allow you to open the audio device for playback in this -circumstance, and your audio callback will fire, but SDL will throw the audio -data away until the user interacts with the page. This helps apps that depend -on the audio callback to make progress, and also keeps audio playback in sync -once the app is finally allowed to make noise. - -There are two reasonable ways to deal with the silence at the app level: -if you are writing some sort of media player thing, where the user expects -there to be a volume control when you mouseover the canvas, just default -that control to a muted state; if the user clicks on the control to unmute -it, on this first click, open the audio device. This allows the media to -play at start, and the user can reasonably opt-in to listening. - -Many games do not have this sort of UI, and are more rigid about starting -audio along with everything else at the start of the process. For these, your -best bet is to write a little Javascript that puts up a "Click here to play!" -UI, and upon the user clicking, remove that UI and then call the Emscripten -app's main() function. As far as the application knows, the audio device was -available to be opened as soon as the program started, and since this magic -happens in a little Javascript, you don't have to change your C/C++ code at -all to make it happen. - -Please see the discussion at https://github.com/libsdl-org/SDL/issues/6385 -for some Javascript code to steal for this approach. - - -## Rendering - -If you use SDL's 2D render API, it will use GLES2 internally, which -Emscripten will turn into WebGL calls. You can also use OpenGL ES 2 -directly by creating a GL context and drawing into it. - -Calling SDL_RenderPresent (or SDL_GL_SwapWindow) will not actually -present anything on the screen until your return from your mainloop -function. - - -## Building SDL/emscripten - -First: do you _really_ need to build SDL from source? - -If you aren't developing SDL itself, have a desire to mess with its source -code, or need something on the bleeding edge, don't build SDL. Just use -Emscripten's packaged version! - -Compile and link your app with `-sUSE_SDL=2` and it'll use a build of -SDL packaged with Emscripten. This comes from the same source code and -fixes the Emscripten project makes to SDL are generally merged into SDL's -revision control, so often this is much easier for app developers. - -`-sUSE_SDL=1` will select Emscripten's JavaScript reimplementation of SDL -1.2 instead; if you need SDL 1.2, this might be fine, but we generally -recommend you don't use SDL 1.2 in modern times. - - -If you want to build SDL, though... - -SDL currently requires at least Emscripten 3.1.35 to build. Newer versions -are likely to work, as well. - - -Build: - -This works on Linux/Unix and macOS. Please send comments about Windows. - -Make sure you've [installed emsdk](https://emscripten.org/docs/getting_started/downloads.html) -first, and run `source emsdk_env.sh` at the command line so it finds the -tools. - -(These cmake options might be overkill, but this has worked for me.) - -```bash -mkdir build -cd build -emcmake cmake .. -# you can also do `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command. -emmake make -j4 -``` - -If you want to build with thread support, something like this works: - -```bash -mkdir build -cd build -emcmake cmake -DSDL_THREADS=On .. -# you can also do `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command. -emmake make -j4 -``` - -To build the tests, add `-DSDL_TESTS=On` to the `emcmake cmake` command line. - - -## Building your app - -You need to compile with `emcc` instead of `gcc` or `clang` or whatever, but -mostly it uses the same command line arguments as Clang. - -Link against the SDL/build/libSDL3.a file you generated by building SDL, -link with `-sUSE_SDL=2` to use Emscripten's prepackaged SDL2 build. - -Usually you would produce a binary like this: - -```bash -gcc -o mygame mygame.c # or whatever -``` - -But for Emscripten, you want to output something else: - -```bash -emcc -o index.html mygame.c -``` - -This will produce several files...support Javascript and WebAssembly (.wasm) -files. The `-o index.html` will produce a simple HTML page that loads and -runs your app. You will (probably) eventually want to replace or customize -that file and do `-o index.js` instead to just build the code pieces. - -If you're working on a program of any serious size, you'll likely need to -link with `-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb` to get access -to more memory. If using pthreads, you'll need the `-sMAXIMUM_MEMORY=1gb` -or the app will fail to start on iOS browsers, but this might be a bug that -goes away in the future. - - -## Data files - -Your game probably has data files. Here's how to access them. - -Filesystem access works like a Unix filesystem; you have a single directory -tree, possibly interpolated from several mounted locations, no drive letters, -'/' for a path separator. You can access them with standard file APIs like -open() or fopen() or SDL_RWops. You can read or write from the filesystem. - -By default, you probably have a "MEMFS" filesystem (all files are stored in -memory, but access to them is immediate and doesn't need to block). There are -other options, like "IDBFS" (files are stored in a local database, so they -don't need to be in RAM all the time and they can persist between runs of the -program, but access is not synchronous). You can mix and match these file -systems, mounting a MEMFS filesystem at one place and idbfs elsewhere, etc, -but that's beyond the scope of this document. Please refer to Emscripten's -[page on the topic](https://emscripten.org/docs/porting/files/file_systems_overview.html) -for more info. - -The _easiest_ (but not the best) way to get at your data files is to embed -them in the app itself. Emscripten's linker has support for automating this. - -```bash -emcc -o index.html loopwave.c --embed-file=../test/sample.wav@/sounds/sample.wav -``` - -This will pack ../test/sample.wav in your app, and make it available at -"/sounds/sample.wav" at runtime. Emscripten makes sure this data is available -before your main() function runs, and since it's in MEMFS, you can just -read it like you do on other platforms. `--embed-file` can also accept a -directory to pack an entire tree, and you can specify the argument multiple -times to pack unrelated things into the final installation. - -Note that this is absolutely the best approach if you have a few small -files to include and shouldn't worry about the issue further. However, if you -have hundreds of megabytes and/or thousands of files, this is not so great, -since the user will download it all every time they load your page, and it -all has to live in memory at runtime. - -[Emscripten's documentation on the matter](https://emscripten.org/docs/porting/files/packaging_files.html) -gives other options and details, and is worth a read. - - -## Debugging - -Debugging web apps is a mixed bag. You should compile and link with -`-gsource-map`, which embeds a ton of source-level debugging information into -the build, and make sure _the app source code is available on the web server_, -which is often a scary proposition for various reasons. - -When you debug from the browser's tools and hit a breakpoint, you can step -through the actual C/C++ source code, though, which can be nice. - -If you try debugging in Firefox and it doesn't work well for no apparent -reason, try Chrome, and vice-versa. These tools are still relatively new, -and improving all the time. - -SDL_Log() (or even plain old printf) will write to the Javascript console, -and honestly I find printf-style debugging to be easier than setting up a build -for proper debugging, so use whatever tools work best for you. - - -## Questions? - -Please give us feedback on this document at [the SDL bug tracker](https://github.com/libsdl-org/SDL/issues). -If something is wrong or unclear, we want to know! - - - +# Emscripten + +## The state of things + +(As of September 2023, but things move quickly and we don't update this +document often.) + +In modern times, all the browsers you probably care about (Chrome, Firefox, +Edge, and Safari, on Windows, macOS, Linux, iOS and Android), support some +reasonable base configurations: + +- WebAssembly (don't bother with asm.js any more) +- WebGL (which will look like OpenGL ES 2 or 3 to your app). +- Threads (see caveats, though!) +- Game controllers +- Autoupdating (so you can assume they have a recent version of the browser) + +All this to say we're at the point where you don't have to make a lot of +concessions to get even a fairly complex SDL-based game up and running. + + +## RTFM + +This document is a quick rundown of some high-level details. The +documentation at [emscripten.org](https://emscripten.org/) is vast +and extremely detailed for a wide variety of topics, and you should at +least skim through it at some point. + + +## Porting your app to Emscripten + +Many many things just need some simple adjustments and they'll compile +like any other C/C++ code, as long as SDL was handling the platform-specific +work for your program. + +First, you probably need this in at least one of your source files: + +```c +#ifdef __EMSCRIPTEN__ +#include +#endif +``` + +Second: assembly language code has to go. Replace it with C. You can even use +[x86 SIMD intrinsic functions in Emscripten](https://emscripten.org/docs/porting/simd.html)! + +Third: Middleware has to go. If you have a third-party library you link +against, you either need an Emscripten port of it, or the source code to it +to compile yourself, or you need to remove it. + +Fourth: You still start in a function called main(), but you need to get out of +it and into a function that gets called repeatedly, and returns quickly, +called a mainloop. + +Somewhere in your program, you probably have something that looks like a more +complicated version of this: + +```c +void main(void) +{ + initialize_the_game(); + while (game_is_still_running) { + check_for_new_input(); + think_about_stuff(); + draw_the_next_frame(); + } + deinitialize_the_game(); +} +``` + +This will not work on Emscripten, because the main thread needs to be free +to do stuff and can't sit in this loop forever. So Emscripten lets you set up +a [mainloop](https://emscripten.org/docs/porting/emscripten-runtime-environment.html#browser-main-loop). + +```c +static void mainloop(void) /* this will run often, possibly at the monitor's refresh rate */ +{ + if (!game_is_still_running) { + deinitialize_the_game(); + #ifdef __EMSCRIPTEN__ + emscripten_cancel_main_loop(); /* this should "kill" the app. */ + #else + exit(0); + #endif + } + + check_for_new_input(); + think_about_stuff(); + draw_the_next_frame(); +} + +void main(void) +{ + initialize_the_game(); + #ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(mainloop, 0, 1); + #else + while (1) { mainloop(); } + #endif +} +``` + +Basically, `emscripten_set_main_loop(mainloop, 0, 1);` says "run +`mainloop` over and over until I end the program." The function will +run, and return, freeing the main thread for other tasks, and then +run again when it's time. The `1` parameter does some magic to make +your main() function end immediately; this is useful because you +don't want any shutdown code that might be sitting below this code +to actually run if main() were to continue on, since we're just +getting started. + +There's a lot of little details that are beyond the scope of this +document, but that's the biggest intial set of hurdles to porting +your app to the web. + + +## Do you need threads? + +If you plan to use threads, they work on all major browsers now. HOWEVER, +they bring with them a lot of careful considerations. Rendering _must_ +be done on the main thread. This is a general guideline for many +platforms, but a hard requirement on the web. + +Many other things also must happen on the main thread; often times SDL +and Emscripten make efforts to "proxy" work to the main thread that +must be there, but you have to be careful (and read more detailed +documentation than this for the finer points). + +Even when using threads, your main thread needs to set an Emscripten +mainloop that runs quickly and returns, or things will fail to work +correctly. + +You should definitely read [Emscripten's pthreads docs](https://emscripten.org/docs/porting/pthreads.html) +for all the finer points. Mostly SDL's thread API will work as expected, +but is built on pthreads, so it shares the same little incompatibilities +that are documented there, such as where you can use a mutex, and when +a thread will start running, etc. + + +IMPORTANT: You have to decide to either build something that uses +threads or something that doesn't; you can't have one build +that works everywhere. This is an Emscripten (or maybe WebAssembly? +Or just web browsers in general?) limitation. If you aren't using +threads, it's easier to not enable them at all, at build time. + +If you use threads, you _have to_ run from a web server that has +[COOP/COEP headers set correctly](https://web.dev/why-coop-coep/) +or your program will fail to start at all. + +If building with threads, `__EMSCRIPTEN_PTHREADS__` will be defined +for checking with the C preprocessor, so you can build something +different depending on what sort of build you're compiling. + + +## Audio + +Audio works as expected at the API level, but not exactly like other +platforms. + +You'll only see a single default audio device. Audio capture also works; +if the browser pops up a prompt to ask for permission to access the +microphone, the SDL_OpenAudioDevice call will succeed and start producing +silence at a regular interval. Once the user approves the request, real +audio data will flow. If the user denies it, the app is not informed and +will just continue to receive silence. + +Modern web browsers will not permit web pages to produce sound before the +user has interacted with them (clicked or tapped on them, usually); this is +for several reasons, not the least of which being that no one likes when a +random browser tab suddenly starts making noise and the user has to scramble +to figure out which and silence it. + +SDL will allow you to open the audio device for playback in this +circumstance, and your audio callback will fire, but SDL will throw the audio +data away until the user interacts with the page. This helps apps that depend +on the audio callback to make progress, and also keeps audio playback in sync +once the app is finally allowed to make noise. + +There are two reasonable ways to deal with the silence at the app level: +if you are writing some sort of media player thing, where the user expects +there to be a volume control when you mouseover the canvas, just default +that control to a muted state; if the user clicks on the control to unmute +it, on this first click, open the audio device. This allows the media to +play at start, and the user can reasonably opt-in to listening. + +Many games do not have this sort of UI, and are more rigid about starting +audio along with everything else at the start of the process. For these, your +best bet is to write a little Javascript that puts up a "Click here to play!" +UI, and upon the user clicking, remove that UI and then call the Emscripten +app's main() function. As far as the application knows, the audio device was +available to be opened as soon as the program started, and since this magic +happens in a little Javascript, you don't have to change your C/C++ code at +all to make it happen. + +Please see the discussion at https://github.com/libsdl-org/SDL/issues/6385 +for some Javascript code to steal for this approach. + + +## Rendering + +If you use SDL's 2D render API, it will use GLES2 internally, which +Emscripten will turn into WebGL calls. You can also use OpenGL ES 2 +directly by creating a GL context and drawing into it. + +Calling SDL_RenderPresent (or SDL_GL_SwapWindow) will not actually +present anything on the screen until your return from your mainloop +function. + + +## Building SDL/emscripten + +First: do you _really_ need to build SDL from source? + +If you aren't developing SDL itself, have a desire to mess with its source +code, or need something on the bleeding edge, don't build SDL. Just use +Emscripten's packaged version! + +Compile and link your app with `-sUSE_SDL=2` and it'll use a build of +SDL packaged with Emscripten. This comes from the same source code and +fixes the Emscripten project makes to SDL are generally merged into SDL's +revision control, so often this is much easier for app developers. + +`-sUSE_SDL=1` will select Emscripten's JavaScript reimplementation of SDL +1.2 instead; if you need SDL 1.2, this might be fine, but we generally +recommend you don't use SDL 1.2 in modern times. + + +If you want to build SDL, though... + +SDL currently requires at least Emscripten 3.1.35 to build. Newer versions +are likely to work, as well. + + +Build: + +This works on Linux/Unix and macOS. Please send comments about Windows. + +Make sure you've [installed emsdk](https://emscripten.org/docs/getting_started/downloads.html) +first, and run `source emsdk_env.sh` at the command line so it finds the +tools. + +(These cmake options might be overkill, but this has worked for me.) + +```bash +mkdir build +cd build +emcmake cmake .. +# you can also do `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command. +emmake make -j4 +``` + +If you want to build with thread support, something like this works: + +```bash +mkdir build +cd build +emcmake cmake -DSDL_THREADS=On .. +# you can also do `emcmake cmake -G Ninja ..` and then use `ninja` instead of this command. +emmake make -j4 +``` + +To build the tests, add `-DSDL_TESTS=On` to the `emcmake cmake` command line. + + +## Building your app + +You need to compile with `emcc` instead of `gcc` or `clang` or whatever, but +mostly it uses the same command line arguments as Clang. + +Link against the SDL/build/libSDL3.a file you generated by building SDL, +link with `-sUSE_SDL=2` to use Emscripten's prepackaged SDL2 build. + +Usually you would produce a binary like this: + +```bash +gcc -o mygame mygame.c # or whatever +``` + +But for Emscripten, you want to output something else: + +```bash +emcc -o index.html mygame.c +``` + +This will produce several files...support Javascript and WebAssembly (.wasm) +files. The `-o index.html` will produce a simple HTML page that loads and +runs your app. You will (probably) eventually want to replace or customize +that file and do `-o index.js` instead to just build the code pieces. + +If you're working on a program of any serious size, you'll likely need to +link with `-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb` to get access +to more memory. If using pthreads, you'll need the `-sMAXIMUM_MEMORY=1gb` +or the app will fail to start on iOS browsers, but this might be a bug that +goes away in the future. + + +## Data files + +Your game probably has data files. Here's how to access them. + +Filesystem access works like a Unix filesystem; you have a single directory +tree, possibly interpolated from several mounted locations, no drive letters, +'/' for a path separator. You can access them with standard file APIs like +open() or fopen() or SDL_RWops. You can read or write from the filesystem. + +By default, you probably have a "MEMFS" filesystem (all files are stored in +memory, but access to them is immediate and doesn't need to block). There are +other options, like "IDBFS" (files are stored in a local database, so they +don't need to be in RAM all the time and they can persist between runs of the +program, but access is not synchronous). You can mix and match these file +systems, mounting a MEMFS filesystem at one place and idbfs elsewhere, etc, +but that's beyond the scope of this document. Please refer to Emscripten's +[page on the topic](https://emscripten.org/docs/porting/files/file_systems_overview.html) +for more info. + +The _easiest_ (but not the best) way to get at your data files is to embed +them in the app itself. Emscripten's linker has support for automating this. + +```bash +emcc -o index.html loopwave.c --embed-file=../test/sample.wav@/sounds/sample.wav +``` + +This will pack ../test/sample.wav in your app, and make it available at +"/sounds/sample.wav" at runtime. Emscripten makes sure this data is available +before your main() function runs, and since it's in MEMFS, you can just +read it like you do on other platforms. `--embed-file` can also accept a +directory to pack an entire tree, and you can specify the argument multiple +times to pack unrelated things into the final installation. + +Note that this is absolutely the best approach if you have a few small +files to include and shouldn't worry about the issue further. However, if you +have hundreds of megabytes and/or thousands of files, this is not so great, +since the user will download it all every time they load your page, and it +all has to live in memory at runtime. + +[Emscripten's documentation on the matter](https://emscripten.org/docs/porting/files/packaging_files.html) +gives other options and details, and is worth a read. + + +## Debugging + +Debugging web apps is a mixed bag. You should compile and link with +`-gsource-map`, which embeds a ton of source-level debugging information into +the build, and make sure _the app source code is available on the web server_, +which is often a scary proposition for various reasons. + +When you debug from the browser's tools and hit a breakpoint, you can step +through the actual C/C++ source code, though, which can be nice. + +If you try debugging in Firefox and it doesn't work well for no apparent +reason, try Chrome, and vice-versa. These tools are still relatively new, +and improving all the time. + +SDL_Log() (or even plain old printf) will write to the Javascript console, +and honestly I find printf-style debugging to be easier than setting up a build +for proper debugging, so use whatever tools work best for you. + + +## Questions? + +Please give us feedback on this document at [the SDL bug tracker](https://github.com/libsdl-org/SDL/issues). +If something is wrong or unclear, we want to know! + + + diff --git a/docs/README-gdk.md b/docs/README-gdk.md index fefe163579418..6c242b5a0c863 100644 --- a/docs/README-gdk.md +++ b/docs/README-gdk.md @@ -1,159 +1,159 @@ -GDK -===== - -This port allows SDL applications to run via Microsoft's Game Development Kit (GDK). - -Windows (GDK) and Xbox One/Xbox Series (GDKX) are supported. Although most of the Xbox code is included in the public SDL source code, NDA access is required for a small number of source files. If you have access to GDKX, these required Xbox files are posted on the GDK forums [here](https://forums.xboxlive.com/questions/130003/). - - -Requirements ------------- - -* Microsoft Visual Studio 2022 (in theory, it should also work in 2017 or 2019, but this has not been tested) -* Microsoft GDK June 2022 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/June_2022)) -* To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the identifiers used by the GDK test programs in the included solution will work. - - -Windows GDK Status ------- - -The Windows GDK port supports the full set of Win32 APIs, renderers, controllers, input devices, etc., as the normal Windows x64 build of SDL. - -* Additionally, the GDK port adds the following: - * Compile-time platform detection for SDL programs. The `__GDK__` is `#define`d on every GDK platform, and the `__WINGDK__` is `#define`d on Windows GDK, specifically. (This distinction exists because other GDK platforms support a smaller subset of functionality. This allows you to mark code for "any" GDK separate from Windows GDK.) - * GDK-specific setup: - * Initializing/uninitializing the game runtime, and initializing Xbox Live services - * Creating a global task queue and setting it as the default for the process. When running any async operations, passing in `NULL` as the task queue will make the task get added to the global task queue. - - * An implementation on `WinMain` that performs the above GDK setup that you can use by #include'ing SDL_main.h in the source file that includes your standard main() function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters. To use `SDL_RunApp`, `#define SDL_MAIN_HANDLED` before `#include `. - * Global task queue callbacks are dispatched during `SDL_PumpEvents` (which is also called internally if using `SDL_PollEvent`). - * You can get the handle of the global task queue through `SDL_GDKGetTaskQueue`, if needed. When done with the queue, be sure to use `XTaskQueueCloseHandle` to decrement the reference count (otherwise it will cause a resource leak). - -* Single-player games have some additional features available: - * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer. - * `SDL_GetPrefPath` still works, but only for single-player titles. - -These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! - -* What doesn't work: - * Compilation with anything other than through the included Visual C++ solution file - -## VisualC-GDK Solution - -The included `VisualC-GDK/SDL.sln` solution includes the following targets for the Gaming.Desktop.x64 configuration: - -* SDL3 (DLL) - This is the typical SDL3.dll, but for Gaming.Desktop.x64. -* tests/testgamecontroller - Standard SDL test program demonstrating controller functionality. -* tests/testgdk - GDK-specific test program that demonstrates using the global task queue to login a user into Xbox Live. - *NOTE*: As of the June 2022 GDK, you cannot test user logins without a valid Title ID and MSAAppId. You will need to manually change the identifiers in the `MicrosoftGame.config` to your valid IDs from Partner Center if you wish to test this. -* tests/testsprite - Standard SDL test program demonstrating sprite drawing functionality. - -If you set one of the test programs as a startup project, you can run it directly from Visual Studio. - -Windows GDK Setup, Detailed Steps ---------------------- - -These steps assume you already have a game using SDL that runs on Windows x64 along with a corresponding Visual Studio solution file for the x64 version. If you don't have this, it's easiest to use one of the test program vcxproj files in the `VisualC-GDK` directory as a starting point, though you will still need to do most of the steps below. - -### 1. Add a Gaming.Desktop.x64 Configuration ### - -In your game's existing Visual Studio Solution, go to Build > Configuration Manager. From the "Active solution platform" drop-down select "New...". From the drop-down list, select Gaming.Desktop.x64 and copy the settings from the x64 configuration. - -### 2. Build SDL3 for GDK ### - -Open `VisualC-GDK/SDL.sln` in Visual Studio, you need to build the SDL3 target for the Gaming.Desktop.x64 platform (Release is recommended). You will need to copy/keep track of the `SDL3.dll`, `XCurl.dll` (which is output by Gaming.Desktop.x64), and `SDL3.lib` output files for your game project. - -*Alternatively*, you could setup your solution file to instead reference the SDL3 project file targets from the SDL source, and add those projects as a dependency. This would mean that SDL3 would be built when your game is built. - -### 3. Configuring Project Settings ### - -While the Gaming.Desktop.x64 configuration sets most of the required settings, there are some additional items to configure for your game project under the Gaming.Desktop.x64 Configuration: - -* Under C/C++ > General > Additional Include Directories, make sure the `SDL/include` path is referenced -* Under Linker > General > Additional Library Directories, make sure to reference the path where the newly-built SDL3.lib are -* Under Linker > Input > Additional Dependencies, you need the following: - * `SDL3.lib` - * `xgameruntime.lib` - * `../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib` -* Note that in general, the GDK libraries depend on the MSVC C/C++ runtime, so there is no way to remove this dependency from a GDK program that links against GDK. - -### 4. Setting up SDL_main ### - -Rather than using your own implementation of `WinMain`, it's recommended that you instead `#include ` and declare a standard main function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters; in that case `#define SDL_MAIN_HANDLED` before including SDL_main.h - -### 5. Required DLLs ### - -The game will not launch in the debugger unless required DLLs are included in the directory that contains the game's .exe file. You need to make sure that the following files are copied into the directory: - -* Your SDL3.dll -* "$(Console_GRDKExtLibRoot)Xbox.Services.API.C\DesignTime\CommonConfiguration\Neutral\Lib\Release\Microsoft.Xbox.Services.141.GDK.C.Thunks.dll" -* XCurl.dll - -You can either copy these in a post-build step, or you can add the dlls into the project and set its Configuration Properties > General > Item type to "Copy file," which will also copy them into the output directory. - -### 6. Setting up MicrosoftGame.config ### - -You can copy `VisualC-GDK/tests/testgdk/MicrosoftGame.config` and use that as a starting point in your project. Minimally, you will want to change the Executable Name attribute, the DefaultDisplayName, and the Description. - -This file must be copied into the same directory as the game's .exe file. As with the DLLs, you can either use a post-build step or the "Copy file" item type. - -For basic testing, you do not need to change anything else in `MicrosoftGame.config`. However, if you want to test any Xbox Live services (such as logging in users) _or_ publish a package, you will need to setup a Game app on Partner Center. - -Then, you need to set the following values to the values from Partner Center: - -* Identity tag - Name and Publisher attributes -* TitleId -* MSAAppId - -### 7. Adding Required Logos - -Several logo PNG files are required to be able to launch the game, even from the debugger. You can use the sample logos provided in `VisualC-GDK/logos`. As with the other files, they must be copied into the same directory as the game's .exe file. - - -### 8. Copying any Data Files ### - -When debugging GDK games, there is no way to specify a working directory. Therefore, any required game data must also be copied into the output directory, likely in a post-build step. - - -### 9. Build and Run from Visual Studio ### - -At this point, you should be able to build and run your game from the Visual Studio Debugger. If you get any linker errors, make sure you double-check that you referenced all the required libs. - -If you are testing Xbox Live functionality, it's likely you will need to change to the Sandbox for your title. To do this: - -1. Run "Desktop VS 2022 Gaming Command Prompt" from the Start Menu -2. Switch the sandbox name with: - `XblPCSandbox SANDBOX.#` -3. (To switch back to the retail sandbox): - `XblPCSandbox RETAIL` - -### 10. Packaging and Installing Locally - -You can use one of the test program's `PackageLayout.xml` as a starting point. Minimally, you will need to change the exe to the correct name and also reference any required game data. As with the other data files, it's easiest if you have this copy to the output directory, although it's not a requirement as you can specify relative paths to files. - -To create the package: - -1. Run "Desktop VS 2022 Gaming Command Prompt" from the Start Menu -2. `cd` to the directory containing the `PackageLayout.xml` with the correct paths (if you use the local path as in the sample package layout, this would be from your .exe output directory) -3. `mkdir Package` to create an output directory -4. To package the file into the `Package` directory, use: - `makepkg pack /f PackageLayout.xml /lt /d . /nogameos /pc /pd Package` -5. To install the package, use: - `wdapp install PACKAGENAME.msixvc` -6. Once the package is installed, you can run it from the start menu. -7. As with when running from Visual Studio, if you need to test any Xbox Live functionality you must switch to the correct sandbox. - - -Troubleshooting ---------------- - -#### Xbox Live Login does not work - -As of June 2022 GDK, you must have a valid Title Id and MSAAppId in order to test Xbox Live functionality such as user login. Make sure these are set correctly in the `MicrosoftGame.config`. This means that even testgdk will not let you login without setting these properties to valid values. - -Furthermore, confirm that your PC is set to the correct sandbox. - - -#### "The current user has already installed an unpackaged version of this app. A packaged version cannot replace this." error when installing - -Prior to June 2022 GDK, running from the Visual Studio debugger would still locally register the app (and it would appear on the start menu). To fix this, you have to uninstall it (it's simplest to right click on it from the start menu to uninstall it). +GDK +===== + +This port allows SDL applications to run via Microsoft's Game Development Kit (GDK). + +Windows (GDK) and Xbox One/Xbox Series (GDKX) are supported. Although most of the Xbox code is included in the public SDL source code, NDA access is required for a small number of source files. If you have access to GDKX, these required Xbox files are posted on the GDK forums [here](https://forums.xboxlive.com/questions/130003/). + + +Requirements +------------ + +* Microsoft Visual Studio 2022 (in theory, it should also work in 2017 or 2019, but this has not been tested) +* Microsoft GDK June 2022 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/June_2022)) +* To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the identifiers used by the GDK test programs in the included solution will work. + + +Windows GDK Status +------ + +The Windows GDK port supports the full set of Win32 APIs, renderers, controllers, input devices, etc., as the normal Windows x64 build of SDL. + +* Additionally, the GDK port adds the following: + * Compile-time platform detection for SDL programs. The `__GDK__` is `#define`d on every GDK platform, and the `__WINGDK__` is `#define`d on Windows GDK, specifically. (This distinction exists because other GDK platforms support a smaller subset of functionality. This allows you to mark code for "any" GDK separate from Windows GDK.) + * GDK-specific setup: + * Initializing/uninitializing the game runtime, and initializing Xbox Live services + * Creating a global task queue and setting it as the default for the process. When running any async operations, passing in `NULL` as the task queue will make the task get added to the global task queue. + + * An implementation on `WinMain` that performs the above GDK setup that you can use by #include'ing SDL_main.h in the source file that includes your standard main() function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters. To use `SDL_RunApp`, `#define SDL_MAIN_HANDLED` before `#include `. + * Global task queue callbacks are dispatched during `SDL_PumpEvents` (which is also called internally if using `SDL_PollEvent`). + * You can get the handle of the global task queue through `SDL_GDKGetTaskQueue`, if needed. When done with the queue, be sure to use `XTaskQueueCloseHandle` to decrement the reference count (otherwise it will cause a resource leak). + +* Single-player games have some additional features available: + * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer. + * `SDL_GetPrefPath` still works, but only for single-player titles. + +These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! + +* What doesn't work: + * Compilation with anything other than through the included Visual C++ solution file + +## VisualC-GDK Solution + +The included `VisualC-GDK/SDL.sln` solution includes the following targets for the Gaming.Desktop.x64 configuration: + +* SDL3 (DLL) - This is the typical SDL3.dll, but for Gaming.Desktop.x64. +* tests/testgamecontroller - Standard SDL test program demonstrating controller functionality. +* tests/testgdk - GDK-specific test program that demonstrates using the global task queue to login a user into Xbox Live. + *NOTE*: As of the June 2022 GDK, you cannot test user logins without a valid Title ID and MSAAppId. You will need to manually change the identifiers in the `MicrosoftGame.config` to your valid IDs from Partner Center if you wish to test this. +* tests/testsprite - Standard SDL test program demonstrating sprite drawing functionality. + +If you set one of the test programs as a startup project, you can run it directly from Visual Studio. + +Windows GDK Setup, Detailed Steps +--------------------- + +These steps assume you already have a game using SDL that runs on Windows x64 along with a corresponding Visual Studio solution file for the x64 version. If you don't have this, it's easiest to use one of the test program vcxproj files in the `VisualC-GDK` directory as a starting point, though you will still need to do most of the steps below. + +### 1. Add a Gaming.Desktop.x64 Configuration ### + +In your game's existing Visual Studio Solution, go to Build > Configuration Manager. From the "Active solution platform" drop-down select "New...". From the drop-down list, select Gaming.Desktop.x64 and copy the settings from the x64 configuration. + +### 2. Build SDL3 for GDK ### + +Open `VisualC-GDK/SDL.sln` in Visual Studio, you need to build the SDL3 target for the Gaming.Desktop.x64 platform (Release is recommended). You will need to copy/keep track of the `SDL3.dll`, `XCurl.dll` (which is output by Gaming.Desktop.x64), and `SDL3.lib` output files for your game project. + +*Alternatively*, you could setup your solution file to instead reference the SDL3 project file targets from the SDL source, and add those projects as a dependency. This would mean that SDL3 would be built when your game is built. + +### 3. Configuring Project Settings ### + +While the Gaming.Desktop.x64 configuration sets most of the required settings, there are some additional items to configure for your game project under the Gaming.Desktop.x64 Configuration: + +* Under C/C++ > General > Additional Include Directories, make sure the `SDL/include` path is referenced +* Under Linker > General > Additional Library Directories, make sure to reference the path where the newly-built SDL3.lib are +* Under Linker > Input > Additional Dependencies, you need the following: + * `SDL3.lib` + * `xgameruntime.lib` + * `../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib` +* Note that in general, the GDK libraries depend on the MSVC C/C++ runtime, so there is no way to remove this dependency from a GDK program that links against GDK. + +### 4. Setting up SDL_main ### + +Rather than using your own implementation of `WinMain`, it's recommended that you instead `#include ` and declare a standard main function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters; in that case `#define SDL_MAIN_HANDLED` before including SDL_main.h + +### 5. Required DLLs ### + +The game will not launch in the debugger unless required DLLs are included in the directory that contains the game's .exe file. You need to make sure that the following files are copied into the directory: + +* Your SDL3.dll +* "$(Console_GRDKExtLibRoot)Xbox.Services.API.C\DesignTime\CommonConfiguration\Neutral\Lib\Release\Microsoft.Xbox.Services.141.GDK.C.Thunks.dll" +* XCurl.dll + +You can either copy these in a post-build step, or you can add the dlls into the project and set its Configuration Properties > General > Item type to "Copy file," which will also copy them into the output directory. + +### 6. Setting up MicrosoftGame.config ### + +You can copy `VisualC-GDK/tests/testgdk/MicrosoftGame.config` and use that as a starting point in your project. Minimally, you will want to change the Executable Name attribute, the DefaultDisplayName, and the Description. + +This file must be copied into the same directory as the game's .exe file. As with the DLLs, you can either use a post-build step or the "Copy file" item type. + +For basic testing, you do not need to change anything else in `MicrosoftGame.config`. However, if you want to test any Xbox Live services (such as logging in users) _or_ publish a package, you will need to setup a Game app on Partner Center. + +Then, you need to set the following values to the values from Partner Center: + +* Identity tag - Name and Publisher attributes +* TitleId +* MSAAppId + +### 7. Adding Required Logos + +Several logo PNG files are required to be able to launch the game, even from the debugger. You can use the sample logos provided in `VisualC-GDK/logos`. As with the other files, they must be copied into the same directory as the game's .exe file. + + +### 8. Copying any Data Files ### + +When debugging GDK games, there is no way to specify a working directory. Therefore, any required game data must also be copied into the output directory, likely in a post-build step. + + +### 9. Build and Run from Visual Studio ### + +At this point, you should be able to build and run your game from the Visual Studio Debugger. If you get any linker errors, make sure you double-check that you referenced all the required libs. + +If you are testing Xbox Live functionality, it's likely you will need to change to the Sandbox for your title. To do this: + +1. Run "Desktop VS 2022 Gaming Command Prompt" from the Start Menu +2. Switch the sandbox name with: + `XblPCSandbox SANDBOX.#` +3. (To switch back to the retail sandbox): + `XblPCSandbox RETAIL` + +### 10. Packaging and Installing Locally + +You can use one of the test program's `PackageLayout.xml` as a starting point. Minimally, you will need to change the exe to the correct name and also reference any required game data. As with the other data files, it's easiest if you have this copy to the output directory, although it's not a requirement as you can specify relative paths to files. + +To create the package: + +1. Run "Desktop VS 2022 Gaming Command Prompt" from the Start Menu +2. `cd` to the directory containing the `PackageLayout.xml` with the correct paths (if you use the local path as in the sample package layout, this would be from your .exe output directory) +3. `mkdir Package` to create an output directory +4. To package the file into the `Package` directory, use: + `makepkg pack /f PackageLayout.xml /lt /d . /nogameos /pc /pd Package` +5. To install the package, use: + `wdapp install PACKAGENAME.msixvc` +6. Once the package is installed, you can run it from the start menu. +7. As with when running from Visual Studio, if you need to test any Xbox Live functionality you must switch to the correct sandbox. + + +Troubleshooting +--------------- + +#### Xbox Live Login does not work + +As of June 2022 GDK, you must have a valid Title Id and MSAAppId in order to test Xbox Live functionality such as user login. Make sure these are set correctly in the `MicrosoftGame.config`. This means that even testgdk will not let you login without setting these properties to valid values. + +Furthermore, confirm that your PC is set to the correct sandbox. + + +#### "The current user has already installed an unpackaged version of this app. A packaged version cannot replace this." error when installing + +Prior to June 2022 GDK, running from the Visual Studio debugger would still locally register the app (and it would appear on the start menu). To fix this, you have to uninstall it (it's simplest to right click on it from the start menu to uninstall it). diff --git a/docs/README-git.md b/docs/README-git.md index fd12fd9f65490..3f03488ae828e 100644 --- a/docs/README-git.md +++ b/docs/README-git.md @@ -1,19 +1,19 @@ -git -========= - -The latest development version of SDL is available via git. -Git allows you to get up-to-the-minute fixes and enhancements; -as a developer works on a source tree, you can use "git" to mirror that -source tree instead of waiting for an official release. Please look -at the Git website ( https://git-scm.com/ ) for more -information on using git, where you can also download software for -macOS, Windows, and Unix systems. - - git clone https://github.com/libsdl-org/SDL - -If you are building SDL via configure, you will need to run autogen.sh -before running configure. - -There is a web interface to the Git repository at: - http://github.com/libsdl-org/SDL/ - +git +========= + +The latest development version of SDL is available via git. +Git allows you to get up-to-the-minute fixes and enhancements; +as a developer works on a source tree, you can use "git" to mirror that +source tree instead of waiting for an official release. Please look +at the Git website ( https://git-scm.com/ ) for more +information on using git, where you can also download software for +macOS, Windows, and Unix systems. + + git clone https://github.com/libsdl-org/SDL + +If you are building SDL via configure, you will need to run autogen.sh +before running configure. + +There is a web interface to the Git repository at: + http://github.com/libsdl-org/SDL/ + diff --git a/docs/README-hg.md b/docs/README-hg.md index bd4e67263db45..b42aaa5b2ccae 100644 --- a/docs/README-hg.md +++ b/docs/README-hg.md @@ -1,7 +1,7 @@ -Mercurial -====== - -We are no longer hosted in Mercurial. Please see README-git.md for details. - -Thanks! - +Mercurial +====== + +We are no longer hosted in Mercurial. Please see README-git.md for details. + +Thanks! + diff --git a/docs/README-highdpi.md b/docs/README-highdpi.md index 6c3d51480239c..fd28575dda7bd 100644 --- a/docs/README-highdpi.md +++ b/docs/README-highdpi.md @@ -1,8 +1,8 @@ - -SDL 3.0 has new support for high DPI displays - -Displays now have a content display scale, which is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability. You can query the display content scale using `SDL_GetDisplayContentScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event. - -The window size is now distinct from the window pixel size, and the ratio between the two is the window pixel density. If the window is created with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, SDL will try to match the native pixel density for the display, otherwise it will try to have the pixel size match the window size. You can query the window pixel density using `SDL_GetWindowPixelDensity()`. You can query the window pixel size using `SDL_GetWindowSizeInPixels()`, and when this changes you get an `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event. You are guaranteed to get a `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event when a window is created and resized, and you can use this event to create and resize your graphics context for the window. - -The window has a display scale, which is the scale from the pixel resolution to the desired content size, e.g. the combination of the pixel density and the content scale. For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window with the high density flag on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0. You can query the window display scale using `SDL_GetWindowDisplayScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event. + +SDL 3.0 has new support for high DPI displays + +Displays now have a content display scale, which is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability. You can query the display content scale using `SDL_GetDisplayContentScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event. + +The window size is now distinct from the window pixel size, and the ratio between the two is the window pixel density. If the window is created with the `SDL_WINDOW_HIGH_PIXEL_DENSITY` flag, SDL will try to match the native pixel density for the display, otherwise it will try to have the pixel size match the window size. You can query the window pixel density using `SDL_GetWindowPixelDensity()`. You can query the window pixel size using `SDL_GetWindowSizeInPixels()`, and when this changes you get an `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event. You are guaranteed to get a `SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` event when a window is created and resized, and you can use this event to create and resize your graphics context for the window. + +The window has a display scale, which is the scale from the pixel resolution to the desired content size, e.g. the combination of the pixel density and the content scale. For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window with the high density flag on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0. You can query the window display scale using `SDL_GetWindowDisplayScale()`, and when this changes you get an `SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED` event. diff --git a/docs/README-ios.md b/docs/README-ios.md index 6e48af9434713..221cb27d68a1f 100644 --- a/docs/README-ios.md +++ b/docs/README-ios.md @@ -1,272 +1,272 @@ -iOS -====== - -Building the Simple DirectMedia Layer for iOS 9.0+ -============================================================================== - -Requirements: macOS 10.9 or later and the iOS 9.0 or newer SDK. - -Instructions: - -1. Open SDL.xcodeproj (located in Xcode/SDL) in Xcode. -2. Select your desired target, and hit build. - - -Using the Simple DirectMedia Layer for iOS -============================================================================== - -1. Run Xcode and create a new project using the iOS Game template, selecting the Objective C language and Metal game technology. -2. In the main view, delete all files except for Assets and LaunchScreen -3. Right click the project in the main view, select "Add Files...", and add the SDL project, Xcode/SDL/SDL.xcodeproj -4. Select the project in the main view, go to the "Info" tab and under "Custom iOS Target Properties" remove the line "Main storyboard file base name" -5. Select the project in the main view, go to the "Build Settings" tab, select "All", and edit "Header Search Path" and drag over the SDL "Public Headers" folder from the left -6. Select the project in the main view, go to the "Build Phases" tab, select "Link Binary With Libraries", and add SDL3.framework from "Framework-iOS" -7. Select the project in the main view, go to the "General" tab, scroll down to "Frameworks, Libraries, and Embedded Content", and select "Embed & Sign" for the SDL library. -8. Add the source files that you would normally have for an SDL program, making sure to have #include "SDL.h" at the top of the file containing your main() function. -9. Add any assets that your application needs. -10. Enjoy! - - -TODO: Add information regarding App Store requirements such as icons, etc. - - -Notes -- Retina / High-DPI and window sizes -============================================================================== - -Window and display mode sizes in SDL are in points rather than in pixels. -On iOS this means that a window created on an iPhone 6 will have a size in -points of 375 x 667, rather than a size in pixels of 750 x 1334. All iOS apps -are expected to size their content based on points rather than pixels, -as this allows different iOS devices to have different pixel densities -(Retina versus non-Retina screens, etc.) without apps caring too much. - -SDL_GetWindowSize() and mouse coordinates are in points rather than pixels, -but the window will have a much greater pixel density when the device supports -it, and the SDL_GetWindowSizeInPixels() can be called to determine the size -in pixels of the drawable screen framebuffer. - -The SDL 2D rendering API will automatically handle this for you, by default -providing a rendering area in points, and you can call SDL_SetRenderLogicalPresentation() -to gain access to the higher density resolution. - -Some OpenGL ES functions such as glViewport expect sizes in pixels rather than -sizes in points. When doing 2D rendering with OpenGL ES, an orthographic projection -matrix using the size in points (SDL_GetWindowSize()) can be used in order to -display content at the same scale no matter whether a Retina device is used or not. - - -Notes -- Application events -============================================================================== - -On iOS the application goes through a fixed life cycle and you will get -notifications of state changes via application events. When these events -are delivered you must handle them in an event callback because the OS may -not give you any processing time after the events are delivered. - -e.g. - - int HandleAppEvents(void *userdata, SDL_Event *event) - { - switch (event->type) - { - case SDL_EVENT_TERMINATING: - /* Terminate the app. - Shut everything down before returning from this function. - */ - return 0; - case SDL_EVENT_LOW_MEMORY: - /* You will get this when your app is paused and iOS wants more memory. - Release as much memory as possible. - */ - return 0; - case SDL_EVENT_WILL_ENTER_BACKGROUND: - /* Prepare your app to go into the background. Stop loops, etc. - This gets called when the user hits the home button, or gets a call. - */ - return 0; - case SDL_EVENT_DID_ENTER_BACKGROUND: - /* This will get called if the user accepted whatever sent your app to the background. - If the user got a phone call and canceled it, you'll instead get an SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops. - When you get this, you have 5 seconds to save all your state or the app will be terminated. - Your app is NOT active at this point. - */ - return 0; - case SDL_EVENT_WILL_ENTER_FOREGROUND: - /* This call happens when your app is coming back to the foreground. - Restore all your state here. - */ - return 0; - case SDL_EVENT_DID_ENTER_FOREGROUND: - /* Restart your loops here. - Your app is interactive and getting CPU again. - */ - return 0; - default: - /* No special processing, add it to the event queue */ - return 1; - } - } - - int main(int argc, char *argv[]) - { - SDL_SetEventFilter(HandleAppEvents, NULL); - - ... run your main loop - - return 0; - } - - -Notes -- Accelerometer as Joystick -============================================================================== - -SDL for iPhone supports polling the built in accelerometer as a joystick device. For an example on how to do this, see the accelerometer.c in the demos directory. - -The main thing to note when using the accelerometer with SDL is that while the iPhone natively reports accelerometer as floating point values in units of g-force, SDL_GetJoystickAxis() reports joystick values as signed integers. Hence, in order to convert between the two, some clamping and scaling is necessary on the part of the iPhone SDL joystick driver. To convert SDL_GetJoystickAxis() reported values BACK to units of g-force, simply multiply the values by SDL_IPHONE_MAX_GFORCE / 0x7FFF. - - -Notes -- Keyboard -============================================================================== - -The SDL keyboard API has been extended to support on-screen keyboards: - -void SDL_StartTextInput() - -- enables text events and reveals the onscreen keyboard. - -void SDL_StopTextInput() - -- disables text events and hides the onscreen keyboard. - -SDL_bool SDL_TextInputActive() - -- returns whether or not text events are enabled (and the onscreen keyboard is visible) - - -Notes -- Mouse -============================================================================== - -iOS now supports Bluetooth mice on iPad, but by default will provide the mouse input as touch. In order for SDL to see the real mouse events, you should set the key UIApplicationSupportsIndirectInputEvents to true in your Info.plist - - -Notes -- Reading and Writing files -============================================================================== - -Each application installed on iPhone resides in a sandbox which includes its own Application Home directory. Your application may not access files outside this directory. - -Once your application is installed its directory tree looks like: - - MySDLApp Home/ - MySDLApp.app - Documents/ - Library/ - Preferences/ - tmp/ - -When your SDL based iPhone application starts up, it sets the working directory to the main bundle (MySDLApp Home/MySDLApp.app), where your application resources are stored. You cannot write to this directory. Instead, I advise you to write document files to "../Documents/" and preferences to "../Library/Preferences". - -More information on this subject is available here: -http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html - - -Notes -- xcFramework -============================================================================== - -The SDL.xcodeproj file now includes a target to build SDL3.xcframework. An xcframework is a new (Xcode 11) uber-framework which can handle any combination of processor type and target OS platform. - -In the past, iOS devices were always an ARM variant processor, and the simulator was always i386 or x86_64, and thus libraries could be combined into a single framework for both simulator and device. With the introduction of the Apple Silicon ARM-based machines, regular frameworks would collide as CPU type was no longer sufficient to differentiate the platform. So Apple created the new xcframework library package. - -The xcframework target builds into a Products directory alongside the SDL.xcodeproj file, as SDL3.xcframework. This can be brought in to any iOS project and will function properly for both simulator and device, no matter their CPUs. Note that Intel Macs cannot cross-compile for Apple Silicon Macs. If you need AS compatibility, perform this build on an Apple Silicon Mac. - -This target requires Xcode 11 or later. The target will simply fail to build if attempted on older Xcodes. - -In addition, on Apple platforms, main() cannot be in a dynamically loaded library. -However, unlike in SDL2, in SDL3 SDL_main is implemented inline in SDL_main.h, so you don't need to link against a static libSDL3main.lib, and you don't need to copy a .c file from the SDL3 source either. -This means that iOS apps which used the statically-linked libSDL3.lib and now link with the xcframwork can just `#include ` in the source file that contains their standard `int main(int argc; char *argv[])` function to get a header-only SDL_main implementation that calls the `SDL_RunApp()` with your standard main function. - -Using an xcFramework is similar to using a regular framework. However, issues have been seen with the build system not seeing the headers in the xcFramework. To remedy this, add the path to the xcFramework in your app's target ==> Build Settings ==> Framework Search Paths and mark it recursive (this is critical). Also critical is to remove "*.framework" from Build Settings ==> Sub-Directories to Exclude in Recursive Searches. Clean the build folder, and on your next build the build system should be able to see any of these in your code, as expected: - -#include "SDL_main.h" -#include -#include - - -Notes -- iPhone SDL limitations -============================================================================== - -Windows: - Full-size, single window applications only. You cannot create multi-window SDL applications for iPhone OS. The application window will fill the display, though you have the option of turning on or off the menu-bar (pass SDL_CreateWindow() the flag SDL_WINDOW_BORDERLESS). - -Textures: - The optimal texture formats on iOS are SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_XBGR8888, and SDL_PIXELFORMAT_RGB24 pixel formats. - -Loading Shared Objects: - This is disabled by default since it seems to break the terms of the iOS SDK agreement for iOS versions prior to iOS 8. It can be re-enabled in SDL_config_ios.h. - - -Notes -- CoreBluetooth.framework -============================================================================== - -SDL_JOYSTICK_HIDAPI is disabled by default. It can give you access to a lot -more game controller devices, but it requires permission from the user before -your app will be able to talk to the Bluetooth hardware. "Made For iOS" -branded controllers do not need this as we don't have to speak to them -directly with raw bluetooth, so many apps can live without this. - -You'll need to link with CoreBluetooth.framework and add something like this -to your Info.plist: - -NSBluetoothPeripheralUsageDescription -MyApp would like to remain connected to nearby bluetooth Game Controllers and Game Pads even when you're not using the app. - - -Game Center -============================================================================== - -Game Center integration might require that you break up your main loop in order to yield control back to the system. In other words, instead of running an endless main loop, you run each frame in a callback function, using: - - int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); - -This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run. - -e.g. - - extern "C" - void ShowFrame(void*) - { - ... do event handling, frame logic and rendering ... - } - - int main(int argc, char *argv[]) - { - ... initialize game ... - - #ifdef __IOS__ - // Initialize the Game Center for scoring and matchmaking - InitGameCenter(); - - // Set up the game to run in the window animation callback on iOS - // so that Game Center and so forth works correctly. - SDL_iPhoneSetAnimationCallback(window, 1, ShowFrame, NULL); - #else - while ( running ) { - ShowFrame(0); - DelayFrame(); - } - #endif - return 0; - } - - -Deploying to older versions of iOS -============================================================================== - -SDL supports deploying to older versions of iOS than are supported by the latest version of Xcode, all the way back to iOS 8.0 - -In order to do that you need to download an older version of Xcode: -https://developer.apple.com/download/more/?name=Xcode - -Open the package contents of the older Xcode and your newer version of Xcode and copy over the folders in Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport - -Then open the file Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist and add the versions of iOS you want to deploy to the key Root/DefaultProperties/DEPLOYMENT_TARGET_SUGGESTED_VALUES - -Open your project and set your deployment target to the desired version of iOS - -Finally, remove GameController from the list of frameworks linked by your application and edit the build settings for "Other Linker Flags" and add -weak_framework GameController +iOS +====== + +Building the Simple DirectMedia Layer for iOS 9.0+ +============================================================================== + +Requirements: macOS 10.9 or later and the iOS 9.0 or newer SDK. + +Instructions: + +1. Open SDL.xcodeproj (located in Xcode/SDL) in Xcode. +2. Select your desired target, and hit build. + + +Using the Simple DirectMedia Layer for iOS +============================================================================== + +1. Run Xcode and create a new project using the iOS Game template, selecting the Objective C language and Metal game technology. +2. In the main view, delete all files except for Assets and LaunchScreen +3. Right click the project in the main view, select "Add Files...", and add the SDL project, Xcode/SDL/SDL.xcodeproj +4. Select the project in the main view, go to the "Info" tab and under "Custom iOS Target Properties" remove the line "Main storyboard file base name" +5. Select the project in the main view, go to the "Build Settings" tab, select "All", and edit "Header Search Path" and drag over the SDL "Public Headers" folder from the left +6. Select the project in the main view, go to the "Build Phases" tab, select "Link Binary With Libraries", and add SDL3.framework from "Framework-iOS" +7. Select the project in the main view, go to the "General" tab, scroll down to "Frameworks, Libraries, and Embedded Content", and select "Embed & Sign" for the SDL library. +8. Add the source files that you would normally have for an SDL program, making sure to have #include "SDL.h" at the top of the file containing your main() function. +9. Add any assets that your application needs. +10. Enjoy! + + +TODO: Add information regarding App Store requirements such as icons, etc. + + +Notes -- Retina / High-DPI and window sizes +============================================================================== + +Window and display mode sizes in SDL are in points rather than in pixels. +On iOS this means that a window created on an iPhone 6 will have a size in +points of 375 x 667, rather than a size in pixels of 750 x 1334. All iOS apps +are expected to size their content based on points rather than pixels, +as this allows different iOS devices to have different pixel densities +(Retina versus non-Retina screens, etc.) without apps caring too much. + +SDL_GetWindowSize() and mouse coordinates are in points rather than pixels, +but the window will have a much greater pixel density when the device supports +it, and the SDL_GetWindowSizeInPixels() can be called to determine the size +in pixels of the drawable screen framebuffer. + +The SDL 2D rendering API will automatically handle this for you, by default +providing a rendering area in points, and you can call SDL_SetRenderLogicalPresentation() +to gain access to the higher density resolution. + +Some OpenGL ES functions such as glViewport expect sizes in pixels rather than +sizes in points. When doing 2D rendering with OpenGL ES, an orthographic projection +matrix using the size in points (SDL_GetWindowSize()) can be used in order to +display content at the same scale no matter whether a Retina device is used or not. + + +Notes -- Application events +============================================================================== + +On iOS the application goes through a fixed life cycle and you will get +notifications of state changes via application events. When these events +are delivered you must handle them in an event callback because the OS may +not give you any processing time after the events are delivered. + +e.g. + + int HandleAppEvents(void *userdata, SDL_Event *event) + { + switch (event->type) + { + case SDL_EVENT_TERMINATING: + /* Terminate the app. + Shut everything down before returning from this function. + */ + return 0; + case SDL_EVENT_LOW_MEMORY: + /* You will get this when your app is paused and iOS wants more memory. + Release as much memory as possible. + */ + return 0; + case SDL_EVENT_WILL_ENTER_BACKGROUND: + /* Prepare your app to go into the background. Stop loops, etc. + This gets called when the user hits the home button, or gets a call. + */ + return 0; + case SDL_EVENT_DID_ENTER_BACKGROUND: + /* This will get called if the user accepted whatever sent your app to the background. + If the user got a phone call and canceled it, you'll instead get an SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops. + When you get this, you have 5 seconds to save all your state or the app will be terminated. + Your app is NOT active at this point. + */ + return 0; + case SDL_EVENT_WILL_ENTER_FOREGROUND: + /* This call happens when your app is coming back to the foreground. + Restore all your state here. + */ + return 0; + case SDL_EVENT_DID_ENTER_FOREGROUND: + /* Restart your loops here. + Your app is interactive and getting CPU again. + */ + return 0; + default: + /* No special processing, add it to the event queue */ + return 1; + } + } + + int main(int argc, char *argv[]) + { + SDL_SetEventFilter(HandleAppEvents, NULL); + + ... run your main loop + + return 0; + } + + +Notes -- Accelerometer as Joystick +============================================================================== + +SDL for iPhone supports polling the built in accelerometer as a joystick device. For an example on how to do this, see the accelerometer.c in the demos directory. + +The main thing to note when using the accelerometer with SDL is that while the iPhone natively reports accelerometer as floating point values in units of g-force, SDL_GetJoystickAxis() reports joystick values as signed integers. Hence, in order to convert between the two, some clamping and scaling is necessary on the part of the iPhone SDL joystick driver. To convert SDL_GetJoystickAxis() reported values BACK to units of g-force, simply multiply the values by SDL_IPHONE_MAX_GFORCE / 0x7FFF. + + +Notes -- Keyboard +============================================================================== + +The SDL keyboard API has been extended to support on-screen keyboards: + +void SDL_StartTextInput() + -- enables text events and reveals the onscreen keyboard. + +void SDL_StopTextInput() + -- disables text events and hides the onscreen keyboard. + +SDL_bool SDL_TextInputActive() + -- returns whether or not text events are enabled (and the onscreen keyboard is visible) + + +Notes -- Mouse +============================================================================== + +iOS now supports Bluetooth mice on iPad, but by default will provide the mouse input as touch. In order for SDL to see the real mouse events, you should set the key UIApplicationSupportsIndirectInputEvents to true in your Info.plist + + +Notes -- Reading and Writing files +============================================================================== + +Each application installed on iPhone resides in a sandbox which includes its own Application Home directory. Your application may not access files outside this directory. + +Once your application is installed its directory tree looks like: + + MySDLApp Home/ + MySDLApp.app + Documents/ + Library/ + Preferences/ + tmp/ + +When your SDL based iPhone application starts up, it sets the working directory to the main bundle (MySDLApp Home/MySDLApp.app), where your application resources are stored. You cannot write to this directory. Instead, I advise you to write document files to "../Documents/" and preferences to "../Library/Preferences". + +More information on this subject is available here: +http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html + + +Notes -- xcFramework +============================================================================== + +The SDL.xcodeproj file now includes a target to build SDL3.xcframework. An xcframework is a new (Xcode 11) uber-framework which can handle any combination of processor type and target OS platform. + +In the past, iOS devices were always an ARM variant processor, and the simulator was always i386 or x86_64, and thus libraries could be combined into a single framework for both simulator and device. With the introduction of the Apple Silicon ARM-based machines, regular frameworks would collide as CPU type was no longer sufficient to differentiate the platform. So Apple created the new xcframework library package. + +The xcframework target builds into a Products directory alongside the SDL.xcodeproj file, as SDL3.xcframework. This can be brought in to any iOS project and will function properly for both simulator and device, no matter their CPUs. Note that Intel Macs cannot cross-compile for Apple Silicon Macs. If you need AS compatibility, perform this build on an Apple Silicon Mac. + +This target requires Xcode 11 or later. The target will simply fail to build if attempted on older Xcodes. + +In addition, on Apple platforms, main() cannot be in a dynamically loaded library. +However, unlike in SDL2, in SDL3 SDL_main is implemented inline in SDL_main.h, so you don't need to link against a static libSDL3main.lib, and you don't need to copy a .c file from the SDL3 source either. +This means that iOS apps which used the statically-linked libSDL3.lib and now link with the xcframwork can just `#include ` in the source file that contains their standard `int main(int argc; char *argv[])` function to get a header-only SDL_main implementation that calls the `SDL_RunApp()` with your standard main function. + +Using an xcFramework is similar to using a regular framework. However, issues have been seen with the build system not seeing the headers in the xcFramework. To remedy this, add the path to the xcFramework in your app's target ==> Build Settings ==> Framework Search Paths and mark it recursive (this is critical). Also critical is to remove "*.framework" from Build Settings ==> Sub-Directories to Exclude in Recursive Searches. Clean the build folder, and on your next build the build system should be able to see any of these in your code, as expected: + +#include "SDL_main.h" +#include +#include + + +Notes -- iPhone SDL limitations +============================================================================== + +Windows: + Full-size, single window applications only. You cannot create multi-window SDL applications for iPhone OS. The application window will fill the display, though you have the option of turning on or off the menu-bar (pass SDL_CreateWindow() the flag SDL_WINDOW_BORDERLESS). + +Textures: + The optimal texture formats on iOS are SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_XBGR8888, and SDL_PIXELFORMAT_RGB24 pixel formats. + +Loading Shared Objects: + This is disabled by default since it seems to break the terms of the iOS SDK agreement for iOS versions prior to iOS 8. It can be re-enabled in SDL_config_ios.h. + + +Notes -- CoreBluetooth.framework +============================================================================== + +SDL_JOYSTICK_HIDAPI is disabled by default. It can give you access to a lot +more game controller devices, but it requires permission from the user before +your app will be able to talk to the Bluetooth hardware. "Made For iOS" +branded controllers do not need this as we don't have to speak to them +directly with raw bluetooth, so many apps can live without this. + +You'll need to link with CoreBluetooth.framework and add something like this +to your Info.plist: + +NSBluetoothPeripheralUsageDescription +MyApp would like to remain connected to nearby bluetooth Game Controllers and Game Pads even when you're not using the app. + + +Game Center +============================================================================== + +Game Center integration might require that you break up your main loop in order to yield control back to the system. In other words, instead of running an endless main loop, you run each frame in a callback function, using: + + int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); + +This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run. + +e.g. + + extern "C" + void ShowFrame(void*) + { + ... do event handling, frame logic and rendering ... + } + + int main(int argc, char *argv[]) + { + ... initialize game ... + + #ifdef __IOS__ + // Initialize the Game Center for scoring and matchmaking + InitGameCenter(); + + // Set up the game to run in the window animation callback on iOS + // so that Game Center and so forth works correctly. + SDL_iPhoneSetAnimationCallback(window, 1, ShowFrame, NULL); + #else + while ( running ) { + ShowFrame(0); + DelayFrame(); + } + #endif + return 0; + } + + +Deploying to older versions of iOS +============================================================================== + +SDL supports deploying to older versions of iOS than are supported by the latest version of Xcode, all the way back to iOS 8.0 + +In order to do that you need to download an older version of Xcode: +https://developer.apple.com/download/more/?name=Xcode + +Open the package contents of the older Xcode and your newer version of Xcode and copy over the folders in Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport + +Then open the file Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist and add the versions of iOS you want to deploy to the key Root/DefaultProperties/DEPLOYMENT_TARGET_SUGGESTED_VALUES + +Open your project and set your deployment target to the desired version of iOS + +Finally, remove GameController from the list of frameworks linked by your application and edit the build settings for "Other Linker Flags" and add -weak_framework GameController diff --git a/docs/README-kmsbsd.md b/docs/README-kmsbsd.md index 1bd6d0fdbab86..76048170711ca 100644 --- a/docs/README-kmsbsd.md +++ b/docs/README-kmsbsd.md @@ -1,27 +1,27 @@ -KMSDRM on *BSD -================================================== - -KMSDRM is supported on FreeBSD and OpenBSD. DragonFlyBSD works but requires being a root user. NetBSD isn't supported yet because the application will crash when creating the KMSDRM screen. - -WSCONS support has been brought back, but only as an input backend. It will not be brought back as a video backend to ease maintenance. - -OpenBSD note: Note that the video backend assumes that the user has read/write permissions to the /dev/drm* devices. - - -SDL WSCONS input backend features -=================================================== -1. It is keymap-aware; it will work properly with different keymaps. -2. It has mouse support. -3. Accent input is supported. -4. Compose keys are supported. -5. AltGr and Meta Shift keys work as intended. - -Partially working or no input on OpenBSD/NetBSD. -================================================== - -The WSCONS input backend needs read/write access to the /dev/wskbd* devices, without which it will not work properly. /dev/wsmouse must also be read/write accessible, otherwise mouse input will not work. - -Partially working or no input on FreeBSD. -================================================== - -The evdev devices are only accessible to the root user by default. Edit devfs rules to allow access to such devices. The /dev/kbd* devices are also only accessible to the root user by default. Edit devfs rules to allow access to such devices. +KMSDRM on *BSD +================================================== + +KMSDRM is supported on FreeBSD and OpenBSD. DragonFlyBSD works but requires being a root user. NetBSD isn't supported yet because the application will crash when creating the KMSDRM screen. + +WSCONS support has been brought back, but only as an input backend. It will not be brought back as a video backend to ease maintenance. + +OpenBSD note: Note that the video backend assumes that the user has read/write permissions to the /dev/drm* devices. + + +SDL WSCONS input backend features +=================================================== +1. It is keymap-aware; it will work properly with different keymaps. +2. It has mouse support. +3. Accent input is supported. +4. Compose keys are supported. +5. AltGr and Meta Shift keys work as intended. + +Partially working or no input on OpenBSD/NetBSD. +================================================== + +The WSCONS input backend needs read/write access to the /dev/wskbd* devices, without which it will not work properly. /dev/wsmouse must also be read/write accessible, otherwise mouse input will not work. + +Partially working or no input on FreeBSD. +================================================== + +The evdev devices are only accessible to the root user by default. Edit devfs rules to allow access to such devices. The /dev/kbd* devices are also only accessible to the root user by default. Edit devfs rules to allow access to such devices. diff --git a/docs/README-linux.md b/docs/README-linux.md index 768a712525d9d..4ef7b97d6fa61 100644 --- a/docs/README-linux.md +++ b/docs/README-linux.md @@ -1,88 +1,88 @@ -Linux -================================================================================ - -By default SDL will only link against glibc, the rest of the features will be -enabled dynamically at runtime depending on the available features on the target -system. So, for example if you built SDL with XRandR support and the target -system does not have the XRandR libraries installed, it will be disabled -at runtime, and you won't get a missing library error, at least with the -default configuration parameters. - - -Build Dependencies --------------------------------------------------------------------------------- - -Ubuntu 18.04, all available features enabled: - - sudo apt-get install build-essential git make \ - pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \ - libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev \ - libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev \ - libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \ - libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev - -Ubuntu 22.04+ can also add `libpipewire-0.3-dev libwayland-dev libdecor-0-dev` to that command line. - -Fedora 35, all available features enabled: - - sudo yum install gcc git-core make cmake \ - alsa-lib-devel pulseaudio-libs-devel nas-devel pipewire-devel \ - libX11-devel libXext-devel libXrandr-devel libXcursor-devel libXfixes-devel \ - libXi-devel libXScrnSaver-devel dbus-devel ibus-devel fcitx-devel \ - systemd-devel mesa-libGL-devel libxkbcommon-devel mesa-libGLES-devel \ - mesa-libEGL-devel vulkan-devel wayland-devel wayland-protocols-devel \ - libdrm-devel mesa-libgbm-devel libusb-devel libdecor-devel \ - pipewire-jack-audio-connection-kit-devel \ - -NOTES: -- The sndio audio target is unavailable on Fedora (but probably not what you - should want to use anyhow). - - -Joystick does not work --------------------------------------------------------------------------------- - -If you compiled or are using a version of SDL with udev support (and you should!) -there's a few issues that may cause SDL to fail to detect your joystick. To -debug this, start by installing the evtest utility. On Ubuntu/Debian: - - sudo apt-get install evtest - -Then run: - - sudo evtest - -You'll hopefully see your joystick listed along with a name like "/dev/input/eventXX" -Now run: - - cat /dev/input/event/XX - -If you get a permission error, you need to set a udev rule to change the mode of -your device (see below) - -Also, try: - - sudo udevadm info --query=all --name=input/eventXX - -If you see a line stating ID_INPUT_JOYSTICK=1, great, if you don't see it, -you need to set up an udev rule to force this variable. - -A combined rule for the Saitek Pro Flight Rudder Pedals to fix both issues looks -like: - - SUBSYSTEM=="input", ATTRS{idProduct}=="0763", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" - SUBSYSTEM=="input", ATTRS{idProduct}=="0764", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" - -You can set up similar rules for your device by changing the values listed in -idProduct and idVendor. To obtain these values, try: - - sudo udevadm info -a --name=input/eventXX | grep idVendor - sudo udevadm info -a --name=input/eventXX | grep idProduct - -If multiple values come up for each of these, the one you want is the first one of each. - -On other systems which ship with an older udev (such as CentOS), you may need -to set up a rule such as: - - SUBSYSTEM=="input", ENV{ID_CLASS}=="joystick", ENV{ID_INPUT_JOYSTICK}="1" - +Linux +================================================================================ + +By default SDL will only link against glibc, the rest of the features will be +enabled dynamically at runtime depending on the available features on the target +system. So, for example if you built SDL with XRandR support and the target +system does not have the XRandR libraries installed, it will be disabled +at runtime, and you won't get a missing library error, at least with the +default configuration parameters. + + +Build Dependencies +-------------------------------------------------------------------------------- + +Ubuntu 18.04, all available features enabled: + + sudo apt-get install build-essential git make \ + pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \ + libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev \ + libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev \ + libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \ + libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev + +Ubuntu 22.04+ can also add `libpipewire-0.3-dev libwayland-dev libdecor-0-dev` to that command line. + +Fedora 35, all available features enabled: + + sudo yum install gcc git-core make cmake \ + alsa-lib-devel pulseaudio-libs-devel nas-devel pipewire-devel \ + libX11-devel libXext-devel libXrandr-devel libXcursor-devel libXfixes-devel \ + libXi-devel libXScrnSaver-devel dbus-devel ibus-devel fcitx-devel \ + systemd-devel mesa-libGL-devel libxkbcommon-devel mesa-libGLES-devel \ + mesa-libEGL-devel vulkan-devel wayland-devel wayland-protocols-devel \ + libdrm-devel mesa-libgbm-devel libusb-devel libdecor-devel \ + pipewire-jack-audio-connection-kit-devel \ + +NOTES: +- The sndio audio target is unavailable on Fedora (but probably not what you + should want to use anyhow). + + +Joystick does not work +-------------------------------------------------------------------------------- + +If you compiled or are using a version of SDL with udev support (and you should!) +there's a few issues that may cause SDL to fail to detect your joystick. To +debug this, start by installing the evtest utility. On Ubuntu/Debian: + + sudo apt-get install evtest + +Then run: + + sudo evtest + +You'll hopefully see your joystick listed along with a name like "/dev/input/eventXX" +Now run: + + cat /dev/input/event/XX + +If you get a permission error, you need to set a udev rule to change the mode of +your device (see below) + +Also, try: + + sudo udevadm info --query=all --name=input/eventXX + +If you see a line stating ID_INPUT_JOYSTICK=1, great, if you don't see it, +you need to set up an udev rule to force this variable. + +A combined rule for the Saitek Pro Flight Rudder Pedals to fix both issues looks +like: + + SUBSYSTEM=="input", ATTRS{idProduct}=="0763", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + SUBSYSTEM=="input", ATTRS{idProduct}=="0764", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +You can set up similar rules for your device by changing the values listed in +idProduct and idVendor. To obtain these values, try: + + sudo udevadm info -a --name=input/eventXX | grep idVendor + sudo udevadm info -a --name=input/eventXX | grep idProduct + +If multiple values come up for each of these, the one you want is the first one of each. + +On other systems which ship with an older udev (such as CentOS), you may need +to set up a rule such as: + + SUBSYSTEM=="input", ENV{ID_CLASS}=="joystick", ENV{ID_INPUT_JOYSTICK}="1" + diff --git a/docs/README-macos.md b/docs/README-macos.md index d66aa42840a0a..832278fa756b9 100644 --- a/docs/README-macos.md +++ b/docs/README-macos.md @@ -1,252 +1,252 @@ -# macOS - -These instructions are for people using Apple's macOS. - -From the developer's point of view, macOS is a sort of hybrid Mac and -Unix system, and you have the option of using either traditional -command line tools or Apple's IDE Xcode. - -# Command Line Build - -To build SDL using the command line, use the CMake build script: - -```bash -mkdir build -cd build -cmake .. -cmake --build . -sudo cmake --install . -``` - - -You can also build SDL as a Universal library (a single binary for both -64-bit Intel and ARM architectures): - -```bash -mkdir build -cd build -cmake .. "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" -cmake --build . -sudo cmake --install . -``` - -Please note that building SDL requires at least Xcode 6 and the 10.9 SDK. -PowerPC support for macOS has been officially dropped as of SDL 2.0.2. -32-bit Intel and macOS 10.8 runtime support has been officially dropped as -of SDL 2.24.0. - -To use the library once it's built, you essential have two possibilities: -use the traditional autoconf/automake/make method, or use Xcode. - - -# Caveats for using SDL with macOS - -If you register your own NSApplicationDelegate (using [NSApp setDelegate:]), -SDL will not register its own. This means that SDL will not terminate using -SDL_Quit if it receives a termination request, it will terminate like a -normal app, and it will not send a SDL_EVENT_DROP_FILE when you request to open a -file with the app. To solve these issues, put the following code in your -NSApplicationDelegate implementation: - - -```objc -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - if (SDL_GetEventState(SDL_EVENT_QUIT) == SDL_ENABLE) { - SDL_Event event; - event.type = SDL_EVENT_QUIT; - SDL_PushEvent(&event); - } - - return NSTerminateCancel; -} - -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - if (SDL_GetEventState(SDL_EVENT_DROP_FILE) == SDL_ENABLE) { - SDL_Event event; - event.type = SDL_EVENT_DROP_FILE; - event.drop.file = SDL_strdup([filename UTF8String]); - return (SDL_PushEvent(&event) > 0); - } - - return NO; -} -``` - -# Using the Simple DirectMedia Layer with a traditional Makefile - -An existing build system for your SDL app has good chances to work almost -unchanged on macOS, as long as you link with the SDL framework. However, -to produce a "real" Mac binary that you can distribute to users, you need -to put the generated binary into a so called "bundle", which is basically -a fancy folder with a name like "MyCoolGame.app". - -To get this build automatically, add something like the following rule to -your Makefile.am: - -```make -bundle_contents = APP_NAME.app/Contents -APP_NAME_bundle: EXE_NAME - mkdir -p $(bundle_contents)/MacOS - mkdir -p $(bundle_contents)/Resources - echo "APPL????" > $(bundle_contents)/PkgInfo - $(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/ -``` - -You should replace `EXE_NAME` with the name of the executable. `APP_NAME` is -what will be visible to the user in the Finder. Usually it will be the same -as `EXE_NAME` but capitalized. E.g. if `EXE_NAME` is "testgame" then `APP_NAME` -usually is "TestGame". You might also want to use `@PACKAGE@` to use the -package name as specified in your configure.ac file. - -If your project builds more than one application, you will have to do a bit -more. For each of your target applications, you need a separate rule. - -If you want the created bundles to be installed, you may want to add this -rule to your Makefile.am: - -```make -install-exec-hook: APP_NAME_bundle - rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app - mkdir -p $(DESTDIR)$(prefix)/Applications/ - cp -r $< /$(DESTDIR)$(prefix)Applications/ -``` - -This rule takes the Bundle created by the rule from step 3 and installs them -into "$(DESTDIR)$(prefix)/Applications/". - -Again, if you want to install multiple applications, you will have to augment -the make rule accordingly. - -But beware! That is only part of the story! With the above, you end up with -a barebones .app bundle, which is double-clickable from the Finder. But -there are some more things you should do before shipping your product... - -1. You'll need to copy the SDL framework into the Contents/Frameworks - folder in your bundle, so it is included along with your application. - -2. Add an 'Info.plist' to your application. That is a special XML file which - contains some meta-information about your application (like some copyright - information, the version of your app, the name of an optional icon file, - and other things). Part of that information is displayed by the Finder - when you click on the .app, or if you look at the "Get Info" window. - More information about Info.plist files can be found on Apple's homepage. - - -As a final remark, let me add that I use some of the techniques (and some -variations of them) in [Exult](https://github.com/exult/exult) and -[ScummVM](https://github.com/scummvm/scummvm); both are available in source on -the net, so feel free to take a peek at them for inspiration! - - -# Using the Simple DirectMedia Layer with Xcode - -These instructions are for using Apple's Xcode IDE to build SDL applications. - -## First steps - -The first thing to do is to unpack the Xcode.tar.gz archive in the -top level SDL directory (where the Xcode.tar.gz archive resides). -Because Stuffit Expander will unpack the archive into a subdirectory, -you should unpack the archive manually from the command line: - -```bash -cd [path_to_SDL_source] -tar zxf Xcode.tar.gz -``` - -This will create a new folder called Xcode, which you can browse -normally from the Finder. - -## Building the Framework - -The SDL Library is packaged as a framework bundle, an organized -relocatable folder hierarchy of executable code, interface headers, -and additional resources. For practical purposes, you can think of a -framework as a more user and system-friendly shared library, whose library -file behaves more or less like a standard UNIX shared library. - -To build the framework, simply open the framework project and build it. -By default, the framework bundle "SDL.framework" is installed in -/Library/Frameworks. Therefore, the testers and project stationary expect -it to be located there. However, it will function the same in any of the -following locations: - -* ~/Library/Frameworks -* /Local/Library/Frameworks -* /System/Library/Frameworks - -## Build Options - -There are two "Build Styles" (See the "Targets" tab) for SDL. -"Deployment" should be used if you aren't tweaking the SDL library. -"Development" should be used to debug SDL apps or the library itself. - -## Building the Testers - -Open the SDLTest project and build away! - -## Using the Project Stationary - -Copy the stationary to the indicated folders to access it from -the "New Project" and "Add target" menus. What could be easier? - -## Setting up a new project by hand - -Some of you won't want to use the Stationary so I'll give some tips: - -(this is accurate as of Xcode 12.5.) - -* Click "File" -> "New" -> "Project... -* Choose "macOS" and then "App" from the "Application" section. -* Fill out the options in the next window. User interface is "XIB" and - Language is "Objective-C". -* Remove "main.m" from your project -* Remove "MainMenu.xib" from your project -* Remove "AppDelegates.*" from your project -* Add "\$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path -* Add "\$(HOME)/Library/Frameworks" to the frameworks search path -* Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS" -* Add your files -* Clean and build - -## Building from command line - -Use `xcode-build` in the same directory as your .pbxproj file - -## Running your app - -You can send command line args to your app by either invoking it from -the command line (in *.app/Contents/MacOS) or by entering them in the -Executables" panel of the target settings. - -# Implementation Notes - -Some things that may be of interest about how it all works... - -## Working directory - -In SDL 1.2, the working directory of your SDL app is by default set to its -parent, but this is no longer the case in SDL 2.0. SDL2 does change the -working directory, which means it'll be whatever the command line prompt -that launched the program was using, or if launched by double-clicking in -the finger, it will be "/", the _root of the filesystem_. Plan accordingly! -You can use SDL_GetBasePath() to find where the program is running from and -chdir() there directly. - - -## You have a Cocoa App! - -Your SDL app is essentially a Cocoa application. When your app -starts up and the libraries finish loading, a Cocoa procedure is called, -which sets up the working directory and calls your main() method. -You are free to modify your Cocoa app with generally no consequence -to SDL. You cannot, however, easily change the SDL window itself. -Functionality may be added in the future to help this. - -# Bug reports - -Bugs are tracked at [the GitHub issue tracker](https://github.com/libsdl-org/SDL/issues/). -Please feel free to report bugs there! - +# macOS + +These instructions are for people using Apple's macOS. + +From the developer's point of view, macOS is a sort of hybrid Mac and +Unix system, and you have the option of using either traditional +command line tools or Apple's IDE Xcode. + +# Command Line Build + +To build SDL using the command line, use the CMake build script: + +```bash +mkdir build +cd build +cmake .. +cmake --build . +sudo cmake --install . +``` + + +You can also build SDL as a Universal library (a single binary for both +64-bit Intel and ARM architectures): + +```bash +mkdir build +cd build +cmake .. "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" +cmake --build . +sudo cmake --install . +``` + +Please note that building SDL requires at least Xcode 6 and the 10.9 SDK. +PowerPC support for macOS has been officially dropped as of SDL 2.0.2. +32-bit Intel and macOS 10.8 runtime support has been officially dropped as +of SDL 2.24.0. + +To use the library once it's built, you essential have two possibilities: +use the traditional autoconf/automake/make method, or use Xcode. + + +# Caveats for using SDL with macOS + +If you register your own NSApplicationDelegate (using [NSApp setDelegate:]), +SDL will not register its own. This means that SDL will not terminate using +SDL_Quit if it receives a termination request, it will terminate like a +normal app, and it will not send a SDL_EVENT_DROP_FILE when you request to open a +file with the app. To solve these issues, put the following code in your +NSApplicationDelegate implementation: + + +```objc +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + if (SDL_GetEventState(SDL_EVENT_QUIT) == SDL_ENABLE) { + SDL_Event event; + event.type = SDL_EVENT_QUIT; + SDL_PushEvent(&event); + } + + return NSTerminateCancel; +} + +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + if (SDL_GetEventState(SDL_EVENT_DROP_FILE) == SDL_ENABLE) { + SDL_Event event; + event.type = SDL_EVENT_DROP_FILE; + event.drop.file = SDL_strdup([filename UTF8String]); + return (SDL_PushEvent(&event) > 0); + } + + return NO; +} +``` + +# Using the Simple DirectMedia Layer with a traditional Makefile + +An existing build system for your SDL app has good chances to work almost +unchanged on macOS, as long as you link with the SDL framework. However, +to produce a "real" Mac binary that you can distribute to users, you need +to put the generated binary into a so called "bundle", which is basically +a fancy folder with a name like "MyCoolGame.app". + +To get this build automatically, add something like the following rule to +your Makefile.am: + +```make +bundle_contents = APP_NAME.app/Contents +APP_NAME_bundle: EXE_NAME + mkdir -p $(bundle_contents)/MacOS + mkdir -p $(bundle_contents)/Resources + echo "APPL????" > $(bundle_contents)/PkgInfo + $(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/ +``` + +You should replace `EXE_NAME` with the name of the executable. `APP_NAME` is +what will be visible to the user in the Finder. Usually it will be the same +as `EXE_NAME` but capitalized. E.g. if `EXE_NAME` is "testgame" then `APP_NAME` +usually is "TestGame". You might also want to use `@PACKAGE@` to use the +package name as specified in your configure.ac file. + +If your project builds more than one application, you will have to do a bit +more. For each of your target applications, you need a separate rule. + +If you want the created bundles to be installed, you may want to add this +rule to your Makefile.am: + +```make +install-exec-hook: APP_NAME_bundle + rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app + mkdir -p $(DESTDIR)$(prefix)/Applications/ + cp -r $< /$(DESTDIR)$(prefix)Applications/ +``` + +This rule takes the Bundle created by the rule from step 3 and installs them +into "$(DESTDIR)$(prefix)/Applications/". + +Again, if you want to install multiple applications, you will have to augment +the make rule accordingly. + +But beware! That is only part of the story! With the above, you end up with +a barebones .app bundle, which is double-clickable from the Finder. But +there are some more things you should do before shipping your product... + +1. You'll need to copy the SDL framework into the Contents/Frameworks + folder in your bundle, so it is included along with your application. + +2. Add an 'Info.plist' to your application. That is a special XML file which + contains some meta-information about your application (like some copyright + information, the version of your app, the name of an optional icon file, + and other things). Part of that information is displayed by the Finder + when you click on the .app, or if you look at the "Get Info" window. + More information about Info.plist files can be found on Apple's homepage. + + +As a final remark, let me add that I use some of the techniques (and some +variations of them) in [Exult](https://github.com/exult/exult) and +[ScummVM](https://github.com/scummvm/scummvm); both are available in source on +the net, so feel free to take a peek at them for inspiration! + + +# Using the Simple DirectMedia Layer with Xcode + +These instructions are for using Apple's Xcode IDE to build SDL applications. + +## First steps + +The first thing to do is to unpack the Xcode.tar.gz archive in the +top level SDL directory (where the Xcode.tar.gz archive resides). +Because Stuffit Expander will unpack the archive into a subdirectory, +you should unpack the archive manually from the command line: + +```bash +cd [path_to_SDL_source] +tar zxf Xcode.tar.gz +``` + +This will create a new folder called Xcode, which you can browse +normally from the Finder. + +## Building the Framework + +The SDL Library is packaged as a framework bundle, an organized +relocatable folder hierarchy of executable code, interface headers, +and additional resources. For practical purposes, you can think of a +framework as a more user and system-friendly shared library, whose library +file behaves more or less like a standard UNIX shared library. + +To build the framework, simply open the framework project and build it. +By default, the framework bundle "SDL.framework" is installed in +/Library/Frameworks. Therefore, the testers and project stationary expect +it to be located there. However, it will function the same in any of the +following locations: + +* ~/Library/Frameworks +* /Local/Library/Frameworks +* /System/Library/Frameworks + +## Build Options + +There are two "Build Styles" (See the "Targets" tab) for SDL. +"Deployment" should be used if you aren't tweaking the SDL library. +"Development" should be used to debug SDL apps or the library itself. + +## Building the Testers + +Open the SDLTest project and build away! + +## Using the Project Stationary + +Copy the stationary to the indicated folders to access it from +the "New Project" and "Add target" menus. What could be easier? + +## Setting up a new project by hand + +Some of you won't want to use the Stationary so I'll give some tips: + +(this is accurate as of Xcode 12.5.) + +* Click "File" -> "New" -> "Project... +* Choose "macOS" and then "App" from the "Application" section. +* Fill out the options in the next window. User interface is "XIB" and + Language is "Objective-C". +* Remove "main.m" from your project +* Remove "MainMenu.xib" from your project +* Remove "AppDelegates.*" from your project +* Add "\$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path +* Add "\$(HOME)/Library/Frameworks" to the frameworks search path +* Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS" +* Add your files +* Clean and build + +## Building from command line + +Use `xcode-build` in the same directory as your .pbxproj file + +## Running your app + +You can send command line args to your app by either invoking it from +the command line (in *.app/Contents/MacOS) or by entering them in the +Executables" panel of the target settings. + +# Implementation Notes + +Some things that may be of interest about how it all works... + +## Working directory + +In SDL 1.2, the working directory of your SDL app is by default set to its +parent, but this is no longer the case in SDL 2.0. SDL2 does change the +working directory, which means it'll be whatever the command line prompt +that launched the program was using, or if launched by double-clicking in +the finger, it will be "/", the _root of the filesystem_. Plan accordingly! +You can use SDL_GetBasePath() to find where the program is running from and +chdir() there directly. + + +## You have a Cocoa App! + +Your SDL app is essentially a Cocoa application. When your app +starts up and the libraries finish loading, a Cocoa procedure is called, +which sets up the working directory and calls your main() method. +You are free to modify your Cocoa app with generally no consequence +to SDL. You cannot, however, easily change the SDL window itself. +Functionality may be added in the future to help this. + +# Bug reports + +Bugs are tracked at [the GitHub issue tracker](https://github.com/libsdl-org/SDL/issues/). +Please feel free to report bugs there! + diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 072bf826d5694..40908bfdde9cb 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -1,194 +1,194 @@ -# Where an SDL program starts running. - -## History - -SDL has a long, complicated history with starting a program. - -In most of the civilized world, an application starts in a C-callable -function named "main". You probably learned it a long time ago: - -```c -int main(int argc, char **argv) -{ - printf("Hello world!\n"); - return 0; -} -``` - -But not all platforms work like this. Windows apps might want a different -function named "WinMain", for example, so SDL set out to paper over this -difference. - -Generally how this would work is: your app would always use the "standard" -`main(argc, argv)` function as its entry point, and `#include` the proper -SDL header before that, which did some macro magic. On platforms that used -a standard `main`, it would do nothing and what you saw was what you got. - -But those other platforms! If they needed something that _wasn't_ `main`, -SDL's macro magic would quietly rename your function to `SDL_main`, and -provide its own entry point that called it. Your app was none the wiser and -your code worked everywhere without changes. - - -## The main entry point in SDL3 - -Previous versions of SDL had a static library, SDLmain, that you would link -your app against. SDL3 still has the same macro tricks, but the static library -is gone. Now it's supplied by a "single-header library," which means you -`#include ` and that header will insert a small amount of -code into the source file that included it, so you no longer have to worry -about linking against an extra library that you might need on some platforms. -You just build your app and it works. - -You should _only_ include SDL_main.h from one file (the umbrella header, -SDL.h, does _not_ include it), and know that it will `#define main` to -something else, so if you use this symbol elsewhere as a variable name, etc, -it can cause you unexpected problems. - -SDL_main.h will also include platform-specific code (WinMain or whatnot) that -calls your _actual_ main function. This is compiled directly into your -program. - -If for some reason you need to include SDL_main.h in a file but also _don't_ -want it to generate this platform-specific code, you should define a special -macro before includin the header: - - -```c -#define SDL_MAIN_NOIMPL -``` - -If you are moving from SDL2, remove any references to the SDLmain static -library from your build system, and you should be done. Things should work as -they always have. - -If you have never controlled your process's entry point (you are using SDL -as a module from a general-purpose scripting language interpreter, or you're -using SDL in a plugin for some otherwise-unrelated app), then there is nothing -required of you here; there is no startup code in SDL's entry point code that -is required, so using SDL_main.h is completely optional. Just start using -the SDL API when you are ready. - - -## Main callbacks in SDL3 - -There is a second option in SDL3 for how to structure your program. This is -completely optional and you can ignore it if you're happy using a standard -"main" function. - -Some platforms would rather your program operate in chunks. Most of the time, -games tend to look like this at the highest level: - -```c -int main(int argc, char **argv) -{ - initialize(); - while (keep_running()) { - handle_new_events(); - do_one_frame_of_stuff(); - } - deinitialize(); -} -``` - -There are platforms that would rather be in charge of that `while` loop: -iOS would rather you return from main() immediately and then it will let you -know that it's time to update and draw the next frame of video. Emscripten -(programs that run on a web page) absolutely requires this to function at all. -Video targets like Wayland can notify the app when to draw a new frame, to -save battery life and cooperate with the compositor more closely. - -In most cases, you can add special-case code to your program to deal with this -on different platforms, but SDL3 offers a system to handle this transparently on -the app's behalf. - -To use this, you have to redesign the highest level of your app a little. Once -you do, it'll work on all supported SDL platforms without problems and -`#ifdef`s in your code. - -Instead of providing a "main" function, under this system, you would provide -several functions that SDL will call as appropriate. - -Using the callback entry points works on every platform, because on platforms -that don't require them, we can fake them with a simple loop in an internal -implementation of the usual SDL_main. - -The primary way we expect people to write SDL apps is still with SDL_main, and -this is not intended to replace it. If the app chooses to use this, it just -removes some platform-specific details they might have to otherwise manage, -and maybe removes a barrier to entry on some future platform. And you might -find you enjoy structuring your program like this more! - - -## How to use main callbacks in SDL3 - -To enable the callback entry points, you include SDL_main.h with an extra define, -from a single source file in your project: - -```c -#define SDL_MAIN_USE_CALLBACKS -#include -``` - -Once you do this, you do not write a "main" function at all (and if you do, -the app will likely fail to link). Instead, you provide the following -functions: - -First: - -```c -int SDL_AppInit(int argc, char **argv); -``` - -This will be called _once_ before anything else. argc/argv work like they -always do. If this returns 0, the app runs. If it returns < 0, the app calls -SDL_AppQuit and terminates with an exit code that reports an error to the -platform. If it returns > 0, the app calls SDL_AppQuit and terminates with -an exit code that reports success to the platform. This function should not -go into an infinite mainloop; it should do any one-time startup it requires -and then return. - -Then: - -```c -int SDL_AppIterate(void); -``` - -This is called over and over, possibly at the refresh rate of the display or -some other metric that the platform dictates. This is where the heart of your -app runs. It should return as quickly as reasonably possible, but it's not a -"run one memcpy and that's all the time you have" sort of thing. The app -should do any game updates, and render a frame of video. If it returns < 0, -SDL will call SDL_AppQuit and terminate the process with an exit code that -reports an error to the platform. If it returns > 0, the app calls -SDL_AppQuit and terminates with an exit code that reports success to the -platform. If it returns 0, then SDL_AppIterate will be called again at some -regular frequency. The platform may choose to run this more or less (perhaps -less in the background, etc), or it might just call this function in a loop -as fast as possible. You do not check the event queue in this function -(SDL_AppEvent exists for that). - -Next: - -```c -int SDL_AppEvent(const SDL_Event *event); -``` - -This will be called whenever an SDL event arrives, on the thread that runs -SDL_AppIterate. Your app should also not call SDL_PollEvent, SDL_PumpEvent, -etc, as SDL will manage all this for you. Return values are the same as from -SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. - - -Finally: - -```c -void SDL_AppQuit(void); -``` - -This is called once before terminating the app--assuming the app isn't being -forcibly killed or crashed--as a last chance to clean up. After this returns, -SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app -to call it, too). Process termination proceeds as if the app returned normally -from main(), so atexit handles will run, if your platform supports that. - +# Where an SDL program starts running. + +## History + +SDL has a long, complicated history with starting a program. + +In most of the civilized world, an application starts in a C-callable +function named "main". You probably learned it a long time ago: + +```c +int main(int argc, char **argv) +{ + printf("Hello world!\n"); + return 0; +} +``` + +But not all platforms work like this. Windows apps might want a different +function named "WinMain", for example, so SDL set out to paper over this +difference. + +Generally how this would work is: your app would always use the "standard" +`main(argc, argv)` function as its entry point, and `#include` the proper +SDL header before that, which did some macro magic. On platforms that used +a standard `main`, it would do nothing and what you saw was what you got. + +But those other platforms! If they needed something that _wasn't_ `main`, +SDL's macro magic would quietly rename your function to `SDL_main`, and +provide its own entry point that called it. Your app was none the wiser and +your code worked everywhere without changes. + + +## The main entry point in SDL3 + +Previous versions of SDL had a static library, SDLmain, that you would link +your app against. SDL3 still has the same macro tricks, but the static library +is gone. Now it's supplied by a "single-header library," which means you +`#include ` and that header will insert a small amount of +code into the source file that included it, so you no longer have to worry +about linking against an extra library that you might need on some platforms. +You just build your app and it works. + +You should _only_ include SDL_main.h from one file (the umbrella header, +SDL.h, does _not_ include it), and know that it will `#define main` to +something else, so if you use this symbol elsewhere as a variable name, etc, +it can cause you unexpected problems. + +SDL_main.h will also include platform-specific code (WinMain or whatnot) that +calls your _actual_ main function. This is compiled directly into your +program. + +If for some reason you need to include SDL_main.h in a file but also _don't_ +want it to generate this platform-specific code, you should define a special +macro before includin the header: + + +```c +#define SDL_MAIN_NOIMPL +``` + +If you are moving from SDL2, remove any references to the SDLmain static +library from your build system, and you should be done. Things should work as +they always have. + +If you have never controlled your process's entry point (you are using SDL +as a module from a general-purpose scripting language interpreter, or you're +using SDL in a plugin for some otherwise-unrelated app), then there is nothing +required of you here; there is no startup code in SDL's entry point code that +is required, so using SDL_main.h is completely optional. Just start using +the SDL API when you are ready. + + +## Main callbacks in SDL3 + +There is a second option in SDL3 for how to structure your program. This is +completely optional and you can ignore it if you're happy using a standard +"main" function. + +Some platforms would rather your program operate in chunks. Most of the time, +games tend to look like this at the highest level: + +```c +int main(int argc, char **argv) +{ + initialize(); + while (keep_running()) { + handle_new_events(); + do_one_frame_of_stuff(); + } + deinitialize(); +} +``` + +There are platforms that would rather be in charge of that `while` loop: +iOS would rather you return from main() immediately and then it will let you +know that it's time to update and draw the next frame of video. Emscripten +(programs that run on a web page) absolutely requires this to function at all. +Video targets like Wayland can notify the app when to draw a new frame, to +save battery life and cooperate with the compositor more closely. + +In most cases, you can add special-case code to your program to deal with this +on different platforms, but SDL3 offers a system to handle this transparently on +the app's behalf. + +To use this, you have to redesign the highest level of your app a little. Once +you do, it'll work on all supported SDL platforms without problems and +`#ifdef`s in your code. + +Instead of providing a "main" function, under this system, you would provide +several functions that SDL will call as appropriate. + +Using the callback entry points works on every platform, because on platforms +that don't require them, we can fake them with a simple loop in an internal +implementation of the usual SDL_main. + +The primary way we expect people to write SDL apps is still with SDL_main, and +this is not intended to replace it. If the app chooses to use this, it just +removes some platform-specific details they might have to otherwise manage, +and maybe removes a barrier to entry on some future platform. And you might +find you enjoy structuring your program like this more! + + +## How to use main callbacks in SDL3 + +To enable the callback entry points, you include SDL_main.h with an extra define, +from a single source file in your project: + +```c +#define SDL_MAIN_USE_CALLBACKS +#include +``` + +Once you do this, you do not write a "main" function at all (and if you do, +the app will likely fail to link). Instead, you provide the following +functions: + +First: + +```c +int SDL_AppInit(int argc, char **argv); +``` + +This will be called _once_ before anything else. argc/argv work like they +always do. If this returns 0, the app runs. If it returns < 0, the app calls +SDL_AppQuit and terminates with an exit code that reports an error to the +platform. If it returns > 0, the app calls SDL_AppQuit and terminates with +an exit code that reports success to the platform. This function should not +go into an infinite mainloop; it should do any one-time startup it requires +and then return. + +Then: + +```c +int SDL_AppIterate(void); +``` + +This is called over and over, possibly at the refresh rate of the display or +some other metric that the platform dictates. This is where the heart of your +app runs. It should return as quickly as reasonably possible, but it's not a +"run one memcpy and that's all the time you have" sort of thing. The app +should do any game updates, and render a frame of video. If it returns < 0, +SDL will call SDL_AppQuit and terminate the process with an exit code that +reports an error to the platform. If it returns > 0, the app calls +SDL_AppQuit and terminates with an exit code that reports success to the +platform. If it returns 0, then SDL_AppIterate will be called again at some +regular frequency. The platform may choose to run this more or less (perhaps +less in the background, etc), or it might just call this function in a loop +as fast as possible. You do not check the event queue in this function +(SDL_AppEvent exists for that). + +Next: + +```c +int SDL_AppEvent(const SDL_Event *event); +``` + +This will be called whenever an SDL event arrives, on the thread that runs +SDL_AppIterate. Your app should also not call SDL_PollEvent, SDL_PumpEvent, +etc, as SDL will manage all this for you. Return values are the same as from +SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. + + +Finally: + +```c +void SDL_AppQuit(void); +``` + +This is called once before terminating the app--assuming the app isn't being +forcibly killed or crashed--as a last chance to clean up. After this returns, +SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app +to call it, too). Process termination proceeds as if the app returned normally +from main(), so atexit handles will run, if your platform supports that. + diff --git a/docs/README-migration.md b/docs/README-migration.md index 92351965f6abb..a7a97015efa91 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1,1356 +1,1356 @@ -# Migrating to SDL 3.0 - -This guide provides useful information for migrating applications from SDL 2.0 to SDL 3.0. - -Details on API changes are organized by SDL 2.0 header below. - -The file with your main() function should include , as that is no longer included in SDL.h. - -Many functions and symbols have been renamed. We have provided a handy Python script [rename_symbols.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_symbols.py) to rename SDL2 functions to their SDL3 counterparts: -```sh -rename_symbols.py --all-symbols source_code_path -``` - -It's also possible to apply a semantic patch to migrate more easily to SDL3: [SDL_migration.cocci](https://github.com/libsdl-org/SDL/blob/main/build-scripts/SDL_migration.cocci) - -SDL headers should now be included as `#include `. Typically that's the only header you'll need in your application unless you are using OpenGL or Vulkan functionality. We have provided a handy Python script [rename_headers.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_headers.py) to rename SDL2 headers to their SDL3 counterparts: -```sh -rename_headers.py source_code_path -``` - -CMake users should use this snippet to include SDL support in their project: -``` -find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) -target_link_libraries(mygame PRIVATE SDL3::SDL3) -``` - -Autotools users should use this snippet to include SDL support in their project: -``` -PKG_CHECK_MODULES([SDL3], [sdl3]) -``` -and then add $SDL3_CFLAGS to their project CFLAGS and $SDL3_LIBS to their project LDFLAGS - -Makefile users can use this snippet to include SDL support in their project: -``` -CFLAGS += $(shell pkg-config sdl3 --cflags) -LDFLAGS += $(shell pkg-config sdl3 --libs) -``` - -The SDL3test library has been renamed SDL3_test. - -The SDLmain library has been removed, it's been entirely replaced by SDL_main.h. - -The vi format comments have been removed from source code. Vim users can use the [editorconfig plugin](https://github.com/editorconfig/editorconfig-vim) to automatically set tab spacing for the SDL coding style. - -## SDL_atomic.h - -The following structures have been renamed: -- SDL_atomic_t => SDL_AtomicInt - -## SDL_audio.h - -The audio subsystem in SDL3 is dramatically different than SDL2. The primary way to play audio is no longer an audio callback; instead you bind SDL_AudioStreams to devices; however, there is still a callback method available if needed. - -The SDL 1.2 audio compatibility API has also been removed, as it was a simplified version of the audio callback interface. - -SDL3 will not implicitly initialize the audio subsystem on your behalf if you open a device without doing so. Please explicitly call SDL_Init(SDL_INIT_AUDIO) at some point. - -SDL3's audio subsystem offers an enormous amount of power over SDL2, but if you just want a simple migration of your existing code, you can ignore most of it. The simplest migration path from SDL2 looks something like this: - -In SDL2, you might have done something like this to play audio... - -```c - void SDLCALL MyAudioCallback(void *userdata, Uint8 * stream, int len) - { - /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` */ - } - - /* ...somewhere near startup... */ - SDL_AudioSpec my_desired_audio_format; - SDL_zero(my_desired_audio_format); - my_desired_audio_format.format = AUDIO_S16; - my_desired_audio_format.channels = 2; - my_desired_audio_format.freq = 44100; - my_desired_audio_format.samples = 1024; - my_desired_audio_format.callback = MyAudioCallback; - my_desired_audio_format.userdata = &my_audio_callback_user_data; - SDL_AudioDeviceID my_audio_device = SDL_OpenAudioDevice(NULL, 0, &my_desired_audio_format, NULL, 0); - SDL_PauseAudioDevice(my_audio_device, 0); -``` - -...in SDL3, you can do this... - -```c - void SDLCALL MyNewAudioCallback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) - { - /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` - * - * If you want to use the original callback, you could do something like this: - */ - if (additional_amount > 0) { - Uint8 *data = SDL_stack_alloc(Uint8, additional_amount); - if (data) { - MyAudioCallback(userdata, data, additional_amount); - SDL_PutAudioStreamData(stream, data, additional_amount); - SDL_stack_free(data); - } - } - } - - /* ...somewhere near startup... */ - const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; - SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyNewAudioCallback, &my_audio_callback_user_data); - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); -``` - -If you used SDL_QueueAudio instead of a callback in SDL2, this is also straightforward. - -```c - /* ...somewhere near startup... */ - const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; - SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); - - /* ...in your main loop... */ - /* calculate a little more audio into `buf`, add it to `stream` */ - SDL_PutAudioStreamData(stream, buf, buflen); - -``` - -...these same migration examples apply to audio capture, just using SDL_GetAudioStreamData instead of SDL_PutAudioStreamData. - -SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint. - -The `SDL_AUDIO_ALLOW_*` symbols have been removed; now one may request the format they desire from the audio device, but ultimately SDL_AudioStream will manage the difference. One can use SDL_GetAudioDeviceFormat() to see what the final format is, if any "allowed" changes should be accomodated by the app. - -SDL_AudioDeviceID now represents both an open audio device's handle (a "logical" device) and the instance ID that the hardware owns as long as it exists on the system (a "physical" device). The separation between device instances and device indexes is gone, and logical and physical devices are almost entirely interchangeable at the API level. - -Devices are opened by physical device instance ID, and a new logical instance ID is generated by the open operation; This allows any device to be opened multiple times, possibly by unrelated pieces of code. SDL will manage the logical devices to provide a single stream of audio to the physical device behind the scenes. - -Devices are not opened by an arbitrary string name anymore, but by device instance ID (or magic numbers to request a reasonable default, like a NULL string in SDL2). In SDL2, the string was used to open both a standard list of system devices, but also allowed for arbitrary devices, such as hostnames of network sound servers. In SDL3, many of the backends that supported arbitrary device names are obsolete and have been removed; of those that remain, arbitrary devices will be opened with a default device ID and an SDL_hint, so specific end-users can set an environment variable to fit their needs and apps don't have to concern themselves with it. - -Many functions that would accept a device index and an `iscapture` parameter now just take an SDL_AudioDeviceID, as they are unique across all devices, instead of separate indices into output and capture device lists. - -Rather than iterating over audio devices using a device index, there are new functions, SDL_GetAudioOutputDevices() and SDL_GetAudioCaptureDevices(), to get the current list of devices, and new functions to get information about devices from their instance ID: - -```c -{ - if (SDL_InitSubSystem(SDL_INIT_AUDIO) == 0) { - int i, num_devices; - SDL_AudioDeviceID *devices = SDL_GetAudioOutputDevices(&num_devices); - if (devices) { - for (i = 0; i < num_devices; ++i) { - SDL_AudioDeviceID instance_id = devices[i]; - char *name = SDL_GetAudioDeviceName(instance_id); - SDL_Log("AudioDevice %" SDL_PRIu32 ": %s\n", instance_id, name); - SDL_free(name); - } - SDL_free(devices); - } - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } -} -``` - -SDL_LockAudioDevice() and SDL_UnlockAudioDevice() have been removed, since there is no callback in another thread to protect. SDL's audio subsystem and SDL_AudioStream maintain their own locks internally, so audio streams are safe to use from any thread. If the app assigns a callback to a specific stream, it can use the stream's lock through SDL_LockAudioStream() if necessary. - -SDL_PauseAudioDevice() no longer takes a second argument; it always pauses the device. To unpause, use SDL_ResumeAudioDevice(). - -Audio devices, opened by SDL_OpenAudioDevice(), no longer start in a paused state, as they don't begin processing audio until a stream is bound. - -SDL_GetAudioDeviceStatus() has been removed; there is now SDL_AudioDevicePaused(). - -SDL_QueueAudio(), SDL_DequeueAudio, and SDL_ClearQueuedAudio and SDL_GetQueuedAudioSize() have been removed; an SDL_AudioStream bound to a device provides the exact same functionality. - -APIs that use channel counts used to use a Uint8 for the channel; now they use int. - -SDL_AudioSpec has been reduced; now it only holds format, channel, and sample rate. SDL_GetSilenceValueForFormat() can provide the information from the SDL_AudioSpec's `silence` field. The other SDL2 SDL_AudioSpec fields aren't relevant anymore. - -SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead. - -SDL_GetDefaultAudioInfo() is removed; SDL_GetAudioDeviceFormat() with SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or SDL_AUDIO_DEVICE_DEFAULT_CAPTURE. There is no replacement for querying the default device name; the string is no longer used to open devices, and SDL3 will migrate between physical devices on the fly if the system default changes, so if you must show this to the user, a generic name like "System default" is recommended. - -SDL_MixAudio() has been removed, as it relied on legacy SDL 1.2 quirks; SDL_MixAudioFormat() remains and offers the same functionality. - -SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint. - -SDL_FreeWAV has been removed and calls can be replaced with SDL_free. - -SDL_LoadWAV() is a proper function now and no longer a macro (but offers the same functionality otherwise). - -SDL_LoadWAV_RW() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec. - -SDL_AudioCVT interface has been removed, the SDL_AudioStream interface (for audio supplied in pieces) or the new SDL_ConvertAudioSamples() function (for converting a complete audio buffer in one call) can be used instead. - -Code that used to look like this: -```c - SDL_AudioCVT cvt; - SDL_BuildAudioCVT(&cvt, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate); - cvt.len = src_len; - cvt.buf = (Uint8 *) SDL_malloc(src_len * cvt.len_mult); - SDL_memcpy(cvt.buf, src_data, src_len); - SDL_ConvertAudio(&cvt); - do_something(cvt.buf, cvt.len_cvt); -``` -should be changed to: -```c - Uint8 *dst_data = NULL; - int dst_len = 0; - const SDL_AudioSpec src_spec = { src_format, src_channels, src_rate }; - const SDL_AudioSpec dst_spec = { dst_format, dst_channels, dst_rate }; - if (SDL_ConvertAudioSamples(&src_spec, src_data, src_len, &dst_spec, &dst_data, &dst_len) < 0) { - /* error */ - } - do_something(dst_data, dst_len); - SDL_free(dst_data); -``` - -AUDIO_U16, AUDIO_U16LSB, AUDIO_U16MSB, and AUDIO_U16SYS have been removed. They were not heavily used, and one could not memset a buffer in this format to silence with a single byte value. Use a different audio format. - -If you need to convert U16 audio data to a still-supported format at runtime, the fastest, lossless conversion is to SDL_AUDIO_S16: - -```c - /* this converts the buffer in-place. The buffer size does not change. */ - Sint16 *audio_ui16_to_si16(Uint16 *buffer, const size_t num_samples) - { - size_t i; - const Uint16 *src = buffer; - Sint16 *dst = (Sint16 *) buffer; - - for (i = 0; i < num_samples; i++) { - dst[i] = (Sint16) (src[i] ^ 0x8000); - } - - return dst; - } -``` - -All remaining `AUDIO_*` symbols have been renamed to `SDL_AUDIO_*` for API consistency, but othewise are identical in value and usage. - -In SDL2, SDL_AudioStream would convert/resample audio data during input (via SDL_AudioStreamPut). In SDL3, it does this work when requesting audio (via SDL_GetAudioStreamData, which would have been SDL_AudioStreamGet in SDL2). The way you use an AudioStream is roughly the same, just be aware that the workload moved to a different phase. - -In SDL2, SDL_AudioStreamAvailable() returns 0 if passed a NULL stream. In SDL3, the equivalent SDL_GetAudioStreamAvailable() call returns -1 and sets an error string, which matches other audiostream APIs' behavior. - -In SDL2, SDL_AUDIODEVICEREMOVED events would fire for open devices with the `which` field set to the SDL_AudioDeviceID of the lost device, and in later SDL2 releases, would also fire this event with a `which` field of zero for unopened devices, to signify that the app might want to refresh the available device list. In SDL3, this event works the same, except it won't ever fire with a zero; in this case it'll return the physical device's SDL_AudioDeviceID. Any still-open SDL_AudioDeviceIDs generated from this device with SDL_OpenAudioDevice() will also fire a separate event. - -The following functions have been renamed: -* SDL_AudioStreamAvailable() => SDL_GetAudioStreamAvailable() -* SDL_AudioStreamClear() => SDL_ClearAudioStream() -* SDL_AudioStreamFlush() => SDL_FlushAudioStream() -* SDL_AudioStreamGet() => SDL_GetAudioStreamData() -* SDL_AudioStreamPut() => SDL_PutAudioStreamData() -* SDL_FreeAudioStream() => SDL_DestroyAudioStream() -* SDL_NewAudioStream() => SDL_CreateAudioStream() - - -The following functions have been removed: -* SDL_GetNumAudioDevices() -* SDL_GetAudioDeviceSpec() -* SDL_ConvertAudio() -* SDL_BuildAudioCVT() -* SDL_OpenAudio() -* SDL_CloseAudio() -* SDL_PauseAudio() -* SDL_GetAudioStatus() -* SDL_GetAudioDeviceStatus() -* SDL_GetDefaultAudioInfo() -* SDL_LockAudio() -* SDL_LockAudioDevice() -* SDL_UnlockAudio() -* SDL_UnlockAudioDevice() -* SDL_MixAudio() -* SDL_QueueAudio() -* SDL_DequeueAudio() -* SDL_ClearAudioQueue() -* SDL_GetQueuedAudioSize() - -The following symbols have been renamed: -* AUDIO_F32 => SDL_AUDIO_F32LE -* AUDIO_F32LSB => SDL_AUDIO_F32LE -* AUDIO_F32MSB => SDL_AUDIO_F32BE -* AUDIO_F32SYS => SDL_AUDIO_F32 -* AUDIO_S16 => SDL_AUDIO_S16LE -* AUDIO_S16LSB => SDL_AUDIO_S16LE -* AUDIO_S16MSB => SDL_AUDIO_S16BE -* AUDIO_S16SYS => SDL_AUDIO_S16 -* AUDIO_S32 => SDL_AUDIO_S32LE -* AUDIO_S32LSB => SDL_AUDIO_S32LE -* AUDIO_S32MSB => SDL_AUDIO_S32BE -* AUDIO_S32SYS => SDL_AUDIO_S32 -* AUDIO_S8 => SDL_AUDIO_S8 -* AUDIO_U8 => SDL_AUDIO_U8 - -## SDL_cpuinfo.h - -The intrinsics headers (mmintrin.h, etc.) have been moved to `` and are no longer automatically included in SDL.h. - -SDL_Has3DNow() has been removed; there is no replacement. - -SDL_HasRDTSC() has been removed; there is no replacement. Don't use the RDTSC opcode in modern times, use SDL_GetPerformanceCounter and SDL_GetPerformanceFrequency instead. - -SDL_SIMDAlloc(), SDL_SIMDRealloc(), and SDL_SIMDFree() have been removed. You can use SDL_aligned_alloc() and SDL_aligned_free() with SDL_SIMDGetAlignment() to get the same functionality. - -## SDL_events.h - -The timestamp member of the SDL_Event structure now represents nanoseconds, and is populated with SDL_GetTicksNS() - -The timestamp_us member of the sensor events has been renamed sensor_timestamp and now represents nanoseconds. This value is filled in from the hardware, if available, and may not be synchronized with values returned from SDL_GetTicksNS(). - -You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). - -Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. - -Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. - -The SDL_DISPLAYEVENT_* events have been moved to top level events, and SDL_DISPLAYEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_DISPLAYEVENT and then checking for display events. You can compare the event >= SDL_EVENT_DISPLAY_FIRST and <= SDL_EVENT_DISPLAY_LAST if you need to see whether it's a display event. - -The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event. - -The SDL_EVENT_WINDOW_RESIZED event is always sent, even in response to SDL_SetWindowSize(). - -The SDL_EVENT_WINDOW_SIZE_CHANGED event has been removed, and you can use SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED to detect window backbuffer size changes. - -The gamepad event structures caxis, cbutton, cdevice, ctouchpad, and csensor have been renamed gaxis, gbutton, gdevice, gtouchpad, and gsensor. - -SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state. - -SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback. - -The following symbols have been renamed: -* SDL_APP_DIDENTERBACKGROUND => SDL_EVENT_DID_ENTER_BACKGROUND -* SDL_APP_DIDENTERFOREGROUND => SDL_EVENT_DID_ENTER_FOREGROUND -* SDL_APP_LOWMEMORY => SDL_EVENT_LOW_MEMORY -* SDL_APP_TERMINATING => SDL_EVENT_TERMINATING -* SDL_APP_WILLENTERBACKGROUND => SDL_EVENT_WILL_ENTER_BACKGROUND -* SDL_APP_WILLENTERFOREGROUND => SDL_EVENT_WILL_ENTER_FOREGROUND -* SDL_AUDIODEVICEADDED => SDL_EVENT_AUDIO_DEVICE_ADDED -* SDL_AUDIODEVICEREMOVED => SDL_EVENT_AUDIO_DEVICE_REMOVED -* SDL_CLIPBOARDUPDATE => SDL_EVENT_CLIPBOARD_UPDATE -* SDL_CONTROLLERAXISMOTION => SDL_EVENT_GAMEPAD_AXIS_MOTION -* SDL_CONTROLLERBUTTONDOWN => SDL_EVENT_GAMEPAD_BUTTON_DOWN -* SDL_CONTROLLERBUTTONUP => SDL_EVENT_GAMEPAD_BUTTON_UP -* SDL_CONTROLLERDEVICEADDED => SDL_EVENT_GAMEPAD_ADDED -* SDL_CONTROLLERDEVICEREMAPPED => SDL_EVENT_GAMEPAD_REMAPPED -* SDL_CONTROLLERDEVICEREMOVED => SDL_EVENT_GAMEPAD_REMOVED -* SDL_CONTROLLERSENSORUPDATE => SDL_EVENT_GAMEPAD_SENSOR_UPDATE -* SDL_CONTROLLERTOUCHPADDOWN => SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN -* SDL_CONTROLLERTOUCHPADMOTION => SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION -* SDL_CONTROLLERTOUCHPADUP => SDL_EVENT_GAMEPAD_TOUCHPAD_UP -* SDL_DROPBEGIN => SDL_EVENT_DROP_BEGIN -* SDL_DROPCOMPLETE => SDL_EVENT_DROP_COMPLETE -* SDL_DROPFILE => SDL_EVENT_DROP_FILE -* SDL_DROPTEXT => SDL_EVENT_DROP_TEXT -* SDL_FINGERDOWN => SDL_EVENT_FINGER_DOWN -* SDL_FINGERMOTION => SDL_EVENT_FINGER_MOTION -* SDL_FINGERUP => SDL_EVENT_FINGER_UP -* SDL_FIRSTEVENT => SDL_EVENT_FIRST -* SDL_JOYAXISMOTION => SDL_EVENT_JOYSTICK_AXIS_MOTION -* SDL_JOYBATTERYUPDATED => SDL_EVENT_JOYSTICK_BATTERY_UPDATED -* SDL_JOYBUTTONDOWN => SDL_EVENT_JOYSTICK_BUTTON_DOWN -* SDL_JOYBUTTONUP => SDL_EVENT_JOYSTICK_BUTTON_UP -* SDL_JOYDEVICEADDED => SDL_EVENT_JOYSTICK_ADDED -* SDL_JOYDEVICEREMOVED => SDL_EVENT_JOYSTICK_REMOVED -* SDL_JOYHATMOTION => SDL_EVENT_JOYSTICK_HAT_MOTION -* SDL_KEYDOWN => SDL_EVENT_KEY_DOWN -* SDL_KEYMAPCHANGED => SDL_EVENT_KEYMAP_CHANGED -* SDL_KEYUP => SDL_EVENT_KEY_UP -* SDL_LASTEVENT => SDL_EVENT_LAST -* SDL_LOCALECHANGED => SDL_EVENT_LOCALE_CHANGED -* SDL_MOUSEBUTTONDOWN => SDL_EVENT_MOUSE_BUTTON_DOWN -* SDL_MOUSEBUTTONUP => SDL_EVENT_MOUSE_BUTTON_UP -* SDL_MOUSEMOTION => SDL_EVENT_MOUSE_MOTION -* SDL_MOUSEWHEEL => SDL_EVENT_MOUSE_WHEEL -* SDL_POLLSENTINEL => SDL_EVENT_POLL_SENTINEL -* SDL_QUIT => SDL_EVENT_QUIT -* SDL_RENDER_DEVICE_RESET => SDL_EVENT_RENDER_DEVICE_RESET -* SDL_RENDER_TARGETS_RESET => SDL_EVENT_RENDER_TARGETS_RESET -* SDL_SENSORUPDATE => SDL_EVENT_SENSOR_UPDATE -* SDL_SYSWMEVENT => SDL_EVENT_SYSWM -* SDL_TEXTEDITING => SDL_EVENT_TEXT_EDITING -* SDL_TEXTEDITING_EXT => SDL_EVENT_TEXT_EDITING_EXT -* SDL_TEXTINPUT => SDL_EVENT_TEXT_INPUT -* SDL_USEREVENT => SDL_EVENT_USER - -The following structures have been renamed: -* SDL_ControllerAxisEvent => SDL_GamepadAxisEvent -* SDL_ControllerButtonEvent => SDL_GamepadButtonEvent -* SDL_ControllerDeviceEvent => SDL_GamepadDeviceEvent -* SDL_ControllerSensorEvent => SDL_GamepadSensorEvent -* SDL_ControllerTouchpadEvent => SDL_GamepadTouchpadEvent - -The following functions have been removed: -* SDL_EventState() - replaced with SDL_SetEventEnabled() -* SDL_GetEventState() - replaced with SDL_EventEnabled() - -## SDL_gamecontroller.h - -SDL_gamecontroller.h has been renamed SDL_gamepad.h, and all APIs have been renamed to match. - -The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the which member of the cdevice event structure. - -The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads. - -The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications will now need to provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. Using South as the accept button and East as the cancel button is a good default. - -SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events. - -SDL_CONTROLLER_TYPE_VIRTUAL has been removed, so virtual controllers can emulate other gamepad types. If you need to know whether a controller is virtual, you can use SDL_IsJoystickVirtual(). - -SDL_CONTROLLER_TYPE_AMAZON_LUNA has been removed, and can be replaced with this code: -```c -SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id) -{ - return ((vendor_id == 0x1949 && product_id == 0x0419) || - (vendor_id == 0x0171 && product_id == 0x0419)); -} -``` - -SDL_CONTROLLER_TYPE_GOOGLE_STADIA has been removed, and can be replaced with this code: -```c -SDL_bool SDL_IsJoystickGoogleStadiaController(Uint16 vendor_id, Uint16 product_id) -{ - return (vendor_id == 0x18d1 && product_id == 0x9400); -} -``` - -SDL_CONTROLLER_TYPE_NVIDIA_SHIELD has been removed, and can be replaced with this code: -```c -SDL_bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_id) -{ - return (vendor_id == 0x0955 && (product_id == 0x7210 || product_id == 0x7214)); -} -``` - -The following enums have been renamed: -* SDL_GameControllerAxis => SDL_GamepadAxis -* SDL_GameControllerBindType => SDL_GamepadBindingType -* SDL_GameControllerButton => SDL_GamepadButton -* SDL_GameControllerType => SDL_GamepadType - -The following structures have been renamed: -* SDL_GameController => SDL_Gamepad - -The following functions have been renamed: -* SDL_GameControllerAddMapping() => SDL_AddGamepadMapping() -* SDL_GameControllerAddMappingsFromFile() => SDL_AddGamepadMappingsFromFile() -* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromRW() -* SDL_GameControllerClose() => SDL_CloseGamepad() -* SDL_GameControllerFromInstanceID() => SDL_GetGamepadFromInstanceID() -* SDL_GameControllerFromPlayerIndex() => SDL_GetGamepadFromPlayerIndex() -* SDL_GameControllerGetAppleSFSymbolsNameForAxis() => SDL_GetGamepadAppleSFSymbolsNameForAxis() -* SDL_GameControllerGetAppleSFSymbolsNameForButton() => SDL_GetGamepadAppleSFSymbolsNameForButton() -* SDL_GameControllerGetAttached() => SDL_GamepadConnected() -* SDL_GameControllerGetAxis() => SDL_GetGamepadAxis() -* SDL_GameControllerGetAxisFromString() => SDL_GetGamepadAxisFromString() -* SDL_GameControllerGetButton() => SDL_GetGamepadButton() -* SDL_GameControllerGetButtonFromString() => SDL_GetGamepadButtonFromString() -* SDL_GameControllerGetFirmwareVersion() => SDL_GetGamepadFirmwareVersion() -* SDL_GameControllerGetJoystick() => SDL_GetGamepadJoystick() -* SDL_GameControllerGetNumTouchpadFingers() => SDL_GetNumGamepadTouchpadFingers() -* SDL_GameControllerGetNumTouchpads() => SDL_GetNumGamepadTouchpads() -* SDL_GameControllerGetPlayerIndex() => SDL_GetGamepadPlayerIndex() -* SDL_GameControllerGetProduct() => SDL_GetGamepadProduct() -* SDL_GameControllerGetProductVersion() => SDL_GetGamepadProductVersion() -* SDL_GameControllerGetSensorData() => SDL_GetGamepadSensorData() -* SDL_GameControllerGetSensorDataRate() => SDL_GetGamepadSensorDataRate() -* SDL_GameControllerGetSerial() => SDL_GetGamepadSerial() -* SDL_GameControllerGetStringForAxis() => SDL_GetGamepadStringForAxis() -* SDL_GameControllerGetStringForButton() => SDL_GetGamepadStringForButton() -* SDL_GameControllerGetTouchpadFinger() => SDL_GetGamepadTouchpadFinger() -* SDL_GameControllerGetType() => SDL_GetGamepadType() -* SDL_GameControllerGetVendor() => SDL_GetGamepadVendor() -* SDL_GameControllerHasAxis() => SDL_GamepadHasAxis() -* SDL_GameControllerHasButton() => SDL_GamepadHasButton() -* SDL_GameControllerHasLED() => SDL_GamepadHasLED() -* SDL_GameControllerHasRumble() => SDL_GamepadHasRumble() -* SDL_GameControllerHasRumbleTriggers() => SDL_GamepadHasRumbleTriggers() -* SDL_GameControllerHasSensor() => SDL_GamepadHasSensor() -* SDL_GameControllerIsSensorEnabled() => SDL_GamepadSensorEnabled() -* SDL_GameControllerMapping() => SDL_GetGamepadMapping() -* SDL_GameControllerMappingForGUID() => SDL_GetGamepadMappingForGUID() -* SDL_GameControllerMappingForIndex() => SDL_GetGamepadMappingForIndex() -* SDL_GameControllerName() => SDL_GetGamepadName() -* SDL_GameControllerNumMappings() => SDL_GetNumGamepadMappings() -* SDL_GameControllerOpen() => SDL_OpenGamepad() -* SDL_GameControllerPath() => SDL_GetGamepadPath() -* SDL_GameControllerRumble() => SDL_RumbleGamepad() -* SDL_GameControllerRumbleTriggers() => SDL_RumbleGamepadTriggers() -* SDL_GameControllerSendEffect() => SDL_SendGamepadEffect() -* SDL_GameControllerSetLED() => SDL_SetGamepadLED() -* SDL_GameControllerSetPlayerIndex() => SDL_SetGamepadPlayerIndex() -* SDL_GameControllerSetSensorEnabled() => SDL_SetGamepadSensorEnabled() -* SDL_GameControllerUpdate() => SDL_UpdateGamepads() -* SDL_IsGameController() => SDL_IsGamepad() - -The following functions have been removed: -* SDL_GameControllerEventState() - replaced with SDL_SetGamepadEventsEnabled() and SDL_GamepadEventsEnabled() -* SDL_GameControllerGetBindForAxis() - replaced with SDL_GetGamepadBindings() -* SDL_GameControllerGetBindForButton() - replaced with SDL_GetGamepadBindings() -* SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadInstanceMapping() -* SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName() -* SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath() -* SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType() - -The following symbols have been renamed: -* SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID -* SDL_CONTROLLER_AXIS_LEFTX => SDL_GAMEPAD_AXIS_LEFTX -* SDL_CONTROLLER_AXIS_LEFTY => SDL_GAMEPAD_AXIS_LEFTY -* SDL_CONTROLLER_AXIS_MAX => SDL_GAMEPAD_AXIS_MAX -* SDL_CONTROLLER_AXIS_RIGHTX => SDL_GAMEPAD_AXIS_RIGHTX -* SDL_CONTROLLER_AXIS_RIGHTY => SDL_GAMEPAD_AXIS_RIGHTY -* SDL_CONTROLLER_AXIS_TRIGGERLEFT => SDL_GAMEPAD_AXIS_LEFT_TRIGGER -* SDL_CONTROLLER_AXIS_TRIGGERRIGHT => SDL_GAMEPAD_AXIS_RIGHT_TRIGGER -* SDL_CONTROLLER_BINDTYPE_AXIS => SDL_GAMEPAD_BINDTYPE_AXIS -* SDL_CONTROLLER_BINDTYPE_BUTTON => SDL_GAMEPAD_BINDTYPE_BUTTON -* SDL_CONTROLLER_BINDTYPE_HAT => SDL_GAMEPAD_BINDTYPE_HAT -* SDL_CONTROLLER_BINDTYPE_NONE => SDL_GAMEPAD_BINDTYPE_NONE -* SDL_CONTROLLER_BUTTON_A => SDL_GAMEPAD_BUTTON_SOUTH -* SDL_CONTROLLER_BUTTON_B => SDL_GAMEPAD_BUTTON_EAST -* SDL_CONTROLLER_BUTTON_BACK => SDL_GAMEPAD_BUTTON_BACK -* SDL_CONTROLLER_BUTTON_DPAD_DOWN => SDL_GAMEPAD_BUTTON_DPAD_DOWN -* SDL_CONTROLLER_BUTTON_DPAD_LEFT => SDL_GAMEPAD_BUTTON_DPAD_LEFT -* SDL_CONTROLLER_BUTTON_DPAD_RIGHT => SDL_GAMEPAD_BUTTON_DPAD_RIGHT -* SDL_CONTROLLER_BUTTON_DPAD_UP => SDL_GAMEPAD_BUTTON_DPAD_UP -* SDL_CONTROLLER_BUTTON_GUIDE => SDL_GAMEPAD_BUTTON_GUIDE -* SDL_CONTROLLER_BUTTON_INVALID => SDL_GAMEPAD_BUTTON_INVALID -* SDL_CONTROLLER_BUTTON_LEFTSHOULDER => SDL_GAMEPAD_BUTTON_LEFT_SHOULDER -* SDL_CONTROLLER_BUTTON_LEFTSTICK => SDL_GAMEPAD_BUTTON_LEFT_STICK -* SDL_CONTROLLER_BUTTON_MAX => SDL_GAMEPAD_BUTTON_MAX -* SDL_CONTROLLER_BUTTON_MISC1 => SDL_GAMEPAD_BUTTON_MISC1 -* SDL_CONTROLLER_BUTTON_PADDLE1 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 -* SDL_CONTROLLER_BUTTON_PADDLE2 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 -* SDL_CONTROLLER_BUTTON_PADDLE3 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 -* SDL_CONTROLLER_BUTTON_PADDLE4 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 -* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER => SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER -* SDL_CONTROLLER_BUTTON_RIGHTSTICK => SDL_GAMEPAD_BUTTON_RIGHT_STICK -* SDL_CONTROLLER_BUTTON_START => SDL_GAMEPAD_BUTTON_START -* SDL_CONTROLLER_BUTTON_TOUCHPAD => SDL_GAMEPAD_BUTTON_TOUCHPAD -* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_WEST -* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_NORTH -* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT -* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR -* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT -* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO -* SDL_CONTROLLER_TYPE_PS3 => SDL_GAMEPAD_TYPE_PS3 -* SDL_CONTROLLER_TYPE_PS4 => SDL_GAMEPAD_TYPE_PS4 -* SDL_CONTROLLER_TYPE_PS5 => SDL_GAMEPAD_TYPE_PS5 -* SDL_CONTROLLER_TYPE_UNKNOWN => SDL_GAMEPAD_TYPE_STANDARD -* SDL_CONTROLLER_TYPE_VIRTUAL => SDL_GAMEPAD_TYPE_VIRTUAL -* SDL_CONTROLLER_TYPE_XBOX360 => SDL_GAMEPAD_TYPE_XBOX360 -* SDL_CONTROLLER_TYPE_XBOXONE => SDL_GAMEPAD_TYPE_XBOXONE - -## SDL_gesture.h - -The gesture API has been removed. There is no replacement planned in SDL3. -However, the SDL2 code has been moved to a single-header library that can -be dropped into an SDL3 or SDL2 program, to continue to provide this -functionality to your app and aid migration. That is located in the -[SDL_gesture GitHub repository](https://github.com/libsdl-org/SDL_gesture). - -## SDL_hints.h - -SDL_AddHintCallback() now returns a standard int result instead of void, returning 0 if the function succeeds or a negative error code if there was an error. - -Calling SDL_GetHint() with the name of the hint being changed from within a hint callback will now return the new value rather than the old value. The old value is still passed as a parameter to the hint callback. - -The following hints have been removed: -* SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional -* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver instead -* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text -* SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer -* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() -* SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API. -* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() -* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() -* SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled -* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() -* SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead -* SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend -* SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend - -* Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER -* Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER -* The environment variables SDL_VIDEO_X11_WMCLASS and SDL_VIDEO_WAYLAND_WMCLASS have been removed and replaced with the unified hint SDL_HINT_APP_ID - -## SDL_init.h - -The following symbols have been renamed: -* SDL_INIT_GAMECONTROLLER => SDL_INIT_GAMEPAD - -The following symbols have been removed: -* SDL_INIT_NOPARACHUTE - -## SDL_joystick.h - -SDL_JoystickID has changed from Sint32 to Uint32, with an invalid ID being 0. - -Rather than iterating over joysticks using device index, there is a new function SDL_GetJoysticks() to get the current list of joysticks, and new functions to get information about joysticks from their instance ID: -```c -{ - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == 0) { - int i, num_joysticks; - SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks); - if (joysticks) { - for (i = 0; i < num_joysticks; ++i) { - SDL_JoystickID instance_id = joysticks[i]; - const char *name = SDL_GetJoystickInstanceName(instance_id); - const char *path = SDL_GetJoystickInstancePath(instance_id); - - SDL_Log("Joystick %" SDL_PRIu32 ": %s%s%s VID 0x%.4x, PID 0x%.4x\n", - instance_id, name ? name : "Unknown", path ? ", " : "", path ? path : "", SDL_GetJoystickInstanceVendor(instance_id), SDL_GetJoystickInstanceProduct(instance_id)); - } - SDL_free(joysticks); - } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } -} -``` - -The SDL_EVENT_JOYSTICK_ADDED event now provides the joystick instance ID in the `which` member of the jdevice event structure. - -The functions SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() have been added to directly query the list of available joysticks. - -SDL_AttachVirtualJoystick() and SDL_AttachVirtualJoystickEx() now return the joystick instance ID instead of a device index, and return 0 if there was an error. - -The following functions have been renamed: -* SDL_JoystickAttachVirtual() => SDL_AttachVirtualJoystick() -* SDL_JoystickAttachVirtualEx() => SDL_AttachVirtualJoystickEx() -* SDL_JoystickClose() => SDL_CloseJoystick() -* SDL_JoystickCurrentPowerLevel() => SDL_GetJoystickPowerLevel() -* SDL_JoystickDetachVirtual() => SDL_DetachVirtualJoystick() -* SDL_JoystickFromInstanceID() => SDL_GetJoystickFromInstanceID() -* SDL_JoystickFromPlayerIndex() => SDL_GetJoystickFromPlayerIndex() -* SDL_JoystickGetAttached() => SDL_JoystickConnected() -* SDL_JoystickGetAxis() => SDL_GetJoystickAxis() -* SDL_JoystickGetAxisInitialState() => SDL_GetJoystickAxisInitialState() -* SDL_JoystickGetButton() => SDL_GetJoystickButton() -* SDL_JoystickGetFirmwareVersion() => SDL_GetJoystickFirmwareVersion() -* SDL_JoystickGetGUID() => SDL_GetJoystickGUID() -* SDL_JoystickGetGUIDFromString() => SDL_GetJoystickGUIDFromString() -* SDL_JoystickGetGUIDString() => SDL_GetJoystickGUIDString() -* SDL_JoystickGetHat() => SDL_GetJoystickHat() -* SDL_JoystickGetPlayerIndex() => SDL_GetJoystickPlayerIndex() -* SDL_JoystickGetProduct() => SDL_GetJoystickProduct() -* SDL_JoystickGetProductVersion() => SDL_GetJoystickProductVersion() -* SDL_JoystickGetSerial() => SDL_GetJoystickSerial() -* SDL_JoystickGetType() => SDL_GetJoystickType() -* SDL_JoystickGetVendor() => SDL_GetJoystickVendor() -* SDL_JoystickInstanceID() => SDL_GetJoystickInstanceID() -* SDL_JoystickIsVirtual() => SDL_IsJoystickVirtual() -* SDL_JoystickName() => SDL_GetJoystickName() -* SDL_JoystickNumAxes() => SDL_GetNumJoystickAxes() -* SDL_JoystickNumButtons() => SDL_GetNumJoystickButtons() -* SDL_JoystickNumHats() => SDL_GetNumJoystickHats() -* SDL_JoystickOpen() => SDL_OpenJoystick() -* SDL_JoystickPath() => SDL_GetJoystickPath() -* SDL_JoystickRumble() => SDL_RumbleJoystick() -* SDL_JoystickRumbleTriggers() => SDL_RumbleJoystickTriggers() -* SDL_JoystickSendEffect() => SDL_SendJoystickEffect() -* SDL_JoystickSetLED() => SDL_SetJoystickLED() -* SDL_JoystickSetPlayerIndex() => SDL_SetJoystickPlayerIndex() -* SDL_JoystickSetVirtualAxis() => SDL_SetJoystickVirtualAxis() -* SDL_JoystickSetVirtualButton() => SDL_SetJoystickVirtualButton() -* SDL_JoystickSetVirtualHat() => SDL_SetJoystickVirtualHat() -* SDL_JoystickUpdate() => SDL_UpdateJoysticks() - -The following symbols have been renamed: -* SDL_JOYSTICK_TYPE_GAMECONTROLLER => SDL_JOYSTICK_TYPE_GAMEPAD - -The following functions have been removed: -* SDL_JoystickEventState() - replaced with SDL_SetJoystickEventsEnabled() and SDL_JoystickEventsEnabled() -* SDL_JoystickGetDeviceGUID() - replaced with SDL_GetJoystickInstanceGUID() -* SDL_JoystickGetDeviceInstanceID() -* SDL_JoystickGetDevicePlayerIndex() - replaced with SDL_GetJoystickInstancePlayerIndex() -* SDL_JoystickGetDeviceProduct() - replaced with SDL_GetJoystickInstanceProduct() -* SDL_JoystickGetDeviceProductVersion() - replaced with SDL_GetJoystickInstanceProductVersion() -* SDL_JoystickGetDeviceType() - replaced with SDL_GetJoystickInstanceType() -* SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickInstanceVendor() -* SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickInstanceName() -* SDL_JoystickNumBalls() - API has been removed, see https://github.com/libsdl-org/SDL/issues/6766 -* SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickInstancePath() -* SDL_NumJoysticks() - replaced with SDL_GetJoysticks() - -The following symbols have been removed: -* SDL_JOYBALLMOTION - -## SDL_keyboard.h - -The following functions have been renamed: -* SDL_IsScreenKeyboardShown() => SDL_ScreenKeyboardShown() -* SDL_IsTextInputActive() => SDL_TextInputActive() -* SDL_IsTextInputShown() => SDL_TextInputShown() - -## SDL_keycode.h - -The following symbols have been renamed: -* KMOD_ALT => SDL_KMOD_ALT -* KMOD_CAPS => SDL_KMOD_CAPS -* KMOD_CTRL => SDL_KMOD_CTRL -* KMOD_GUI => SDL_KMOD_GUI -* KMOD_LALT => SDL_KMOD_LALT -* KMOD_LCTRL => SDL_KMOD_LCTRL -* KMOD_LGUI => SDL_KMOD_LGUI -* KMOD_LSHIFT => SDL_KMOD_LSHIFT -* KMOD_MODE => SDL_KMOD_MODE -* KMOD_NONE => SDL_KMOD_NONE -* KMOD_NUM => SDL_KMOD_NUM -* KMOD_RALT => SDL_KMOD_RALT -* KMOD_RCTRL => SDL_KMOD_RCTRL -* KMOD_RESERVED => SDL_KMOD_RESERVED -* KMOD_RGUI => SDL_KMOD_RGUI -* KMOD_RSHIFT => SDL_KMOD_RSHIFT -* KMOD_SCROLL => SDL_KMOD_SCROLL -* KMOD_SHIFT => SDL_KMOD_SHIFT - -## SDL_loadso.h - -SDL_LoadFunction() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior. - -## SDL_main.h - -SDL3 doesn't have a static libSDLmain to link against anymore. -Instead SDL_main.h is now a header-only library **and not included by SDL.h anymore**. - -Using it is really simple: Just `#include ` in the source file with your standard -`int main(int argc, char* argv[])` function. - -## SDL_metal.h - -SDL_Metal_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. - -## SDL_mouse.h - -SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() - -SDL_GetMouseState(), SDL_GetGlobalMouseState(), SDL_GetRelativeMouseState(), SDL_WarpMouseInWindow(), and SDL_WarpMouseGlobal() all use floating point mouse positions, to provide sub-pixel precision on platforms that support it. - -The following functions have been renamed: -* SDL_FreeCursor() => SDL_DestroyCursor() - -## SDL_mutex.h - -SDL_MUTEX_MAXWAIT has been removed; it suggested there was a maximum timeout one could outlive, instead of an infinite wait. Instead, pass a -1 to functions that accepted this symbol. - -SDL_LockMutex and SDL_UnlockMutex now return void; if the mutex is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the mutex is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior. - -The following functions have been renamed: -* SDL_CondBroadcast() => SDL_BroadcastCondition() -* SDL_CondSignal() => SDL_SignalCondition() -* SDL_CondWait() => SDL_WaitCondition() -* SDL_CondWaitTimeout() => SDL_WaitConditionTimeout() -* SDL_CreateCond() => SDL_CreateCondition() -* SDL_DestroyCond() => SDL_DestroyCondition() -* SDL_SemPost() => SDL_PostSemaphore() -* SDL_SemTryWait() => SDL_TryWaitSemaphore() -* SDL_SemValue() => SDL_GetSemaphoreValue() -* SDL_SemWait() => SDL_WaitSemaphore() -* SDL_SemWaitTimeout() => SDL_WaitSemaphoreTimeout() - -The following symbols have been renamed: -* SDL_cond => SDL_Condition -* SDL_mutex => SDL_Mutex -* SDL_sem => SDL_Semaphore - -## SDL_pixels.h - -SDL_CalculateGammaRamp has been removed, because SDL_SetWindowGammaRamp has been removed as well due to poor support in modern operating systems (see [SDL_video.h](#sdl_videoh)). - -The following functions have been renamed: -* SDL_AllocFormat() => SDL_CreatePixelFormat() -* SDL_AllocPalette() => SDL_CreatePalette() -* SDL_FreeFormat() => SDL_DestroyPixelFormat() -* SDL_FreePalette() => SDL_DestroyPalette() -* SDL_MasksToPixelFormatEnum() => SDL_GetPixelFormatEnumForMasks() -* SDL_PixelFormatEnumToMasks() => SDL_GetMasksForPixelFormatEnum() - -The following symbols have been renamed: -* SDL_DISPLAYEVENT_DISCONNECTED => SDL_EVENT_DISPLAY_REMOVED -* SDL_DISPLAYEVENT_MOVED => SDL_EVENT_DISPLAY_MOVED -* SDL_DISPLAYEVENT_ORIENTATION => SDL_EVENT_DISPLAY_ORIENTATION -* SDL_WINDOWEVENT_CLOSE => SDL_EVENT_WINDOW_CLOSE_REQUESTED -* SDL_WINDOWEVENT_DISPLAY_CHANGED => SDL_EVENT_WINDOW_DISPLAY_CHANGED -* SDL_WINDOWEVENT_ENTER => SDL_EVENT_WINDOW_ENTER -* SDL_WINDOWEVENT_EXPOSED => SDL_EVENT_WINDOW_EXPOSED -* SDL_WINDOWEVENT_FOCUS_GAINED => SDL_EVENT_WINDOW_FOCUS_GAINED -* SDL_WINDOWEVENT_FOCUS_LOST => SDL_EVENT_WINDOW_FOCUS_LOST -* SDL_WINDOWEVENT_HIDDEN => SDL_EVENT_WINDOW_HIDDEN -* SDL_WINDOWEVENT_HIT_TEST => SDL_EVENT_WINDOW_HIT_TEST -* SDL_WINDOWEVENT_ICCPROF_CHANGED => SDL_EVENT_WINDOW_ICCPROF_CHANGED -* SDL_WINDOWEVENT_LEAVE => SDL_EVENT_WINDOW_LEAVE -* SDL_WINDOWEVENT_MAXIMIZED => SDL_EVENT_WINDOW_MAXIMIZED -* SDL_WINDOWEVENT_MINIMIZED => SDL_EVENT_WINDOW_MINIMIZED -* SDL_WINDOWEVENT_MOVED => SDL_EVENT_WINDOW_MOVED -* SDL_WINDOWEVENT_RESIZED => SDL_EVENT_WINDOW_RESIZED -* SDL_WINDOWEVENT_RESTORED => SDL_EVENT_WINDOW_RESTORED -* SDL_WINDOWEVENT_SHOWN => SDL_EVENT_WINDOW_SHOWN -* SDL_WINDOWEVENT_SIZE_CHANGED => SDL_EVENT_WINDOW_SIZE_CHANGED -* SDL_WINDOWEVENT_TAKE_FOCUS => SDL_EVENT_WINDOW_TAKE_FOCUS - - -## SDL_platform.h - -The preprocessor symbol `__MACOSX__` has been renamed `__MACOS__`, and `__IPHONEOS__` has been renamed `__IOS__` - -## SDL_rect.h - -The following functions have been renamed: -* SDL_EncloseFPoints() => SDL_GetRectEnclosingPointsFloat() -* SDL_EnclosePoints() => SDL_GetRectEnclosingPoints() -* SDL_FRectEmpty() => SDL_RectEmptyFloat() -* SDL_FRectEquals() => SDL_RectsEqualFloat() -* SDL_FRectEqualsEpsilon() => SDL_RectsEqualEpsilon() -* SDL_HasIntersection() => SDL_HasRectIntersection() -* SDL_HasIntersectionF() => SDL_HasRectIntersectionFloat() -* SDL_IntersectFRect() => SDL_GetRectIntersectionFloat() -* SDL_IntersectFRectAndLine() => SDL_GetRectAndLineIntersectionFloat() -* SDL_IntersectRect() => SDL_GetRectIntersection() -* SDL_IntersectRectAndLine() => SDL_GetRectAndLineIntersection() -* SDL_PointInFRect() => SDL_PointInRectFloat() -* SDL_RectEquals() => SDL_RectsEqual() -* SDL_UnionFRect() => SDL_GetRectUnionFloat() -* SDL_UnionRect() => SDL_GetRectUnion() - -## SDL_render.h - -The 2D renderer API always uses batching in SDL3. There is no magic to turn -it on and off; it doesn't matter if you select a specific renderer or try to -use any hint. This means that all apps that use SDL3's 2D renderer and also -want to call directly into the platform's lower-layer graphics API _must_ call -SDL_RenderFlush() before doing so. This will make sure any pending rendering -work from SDL is done before the app starts directly drawing. - -SDL_GetRenderDriverInfo() has been removed, since most of the information it reported were -estimates and could not be accurate before creating a renderer. Often times this function -was used to figure out the index of a driver, so one would call it in a for-loop, looking -for the driver named "opengl" or whatnot. SDL_GetRenderDriver() has been added for this -functionality, which returns only the name of the driver. - -Additionally, SDL_CreateRenderer()'s second argument is no longer an integer index, but a -`const char *` representing a renderer's name; if you were just using a for-loop to find -which index is the "opengl" or whatnot driver, you can just pass that string directly -here, now. Passing NULL is the same as passing -1 here in SDL2, to signify you want SDL -to decide for you. - -The SDL_RENDERER_TARGETTEXTURE flag has been removed, all current renderers support target texture functionality. - -When a renderer is created, it will automatically set the logical size to the size of -the window in points. For high DPI displays, this will set up scaling from points to -pixels. You can disable this scaling with: -```c - SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST); -``` - -Mouse and touch events are no longer filtered to change their coordinates, instead you -can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into -the rendering viewport. - -SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions. - -The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active. - -The following functions have been renamed: -* SDL_GetRendererOutputSize() => SDL_GetCurrentRenderOutputSize() -* SDL_RenderCopy() => SDL_RenderTexture() -* SDL_RenderCopyEx() => SDL_RenderTextureRotated() -* SDL_RenderCopyExF() => SDL_RenderTextureRotated() -* SDL_RenderCopyF() => SDL_RenderTexture() -* SDL_RenderDrawLine() => SDL_RenderLine() -* SDL_RenderDrawLineF() => SDL_RenderLine() -* SDL_RenderDrawLines() => SDL_RenderLines() -* SDL_RenderDrawLinesF() => SDL_RenderLines() -* SDL_RenderDrawPoint() => SDL_RenderPoint() -* SDL_RenderDrawPointF() => SDL_RenderPoint() -* SDL_RenderDrawPoints() => SDL_RenderPoints() -* SDL_RenderDrawPointsF() => SDL_RenderPoints() -* SDL_RenderDrawRect() => SDL_RenderRect() -* SDL_RenderDrawRectF() => SDL_RenderRect() -* SDL_RenderDrawRects() => SDL_RenderRects() -* SDL_RenderDrawRectsF() => SDL_RenderRects() -* SDL_RenderFillRectF() => SDL_RenderFillRect() -* SDL_RenderFillRectsF() => SDL_RenderFillRects() -* SDL_RenderGetClipRect() => SDL_GetRenderClipRect() -* SDL_RenderGetIntegerScale() => SDL_GetRenderIntegerScale() -* SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalPresentation() -* SDL_RenderGetMetalCommandEncoder() => SDL_GetRenderMetalCommandEncoder() -* SDL_RenderGetMetalLayer() => SDL_GetRenderMetalLayer() -* SDL_RenderGetScale() => SDL_GetRenderScale() -* SDL_RenderGetViewport() => SDL_GetRenderViewport() -* SDL_RenderGetWindow() => SDL_GetRenderWindow() -* SDL_RenderIsClipEnabled() => SDL_RenderClipEnabled() -* SDL_RenderLogicalToWindow() => SDL_RenderCoordinatesToWindow() -* SDL_RenderSetClipRect() => SDL_SetRenderClipRect() -* SDL_RenderSetIntegerScale() => SDL_SetRenderIntegerScale() -* SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalPresentation() -* SDL_RenderSetScale() => SDL_SetRenderScale() -* SDL_RenderSetVSync() => SDL_SetRenderVSync() -* SDL_RenderSetViewport() => SDL_SetRenderViewport() -* SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow() - -The following functions have been removed: -* SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead -* SDL_RenderGetIntegerScale() -* SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE -* SDL_RenderTargetSupported() - render targets are always supported -* SDL_SetTextureUserData() - use SDL_GetTextureProperties() instead - -The following symbols have been renamed: -* SDL_ScaleModeBest => SDL_SCALEMODE_BEST -* SDL_ScaleModeLinear => SDL_SCALEMODE_LINEAR -* SDL_ScaleModeNearest => SDL_SCALEMODE_NEAREST - -## SDL_rwops.h - -The following symbols have been renamed: -* RW_SEEK_CUR => SDL_RW_SEEK_CUR -* RW_SEEK_END => SDL_RW_SEEK_END -* RW_SEEK_SET => SDL_RW_SEEK_SET - -SDL_RWread and SDL_RWwrite (and SDL_RWops::read, SDL_RWops::write) have a different function signature in SDL3. - -Previously they looked more like stdio: - -```c -size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum); -size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxnum); -``` - -But now they look more like POSIX: - -```c -size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size); -size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size); -``` - -Code that used to look like this: -``` -size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) -{ - return SDL_RWread(stream, ptr, size, nitems); -} -``` -should be changed to: -``` -size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) -{ - if (size > 0 && nitems > 0) { - return SDL_RWread(stream, ptr, size * nitems) / size; - } - return 0; -} -``` - -SDL_RWFromFP has been removed from the API, due to issues when the SDL library uses a different C runtime from the application. - -You can implement this in your own code easily: -```c -#include - - -static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence) -{ - int stdiowhence; - - switch (whence) { - case SDL_RW_SEEK_SET: - stdiowhence = SEEK_SET; - break; - case SDL_RW_SEEK_CUR: - stdiowhence = SEEK_CUR; - break; - case SDL_RW_SEEK_END: - stdiowhence = SEEK_END; - break; - default: - return SDL_SetError("Unknown value for 'whence'"); - } - - if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) { - Sint64 pos = ftell((FILE *)context->hidden.stdio.fp); - if (pos < 0) { - return SDL_SetError("Couldn't get stream offset"); - } - return pos; - } - return SDL_Error(SDL_EFSEEK); -} - -static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size) -{ - size_t bytes; - - bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { - SDL_Error(SDL_EFREAD); - } - return bytes; -} - -static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size) -{ - size_t bytes; - - bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { - SDL_Error(SDL_EFWRITE); - } - return bytes; -} - -static int SDLCALL stdio_close(SDL_RWops *context) -{ - int status = 0; - if (context->hidden.stdio.autoclose) { - if (fclose((FILE *)context->hidden.stdio.fp) != 0) { - status = SDL_Error(SDL_EFWRITE); - } - } - SDL_DestroyRW(context); - return status; -} - -SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose) -{ - SDL_RWops *rwops = NULL; - - rwops = SDL_CreateRW(); - if (rwops != NULL) { - rwops->seek = stdio_seek; - rwops->read = stdio_read; - rwops->write = stdio_write; - rwops->close = stdio_close; - rwops->hidden.stdio.fp = fp; - rwops->hidden.stdio.autoclose = autoclose; - rwops->type = SDL_RWOPS_STDFILE; - } - return rwops; -} -``` - -The functions SDL_ReadU8(), SDL_ReadU16LE(), SDL_ReadU16BE(), SDL_ReadU32LE(), SDL_ReadU32BE(), SDL_ReadU64LE(), and SDL_ReadU64BE() now return SDL_TRUE if the read succeeded and SDL_FALSE if it didn't, and store the data in a pointer passed in as a parameter. - -The following functions have been renamed: -* SDL_AllocRW() => SDL_CreateRW() -* SDL_FreeRW() => SDL_DestroyRW() -* SDL_ReadBE16() => SDL_ReadU16BE() -* SDL_ReadBE32() => SDL_ReadU32BE() -* SDL_ReadBE64() => SDL_ReadU64BE() -* SDL_ReadLE16() => SDL_ReadU16LE() -* SDL_ReadLE32() => SDL_ReadU32LE() -* SDL_ReadLE64() => SDL_ReadU64LE() -* SDL_WriteBE16() => SDL_WriteU16BE() -* SDL_WriteBE32() => SDL_WriteU32BE() -* SDL_WriteBE64() => SDL_WriteU64BE() -* SDL_WriteLE16() => SDL_WriteU16LE() -* SDL_WriteLE32() => SDL_WriteU32LE() -* SDL_WriteLE64() => SDL_WriteU64LE() - -## SDL_sensor.h - -SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0. - -Rather than iterating over sensors using device index, there is a new function SDL_GetSensors() to get the current list of sensors, and new functions to get information about sensors from their instance ID: -```c -{ - if (SDL_InitSubSystem(SDL_INIT_SENSOR) == 0) { - int i, num_sensors; - SDL_SensorID *sensors = SDL_GetSensors(&num_sensors); - if (sensors) { - for (i = 0; i < num_sensors; ++i) { - SDL_Log("Sensor %" SDL_PRIu32 ": %s, type %d, platform type %d\n", - sensors[i], - SDL_GetSensorInstanceName(sensors[i]), - SDL_GetSensorInstanceType(sensors[i]), - SDL_GetSensorInstanceNonPortableType(sensors[i])); - } - SDL_free(sensors); - } - SDL_QuitSubSystem(SDL_INIT_SENSOR); - } -} -``` - -Removed SDL_SensorGetDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_SENSOR_UPDATE events. - - -The following functions have been renamed: -* SDL_SensorClose() => SDL_CloseSensor() -* SDL_SensorFromInstanceID() => SDL_GetSensorFromInstanceID() -* SDL_SensorGetData() => SDL_GetSensorData() -* SDL_SensorGetInstanceID() => SDL_GetSensorInstanceID() -* SDL_SensorGetName() => SDL_GetSensorName() -* SDL_SensorGetNonPortableType() => SDL_GetSensorNonPortableType() -* SDL_SensorGetType() => SDL_GetSensorType() -* SDL_SensorOpen() => SDL_OpenSensor() -* SDL_SensorUpdate() => SDL_UpdateSensors() - -The following functions have been removed: -* SDL_LockSensors() -* SDL_NumSensors() - replaced with SDL_GetSensors() -* SDL_SensorGetDeviceInstanceID() -* SDL_SensorGetDeviceName() - replaced with SDL_GetSensorInstanceName() -* SDL_SensorGetDeviceNonPortableType() - replaced with SDL_GetSensorInstanceNonPortableType() -* SDL_SensorGetDeviceType() - replaced with SDL_GetSensorInstanceType() -* SDL_UnlockSensors() - -## SDL_shape.h - -This header has been removed. You can create a window with the SDL_WINDOW_TRANSPARENT flag and then render using the alpha channel to achieve a similar effect. You can see an example of this in test/testshape.c - -## SDL_stdinc.h - -The standard C headers like stdio.h and stdlib.h are no longer included, you should include them directly in your project if you use non-SDL C runtime functions. -M_PI is no longer defined in SDL_stdinc.h, you can use the new symbols SDL_PI_D (double) and SDL_PI_F (float) instead. - - -The following functions have been renamed: -* SDL_strtokr() => SDL_strtok_r() - -## SDL_surface.h - -The userdata member of SDL_Surface has been replaced with a more general properties interface, which can be queried with SDL_GetSurfaceProperties() - -Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat. - -SDL_CreateRGBSurface() and SDL_CreateRGBSurfaceWithFormat() have been combined into a new function SDL_CreateSurface(). -SDL_CreateRGBSurfaceFrom() and SDL_CreateRGBSurfaceWithFormatFrom() have been combined into a new function SDL_CreateSurfaceFrom(). - -You can implement the old functions in your own code easily: -```c -SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) -{ - return SDL_CreateSurface(width, height, - SDL_GetPixelFormatEnumForMasks(depth, Rmask, Gmask, Bmask, Amask)); -} - -SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format) -{ - return SDL_CreateSurface(width, height, format); -} - -SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) -{ - return SDL_CreateSurfaceFrom(pixels, width, height, pitch, - SDL_GetPixelFormatEnumForMasks(depth, Rmask, Gmask, Bmask, Amask)); -} - -SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format) -{ - return SDL_CreateSurfaceFrom(pixels, width, height, pitch, format); -} - -``` - -But if you're migrating your code which uses masks, you probably have a format in mind, possibly one of these: -```c -// Various mask (R, G, B, A) and their corresponding format: -0xFF000000 0x00FF0000 0x0000FF00 0x000000FF => SDL_PIXELFORMAT_RGBA8888 -0x00FF0000 0x0000FF00 0x000000FF 0xFF000000 => SDL_PIXELFORMAT_ARGB8888 -0x0000FF00 0x00FF0000 0xFF000000 0x000000FF => SDL_PIXELFORMAT_BGRA8888 -0x000000FF 0x0000FF00 0x00FF0000 0xFF000000 => SDL_PIXELFORMAT_ABGR8888 -0x0000F800 0x000007E0 0x0000001F 0x00000000 => SDL_PIXELFORMAT_RGB565 -``` - - -The following functions have been renamed: -* SDL_FillRect() => SDL_FillSurfaceRect() -* SDL_FillRects() => SDL_FillSurfaceRects() -* SDL_FreeSurface() => SDL_DestroySurface() -* SDL_GetClipRect() => SDL_GetSurfaceClipRect() -* SDL_GetColorKey() => SDL_GetSurfaceColorKey() -* SDL_HasColorKey() => SDL_SurfaceHasColorKey() -* SDL_HasSurfaceRLE() => SDL_SurfaceHasRLE() -* SDL_LowerBlit() => SDL_BlitSurfaceUnchecked() -* SDL_LowerBlitScaled() => SDL_BlitSurfaceUncheckedScaled() -* SDL_SetClipRect() => SDL_SetSurfaceClipRect() -* SDL_SetColorKey() => SDL_SetSurfaceColorKey() -* SDL_UpperBlit() => SDL_BlitSurface() -* SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled() - -## SDL_system.h - -SDL_WindowsMessageHook has changed signatures so the message may be modified and it can block further message processing. - -SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. - -The following functions have been removed: -* SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property -* SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property -* SDL_RenderGetD3D9Device() - replaced with the "SDL.renderer.d3d9.device" property - -## SDL_syswm.h - -This header has been removed. - -The Windows and X11 events are now available via callbacks which you can set with SDL_SetWindowsMessageHook() and SDL_SetX11EventHook(). - -The information previously available in SDL_GetWindowWMInfo() is now available as window properties, e.g. -```c - HWND hwnd = NULL; - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { - hwnd = info.info.win.window; - } - if (hwnd) { - ... - } -``` -becomes: -```c - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); - if (hwnd) { - ... - } -``` - -## SDL_thread.h - -The following functions have been renamed: -* SDL_TLSCleanup() => SDL_CleanupTLS() -* SDL_TLSCreate() => SDL_CreateTLS() -* SDL_TLSGet() => SDL_GetTLS() -* SDL_TLSSet() => SDL_SetTLS() - -## SDL_timer.h - -SDL_GetTicks() now returns a 64-bit value. Instead of using the SDL_TICKS_PASSED macro, you can directly compare tick values, e.g. -```c -Uint32 deadline = SDL_GetTicks() + 1000; -... -if (SDL_TICKS_PASSED(SDL_GetTicks(), deadline)) { - ... -} -``` -becomes: -```c -Uint64 deadline = SDL_GetTicks() + 1000 -... -if (SDL_GetTicks() >= deadline) { - ... -} -``` - -If you were using this macro for other things besides SDL ticks values, you can define it in your own code as: -```c -#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) -``` - -## SDL_touch.h - -SDL_GetNumTouchFingers() returns a negative error code if there was an error. - -## SDL_version.h - -SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0. - - -## SDL_video.h - -SDL_VideoInit() and SDL_VideoQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_VIDEO, which will properly refcount the subsystems. You can choose a specific video driver using SDL_VIDEO_DRIVER hint. - -Rather than iterating over displays using display index, there is a new function SDL_GetDisplays() to get the current list of displays, and functions which used to take a display index now take SDL_DisplayID, with an invalid ID being 0. -```c -{ - if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0) { - int i, num_displays = 0; - SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); - if (displays) { - for (i = 0; i < num_displays; ++i) { - SDL_DisplayID instance_id = displays[i]; - const char *name = SDL_GetDisplayName(instance_id); - - SDL_Log("Display %" SDL_PRIu32 ": %s\n", instance_id, name ? name : "Unknown"); - } - SDL_free(displays); - } - SDL_QuitSubSystem(SDL_INIT_VIDEO); - } -} -``` - -SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it. - -The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. - -The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag. - -The SDL_WINDOW_SKIP_TASKBAR flag has been replaced by the SDL_WINDOW_UTILITY flag, which has the same functionality. - -SDL_DisplayMode now includes the pixel density which can be greater than 1.0 for display modes that have a higher pixel size than the mode size. You should use SDL_GetWindowSizeInPixels() to get the actual pixel size of the window back buffer. - -The refresh rate in SDL_DisplayMode is now a float. - -Rather than iterating over display modes using an index, there is a new function SDL_GetFullscreenDisplayModes() to get the list of available fullscreen modes on a display. -```c -{ - SDL_DisplayID display = SDL_GetPrimaryDisplay(); - int num_modes = 0; - SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &num_modes); - if (modes) { - for (i = 0; i < num_modes; ++i) { - SDL_DisplayMode *mode = modes[i]; - SDL_Log("Display %" SDL_PRIu32 " mode %d: %dx%d@%gx %gHz\n", - display, i, mode->w, mode->h, mode->pixel_density, mode->refresh_rate); - } - SDL_free(modes); - } -} -``` - -SDL_GetDesktopDisplayMode() and SDL_GetCurrentDisplayMode() return pointers to display modes rather than filling in application memory. - -Windows now have an explicit fullscreen mode that is set, using SDL_SetWindowFullscreenMode(). The fullscreen mode for a window can be queried with SDL_GetWindowFullscreenMode(), which returns a pointer to the mode, or NULL if the window will be fullscreen desktop. SDL_SetWindowFullscreen() just takes a boolean value, setting the correct fullscreen state based on the selected mode. - -SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, and you can call SDL_GetWindowFullscreenMode() to see whether an exclusive fullscreen mode will be used or the fullscreen desktop mode will be used when the window is fullscreen. - -SDL_SetWindowBrightness and SDL_SetWindowGammaRamp have been removed from the API, because they interact poorly with modern operating systems and aren't able to limit their effects to the SDL window. - -Programs which have access to shaders can implement more robust versions of those functions using custom shader code rendered as a post-process effect. - -Removed SDL_GL_CONTEXT_EGL from OpenGL configuration attributes. You can instead use `SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);` - -SDL_GL_GetProcAddress() and SDL_EGL_GetProcAddress() now return `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior. - -SDL_GL_SwapWindow() returns 0 if the function succeeds or a negative error code if there was an error. - -SDL_GL_GetSwapInterval() takes the interval as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. - -SDL_GL_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. - -The SDL_WINDOW_TOOLTIP and SDL_WINDOW_POPUP_MENU window flags are now supported on Windows, Mac (Cocoa), X11, and Wayland. Creating windows with these flags must happen via the `SDL_CreatePopupWindow()` function. This function requires passing in the handle to a valid parent window for the popup, and the popup window is positioned relative to the parent. - -The following functions have been renamed: -* SDL_GetClosestDisplayMode() => SDL_GetClosestFullscreenDisplayMode() -* SDL_GetDisplayOrientation() => SDL_GetCurrentDisplayOrientation() -* SDL_GetPointDisplayIndex() => SDL_GetDisplayForPoint() -* SDL_GetRectDisplayIndex() => SDL_GetDisplayForRect() -* SDL_GetWindowDisplayIndex() => SDL_GetDisplayForWindow() -* SDL_GetWindowDisplayMode() => SDL_GetWindowFullscreenMode() -* SDL_IsScreenSaverEnabled() => SDL_ScreenSaverEnabled() -* SDL_SetWindowDisplayMode() => SDL_SetWindowFullscreenMode() - -The following functions have been removed: -* SDL_GetClosestFullscreenDisplayMode() -* SDL_GetDisplayDPI() - not reliable across platforms, approximately replaced by multiplying `display_scale` in the structure returned by SDL_GetDesktopDisplayMode() times 160 on iPhone and Android, and 96 on other platforms. -* SDL_GetDisplayMode() -* SDL_GetNumDisplayModes() - replaced with SDL_GetFullscreenDisplayModes() -* SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() -* SDL_GetWindowData() - use SDL_GetWindowProperties() instead -* SDL_SetWindowData() - use SDL_GetWindowProperties() instead -* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window - -SDL_Window id type is named SDL_WindowID - -The following symbols have been renamed: -* SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY -* SDL_WINDOW_INPUT_GRABBED => SDL_WINDOW_MOUSE_GRABBED - -## SDL_vulkan.h - -SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no longer makes the app allocate query/allocate space for the result, instead returning a static const internal string. - -SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr. - -SDL_Vulkan_CreateSurface() now takes a VkAllocationCallbacks pointer as its third parameter. If you don't have an allocator to supply, pass a NULL here to use the system default allocator (SDL2 always used the system default allocator here). - -SDL_Vulkan_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. +# Migrating to SDL 3.0 + +This guide provides useful information for migrating applications from SDL 2.0 to SDL 3.0. + +Details on API changes are organized by SDL 2.0 header below. + +The file with your main() function should include , as that is no longer included in SDL.h. + +Many functions and symbols have been renamed. We have provided a handy Python script [rename_symbols.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_symbols.py) to rename SDL2 functions to their SDL3 counterparts: +```sh +rename_symbols.py --all-symbols source_code_path +``` + +It's also possible to apply a semantic patch to migrate more easily to SDL3: [SDL_migration.cocci](https://github.com/libsdl-org/SDL/blob/main/build-scripts/SDL_migration.cocci) + +SDL headers should now be included as `#include `. Typically that's the only header you'll need in your application unless you are using OpenGL or Vulkan functionality. We have provided a handy Python script [rename_headers.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_headers.py) to rename SDL2 headers to their SDL3 counterparts: +```sh +rename_headers.py source_code_path +``` + +CMake users should use this snippet to include SDL support in their project: +``` +find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) +target_link_libraries(mygame PRIVATE SDL3::SDL3) +``` + +Autotools users should use this snippet to include SDL support in their project: +``` +PKG_CHECK_MODULES([SDL3], [sdl3]) +``` +and then add $SDL3_CFLAGS to their project CFLAGS and $SDL3_LIBS to their project LDFLAGS + +Makefile users can use this snippet to include SDL support in their project: +``` +CFLAGS += $(shell pkg-config sdl3 --cflags) +LDFLAGS += $(shell pkg-config sdl3 --libs) +``` + +The SDL3test library has been renamed SDL3_test. + +The SDLmain library has been removed, it's been entirely replaced by SDL_main.h. + +The vi format comments have been removed from source code. Vim users can use the [editorconfig plugin](https://github.com/editorconfig/editorconfig-vim) to automatically set tab spacing for the SDL coding style. + +## SDL_atomic.h + +The following structures have been renamed: +- SDL_atomic_t => SDL_AtomicInt + +## SDL_audio.h + +The audio subsystem in SDL3 is dramatically different than SDL2. The primary way to play audio is no longer an audio callback; instead you bind SDL_AudioStreams to devices; however, there is still a callback method available if needed. + +The SDL 1.2 audio compatibility API has also been removed, as it was a simplified version of the audio callback interface. + +SDL3 will not implicitly initialize the audio subsystem on your behalf if you open a device without doing so. Please explicitly call SDL_Init(SDL_INIT_AUDIO) at some point. + +SDL3's audio subsystem offers an enormous amount of power over SDL2, but if you just want a simple migration of your existing code, you can ignore most of it. The simplest migration path from SDL2 looks something like this: + +In SDL2, you might have done something like this to play audio... + +```c + void SDLCALL MyAudioCallback(void *userdata, Uint8 * stream, int len) + { + /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` */ + } + + /* ...somewhere near startup... */ + SDL_AudioSpec my_desired_audio_format; + SDL_zero(my_desired_audio_format); + my_desired_audio_format.format = AUDIO_S16; + my_desired_audio_format.channels = 2; + my_desired_audio_format.freq = 44100; + my_desired_audio_format.samples = 1024; + my_desired_audio_format.callback = MyAudioCallback; + my_desired_audio_format.userdata = &my_audio_callback_user_data; + SDL_AudioDeviceID my_audio_device = SDL_OpenAudioDevice(NULL, 0, &my_desired_audio_format, NULL, 0); + SDL_PauseAudioDevice(my_audio_device, 0); +``` + +...in SDL3, you can do this... + +```c + void SDLCALL MyNewAudioCallback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) + { + /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` + * + * If you want to use the original callback, you could do something like this: + */ + if (additional_amount > 0) { + Uint8 *data = SDL_stack_alloc(Uint8, additional_amount); + if (data) { + MyAudioCallback(userdata, data, additional_amount); + SDL_PutAudioStreamData(stream, data, additional_amount); + SDL_stack_free(data); + } + } + } + + /* ...somewhere near startup... */ + const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; + SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyNewAudioCallback, &my_audio_callback_user_data); + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); +``` + +If you used SDL_QueueAudio instead of a callback in SDL2, this is also straightforward. + +```c + /* ...somewhere near startup... */ + const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; + SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); + + /* ...in your main loop... */ + /* calculate a little more audio into `buf`, add it to `stream` */ + SDL_PutAudioStreamData(stream, buf, buflen); + +``` + +...these same migration examples apply to audio capture, just using SDL_GetAudioStreamData instead of SDL_PutAudioStreamData. + +SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint. + +The `SDL_AUDIO_ALLOW_*` symbols have been removed; now one may request the format they desire from the audio device, but ultimately SDL_AudioStream will manage the difference. One can use SDL_GetAudioDeviceFormat() to see what the final format is, if any "allowed" changes should be accomodated by the app. + +SDL_AudioDeviceID now represents both an open audio device's handle (a "logical" device) and the instance ID that the hardware owns as long as it exists on the system (a "physical" device). The separation between device instances and device indexes is gone, and logical and physical devices are almost entirely interchangeable at the API level. + +Devices are opened by physical device instance ID, and a new logical instance ID is generated by the open operation; This allows any device to be opened multiple times, possibly by unrelated pieces of code. SDL will manage the logical devices to provide a single stream of audio to the physical device behind the scenes. + +Devices are not opened by an arbitrary string name anymore, but by device instance ID (or magic numbers to request a reasonable default, like a NULL string in SDL2). In SDL2, the string was used to open both a standard list of system devices, but also allowed for arbitrary devices, such as hostnames of network sound servers. In SDL3, many of the backends that supported arbitrary device names are obsolete and have been removed; of those that remain, arbitrary devices will be opened with a default device ID and an SDL_hint, so specific end-users can set an environment variable to fit their needs and apps don't have to concern themselves with it. + +Many functions that would accept a device index and an `iscapture` parameter now just take an SDL_AudioDeviceID, as they are unique across all devices, instead of separate indices into output and capture device lists. + +Rather than iterating over audio devices using a device index, there are new functions, SDL_GetAudioOutputDevices() and SDL_GetAudioCaptureDevices(), to get the current list of devices, and new functions to get information about devices from their instance ID: + +```c +{ + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == 0) { + int i, num_devices; + SDL_AudioDeviceID *devices = SDL_GetAudioOutputDevices(&num_devices); + if (devices) { + for (i = 0; i < num_devices; ++i) { + SDL_AudioDeviceID instance_id = devices[i]; + char *name = SDL_GetAudioDeviceName(instance_id); + SDL_Log("AudioDevice %" SDL_PRIu32 ": %s\n", instance_id, name); + SDL_free(name); + } + SDL_free(devices); + } + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } +} +``` + +SDL_LockAudioDevice() and SDL_UnlockAudioDevice() have been removed, since there is no callback in another thread to protect. SDL's audio subsystem and SDL_AudioStream maintain their own locks internally, so audio streams are safe to use from any thread. If the app assigns a callback to a specific stream, it can use the stream's lock through SDL_LockAudioStream() if necessary. + +SDL_PauseAudioDevice() no longer takes a second argument; it always pauses the device. To unpause, use SDL_ResumeAudioDevice(). + +Audio devices, opened by SDL_OpenAudioDevice(), no longer start in a paused state, as they don't begin processing audio until a stream is bound. + +SDL_GetAudioDeviceStatus() has been removed; there is now SDL_AudioDevicePaused(). + +SDL_QueueAudio(), SDL_DequeueAudio, and SDL_ClearQueuedAudio and SDL_GetQueuedAudioSize() have been removed; an SDL_AudioStream bound to a device provides the exact same functionality. + +APIs that use channel counts used to use a Uint8 for the channel; now they use int. + +SDL_AudioSpec has been reduced; now it only holds format, channel, and sample rate. SDL_GetSilenceValueForFormat() can provide the information from the SDL_AudioSpec's `silence` field. The other SDL2 SDL_AudioSpec fields aren't relevant anymore. + +SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead. + +SDL_GetDefaultAudioInfo() is removed; SDL_GetAudioDeviceFormat() with SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or SDL_AUDIO_DEVICE_DEFAULT_CAPTURE. There is no replacement for querying the default device name; the string is no longer used to open devices, and SDL3 will migrate between physical devices on the fly if the system default changes, so if you must show this to the user, a generic name like "System default" is recommended. + +SDL_MixAudio() has been removed, as it relied on legacy SDL 1.2 quirks; SDL_MixAudioFormat() remains and offers the same functionality. + +SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint. + +SDL_FreeWAV has been removed and calls can be replaced with SDL_free. + +SDL_LoadWAV() is a proper function now and no longer a macro (but offers the same functionality otherwise). + +SDL_LoadWAV_RW() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec. + +SDL_AudioCVT interface has been removed, the SDL_AudioStream interface (for audio supplied in pieces) or the new SDL_ConvertAudioSamples() function (for converting a complete audio buffer in one call) can be used instead. + +Code that used to look like this: +```c + SDL_AudioCVT cvt; + SDL_BuildAudioCVT(&cvt, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate); + cvt.len = src_len; + cvt.buf = (Uint8 *) SDL_malloc(src_len * cvt.len_mult); + SDL_memcpy(cvt.buf, src_data, src_len); + SDL_ConvertAudio(&cvt); + do_something(cvt.buf, cvt.len_cvt); +``` +should be changed to: +```c + Uint8 *dst_data = NULL; + int dst_len = 0; + const SDL_AudioSpec src_spec = { src_format, src_channels, src_rate }; + const SDL_AudioSpec dst_spec = { dst_format, dst_channels, dst_rate }; + if (SDL_ConvertAudioSamples(&src_spec, src_data, src_len, &dst_spec, &dst_data, &dst_len) < 0) { + /* error */ + } + do_something(dst_data, dst_len); + SDL_free(dst_data); +``` + +AUDIO_U16, AUDIO_U16LSB, AUDIO_U16MSB, and AUDIO_U16SYS have been removed. They were not heavily used, and one could not memset a buffer in this format to silence with a single byte value. Use a different audio format. + +If you need to convert U16 audio data to a still-supported format at runtime, the fastest, lossless conversion is to SDL_AUDIO_S16: + +```c + /* this converts the buffer in-place. The buffer size does not change. */ + Sint16 *audio_ui16_to_si16(Uint16 *buffer, const size_t num_samples) + { + size_t i; + const Uint16 *src = buffer; + Sint16 *dst = (Sint16 *) buffer; + + for (i = 0; i < num_samples; i++) { + dst[i] = (Sint16) (src[i] ^ 0x8000); + } + + return dst; + } +``` + +All remaining `AUDIO_*` symbols have been renamed to `SDL_AUDIO_*` for API consistency, but othewise are identical in value and usage. + +In SDL2, SDL_AudioStream would convert/resample audio data during input (via SDL_AudioStreamPut). In SDL3, it does this work when requesting audio (via SDL_GetAudioStreamData, which would have been SDL_AudioStreamGet in SDL2). The way you use an AudioStream is roughly the same, just be aware that the workload moved to a different phase. + +In SDL2, SDL_AudioStreamAvailable() returns 0 if passed a NULL stream. In SDL3, the equivalent SDL_GetAudioStreamAvailable() call returns -1 and sets an error string, which matches other audiostream APIs' behavior. + +In SDL2, SDL_AUDIODEVICEREMOVED events would fire for open devices with the `which` field set to the SDL_AudioDeviceID of the lost device, and in later SDL2 releases, would also fire this event with a `which` field of zero for unopened devices, to signify that the app might want to refresh the available device list. In SDL3, this event works the same, except it won't ever fire with a zero; in this case it'll return the physical device's SDL_AudioDeviceID. Any still-open SDL_AudioDeviceIDs generated from this device with SDL_OpenAudioDevice() will also fire a separate event. + +The following functions have been renamed: +* SDL_AudioStreamAvailable() => SDL_GetAudioStreamAvailable() +* SDL_AudioStreamClear() => SDL_ClearAudioStream() +* SDL_AudioStreamFlush() => SDL_FlushAudioStream() +* SDL_AudioStreamGet() => SDL_GetAudioStreamData() +* SDL_AudioStreamPut() => SDL_PutAudioStreamData() +* SDL_FreeAudioStream() => SDL_DestroyAudioStream() +* SDL_NewAudioStream() => SDL_CreateAudioStream() + + +The following functions have been removed: +* SDL_GetNumAudioDevices() +* SDL_GetAudioDeviceSpec() +* SDL_ConvertAudio() +* SDL_BuildAudioCVT() +* SDL_OpenAudio() +* SDL_CloseAudio() +* SDL_PauseAudio() +* SDL_GetAudioStatus() +* SDL_GetAudioDeviceStatus() +* SDL_GetDefaultAudioInfo() +* SDL_LockAudio() +* SDL_LockAudioDevice() +* SDL_UnlockAudio() +* SDL_UnlockAudioDevice() +* SDL_MixAudio() +* SDL_QueueAudio() +* SDL_DequeueAudio() +* SDL_ClearAudioQueue() +* SDL_GetQueuedAudioSize() + +The following symbols have been renamed: +* AUDIO_F32 => SDL_AUDIO_F32LE +* AUDIO_F32LSB => SDL_AUDIO_F32LE +* AUDIO_F32MSB => SDL_AUDIO_F32BE +* AUDIO_F32SYS => SDL_AUDIO_F32 +* AUDIO_S16 => SDL_AUDIO_S16LE +* AUDIO_S16LSB => SDL_AUDIO_S16LE +* AUDIO_S16MSB => SDL_AUDIO_S16BE +* AUDIO_S16SYS => SDL_AUDIO_S16 +* AUDIO_S32 => SDL_AUDIO_S32LE +* AUDIO_S32LSB => SDL_AUDIO_S32LE +* AUDIO_S32MSB => SDL_AUDIO_S32BE +* AUDIO_S32SYS => SDL_AUDIO_S32 +* AUDIO_S8 => SDL_AUDIO_S8 +* AUDIO_U8 => SDL_AUDIO_U8 + +## SDL_cpuinfo.h + +The intrinsics headers (mmintrin.h, etc.) have been moved to `` and are no longer automatically included in SDL.h. + +SDL_Has3DNow() has been removed; there is no replacement. + +SDL_HasRDTSC() has been removed; there is no replacement. Don't use the RDTSC opcode in modern times, use SDL_GetPerformanceCounter and SDL_GetPerformanceFrequency instead. + +SDL_SIMDAlloc(), SDL_SIMDRealloc(), and SDL_SIMDFree() have been removed. You can use SDL_aligned_alloc() and SDL_aligned_free() with SDL_SIMDGetAlignment() to get the same functionality. + +## SDL_events.h + +The timestamp member of the SDL_Event structure now represents nanoseconds, and is populated with SDL_GetTicksNS() + +The timestamp_us member of the sensor events has been renamed sensor_timestamp and now represents nanoseconds. This value is filled in from the hardware, if available, and may not be synchronized with values returned from SDL_GetTicksNS(). + +You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). + +Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. + +Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. + +The SDL_DISPLAYEVENT_* events have been moved to top level events, and SDL_DISPLAYEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_DISPLAYEVENT and then checking for display events. You can compare the event >= SDL_EVENT_DISPLAY_FIRST and <= SDL_EVENT_DISPLAY_LAST if you need to see whether it's a display event. + +The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event. + +The SDL_EVENT_WINDOW_RESIZED event is always sent, even in response to SDL_SetWindowSize(). + +The SDL_EVENT_WINDOW_SIZE_CHANGED event has been removed, and you can use SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED to detect window backbuffer size changes. + +The gamepad event structures caxis, cbutton, cdevice, ctouchpad, and csensor have been renamed gaxis, gbutton, gdevice, gtouchpad, and gsensor. + +SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state. + +SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback. + +The following symbols have been renamed: +* SDL_APP_DIDENTERBACKGROUND => SDL_EVENT_DID_ENTER_BACKGROUND +* SDL_APP_DIDENTERFOREGROUND => SDL_EVENT_DID_ENTER_FOREGROUND +* SDL_APP_LOWMEMORY => SDL_EVENT_LOW_MEMORY +* SDL_APP_TERMINATING => SDL_EVENT_TERMINATING +* SDL_APP_WILLENTERBACKGROUND => SDL_EVENT_WILL_ENTER_BACKGROUND +* SDL_APP_WILLENTERFOREGROUND => SDL_EVENT_WILL_ENTER_FOREGROUND +* SDL_AUDIODEVICEADDED => SDL_EVENT_AUDIO_DEVICE_ADDED +* SDL_AUDIODEVICEREMOVED => SDL_EVENT_AUDIO_DEVICE_REMOVED +* SDL_CLIPBOARDUPDATE => SDL_EVENT_CLIPBOARD_UPDATE +* SDL_CONTROLLERAXISMOTION => SDL_EVENT_GAMEPAD_AXIS_MOTION +* SDL_CONTROLLERBUTTONDOWN => SDL_EVENT_GAMEPAD_BUTTON_DOWN +* SDL_CONTROLLERBUTTONUP => SDL_EVENT_GAMEPAD_BUTTON_UP +* SDL_CONTROLLERDEVICEADDED => SDL_EVENT_GAMEPAD_ADDED +* SDL_CONTROLLERDEVICEREMAPPED => SDL_EVENT_GAMEPAD_REMAPPED +* SDL_CONTROLLERDEVICEREMOVED => SDL_EVENT_GAMEPAD_REMOVED +* SDL_CONTROLLERSENSORUPDATE => SDL_EVENT_GAMEPAD_SENSOR_UPDATE +* SDL_CONTROLLERTOUCHPADDOWN => SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN +* SDL_CONTROLLERTOUCHPADMOTION => SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION +* SDL_CONTROLLERTOUCHPADUP => SDL_EVENT_GAMEPAD_TOUCHPAD_UP +* SDL_DROPBEGIN => SDL_EVENT_DROP_BEGIN +* SDL_DROPCOMPLETE => SDL_EVENT_DROP_COMPLETE +* SDL_DROPFILE => SDL_EVENT_DROP_FILE +* SDL_DROPTEXT => SDL_EVENT_DROP_TEXT +* SDL_FINGERDOWN => SDL_EVENT_FINGER_DOWN +* SDL_FINGERMOTION => SDL_EVENT_FINGER_MOTION +* SDL_FINGERUP => SDL_EVENT_FINGER_UP +* SDL_FIRSTEVENT => SDL_EVENT_FIRST +* SDL_JOYAXISMOTION => SDL_EVENT_JOYSTICK_AXIS_MOTION +* SDL_JOYBATTERYUPDATED => SDL_EVENT_JOYSTICK_BATTERY_UPDATED +* SDL_JOYBUTTONDOWN => SDL_EVENT_JOYSTICK_BUTTON_DOWN +* SDL_JOYBUTTONUP => SDL_EVENT_JOYSTICK_BUTTON_UP +* SDL_JOYDEVICEADDED => SDL_EVENT_JOYSTICK_ADDED +* SDL_JOYDEVICEREMOVED => SDL_EVENT_JOYSTICK_REMOVED +* SDL_JOYHATMOTION => SDL_EVENT_JOYSTICK_HAT_MOTION +* SDL_KEYDOWN => SDL_EVENT_KEY_DOWN +* SDL_KEYMAPCHANGED => SDL_EVENT_KEYMAP_CHANGED +* SDL_KEYUP => SDL_EVENT_KEY_UP +* SDL_LASTEVENT => SDL_EVENT_LAST +* SDL_LOCALECHANGED => SDL_EVENT_LOCALE_CHANGED +* SDL_MOUSEBUTTONDOWN => SDL_EVENT_MOUSE_BUTTON_DOWN +* SDL_MOUSEBUTTONUP => SDL_EVENT_MOUSE_BUTTON_UP +* SDL_MOUSEMOTION => SDL_EVENT_MOUSE_MOTION +* SDL_MOUSEWHEEL => SDL_EVENT_MOUSE_WHEEL +* SDL_POLLSENTINEL => SDL_EVENT_POLL_SENTINEL +* SDL_QUIT => SDL_EVENT_QUIT +* SDL_RENDER_DEVICE_RESET => SDL_EVENT_RENDER_DEVICE_RESET +* SDL_RENDER_TARGETS_RESET => SDL_EVENT_RENDER_TARGETS_RESET +* SDL_SENSORUPDATE => SDL_EVENT_SENSOR_UPDATE +* SDL_SYSWMEVENT => SDL_EVENT_SYSWM +* SDL_TEXTEDITING => SDL_EVENT_TEXT_EDITING +* SDL_TEXTEDITING_EXT => SDL_EVENT_TEXT_EDITING_EXT +* SDL_TEXTINPUT => SDL_EVENT_TEXT_INPUT +* SDL_USEREVENT => SDL_EVENT_USER + +The following structures have been renamed: +* SDL_ControllerAxisEvent => SDL_GamepadAxisEvent +* SDL_ControllerButtonEvent => SDL_GamepadButtonEvent +* SDL_ControllerDeviceEvent => SDL_GamepadDeviceEvent +* SDL_ControllerSensorEvent => SDL_GamepadSensorEvent +* SDL_ControllerTouchpadEvent => SDL_GamepadTouchpadEvent + +The following functions have been removed: +* SDL_EventState() - replaced with SDL_SetEventEnabled() +* SDL_GetEventState() - replaced with SDL_EventEnabled() + +## SDL_gamecontroller.h + +SDL_gamecontroller.h has been renamed SDL_gamepad.h, and all APIs have been renamed to match. + +The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the which member of the cdevice event structure. + +The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads. + +The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications will now need to provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. Using South as the accept button and East as the cancel button is a good default. + +SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events. + +SDL_CONTROLLER_TYPE_VIRTUAL has been removed, so virtual controllers can emulate other gamepad types. If you need to know whether a controller is virtual, you can use SDL_IsJoystickVirtual(). + +SDL_CONTROLLER_TYPE_AMAZON_LUNA has been removed, and can be replaced with this code: +```c +SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id) +{ + return ((vendor_id == 0x1949 && product_id == 0x0419) || + (vendor_id == 0x0171 && product_id == 0x0419)); +} +``` + +SDL_CONTROLLER_TYPE_GOOGLE_STADIA has been removed, and can be replaced with this code: +```c +SDL_bool SDL_IsJoystickGoogleStadiaController(Uint16 vendor_id, Uint16 product_id) +{ + return (vendor_id == 0x18d1 && product_id == 0x9400); +} +``` + +SDL_CONTROLLER_TYPE_NVIDIA_SHIELD has been removed, and can be replaced with this code: +```c +SDL_bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_id) +{ + return (vendor_id == 0x0955 && (product_id == 0x7210 || product_id == 0x7214)); +} +``` + +The following enums have been renamed: +* SDL_GameControllerAxis => SDL_GamepadAxis +* SDL_GameControllerBindType => SDL_GamepadBindingType +* SDL_GameControllerButton => SDL_GamepadButton +* SDL_GameControllerType => SDL_GamepadType + +The following structures have been renamed: +* SDL_GameController => SDL_Gamepad + +The following functions have been renamed: +* SDL_GameControllerAddMapping() => SDL_AddGamepadMapping() +* SDL_GameControllerAddMappingsFromFile() => SDL_AddGamepadMappingsFromFile() +* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromRW() +* SDL_GameControllerClose() => SDL_CloseGamepad() +* SDL_GameControllerFromInstanceID() => SDL_GetGamepadFromInstanceID() +* SDL_GameControllerFromPlayerIndex() => SDL_GetGamepadFromPlayerIndex() +* SDL_GameControllerGetAppleSFSymbolsNameForAxis() => SDL_GetGamepadAppleSFSymbolsNameForAxis() +* SDL_GameControllerGetAppleSFSymbolsNameForButton() => SDL_GetGamepadAppleSFSymbolsNameForButton() +* SDL_GameControllerGetAttached() => SDL_GamepadConnected() +* SDL_GameControllerGetAxis() => SDL_GetGamepadAxis() +* SDL_GameControllerGetAxisFromString() => SDL_GetGamepadAxisFromString() +* SDL_GameControllerGetButton() => SDL_GetGamepadButton() +* SDL_GameControllerGetButtonFromString() => SDL_GetGamepadButtonFromString() +* SDL_GameControllerGetFirmwareVersion() => SDL_GetGamepadFirmwareVersion() +* SDL_GameControllerGetJoystick() => SDL_GetGamepadJoystick() +* SDL_GameControllerGetNumTouchpadFingers() => SDL_GetNumGamepadTouchpadFingers() +* SDL_GameControllerGetNumTouchpads() => SDL_GetNumGamepadTouchpads() +* SDL_GameControllerGetPlayerIndex() => SDL_GetGamepadPlayerIndex() +* SDL_GameControllerGetProduct() => SDL_GetGamepadProduct() +* SDL_GameControllerGetProductVersion() => SDL_GetGamepadProductVersion() +* SDL_GameControllerGetSensorData() => SDL_GetGamepadSensorData() +* SDL_GameControllerGetSensorDataRate() => SDL_GetGamepadSensorDataRate() +* SDL_GameControllerGetSerial() => SDL_GetGamepadSerial() +* SDL_GameControllerGetStringForAxis() => SDL_GetGamepadStringForAxis() +* SDL_GameControllerGetStringForButton() => SDL_GetGamepadStringForButton() +* SDL_GameControllerGetTouchpadFinger() => SDL_GetGamepadTouchpadFinger() +* SDL_GameControllerGetType() => SDL_GetGamepadType() +* SDL_GameControllerGetVendor() => SDL_GetGamepadVendor() +* SDL_GameControllerHasAxis() => SDL_GamepadHasAxis() +* SDL_GameControllerHasButton() => SDL_GamepadHasButton() +* SDL_GameControllerHasLED() => SDL_GamepadHasLED() +* SDL_GameControllerHasRumble() => SDL_GamepadHasRumble() +* SDL_GameControllerHasRumbleTriggers() => SDL_GamepadHasRumbleTriggers() +* SDL_GameControllerHasSensor() => SDL_GamepadHasSensor() +* SDL_GameControllerIsSensorEnabled() => SDL_GamepadSensorEnabled() +* SDL_GameControllerMapping() => SDL_GetGamepadMapping() +* SDL_GameControllerMappingForGUID() => SDL_GetGamepadMappingForGUID() +* SDL_GameControllerMappingForIndex() => SDL_GetGamepadMappingForIndex() +* SDL_GameControllerName() => SDL_GetGamepadName() +* SDL_GameControllerNumMappings() => SDL_GetNumGamepadMappings() +* SDL_GameControllerOpen() => SDL_OpenGamepad() +* SDL_GameControllerPath() => SDL_GetGamepadPath() +* SDL_GameControllerRumble() => SDL_RumbleGamepad() +* SDL_GameControllerRumbleTriggers() => SDL_RumbleGamepadTriggers() +* SDL_GameControllerSendEffect() => SDL_SendGamepadEffect() +* SDL_GameControllerSetLED() => SDL_SetGamepadLED() +* SDL_GameControllerSetPlayerIndex() => SDL_SetGamepadPlayerIndex() +* SDL_GameControllerSetSensorEnabled() => SDL_SetGamepadSensorEnabled() +* SDL_GameControllerUpdate() => SDL_UpdateGamepads() +* SDL_IsGameController() => SDL_IsGamepad() + +The following functions have been removed: +* SDL_GameControllerEventState() - replaced with SDL_SetGamepadEventsEnabled() and SDL_GamepadEventsEnabled() +* SDL_GameControllerGetBindForAxis() - replaced with SDL_GetGamepadBindings() +* SDL_GameControllerGetBindForButton() - replaced with SDL_GetGamepadBindings() +* SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadInstanceMapping() +* SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName() +* SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath() +* SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType() + +The following symbols have been renamed: +* SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID +* SDL_CONTROLLER_AXIS_LEFTX => SDL_GAMEPAD_AXIS_LEFTX +* SDL_CONTROLLER_AXIS_LEFTY => SDL_GAMEPAD_AXIS_LEFTY +* SDL_CONTROLLER_AXIS_MAX => SDL_GAMEPAD_AXIS_MAX +* SDL_CONTROLLER_AXIS_RIGHTX => SDL_GAMEPAD_AXIS_RIGHTX +* SDL_CONTROLLER_AXIS_RIGHTY => SDL_GAMEPAD_AXIS_RIGHTY +* SDL_CONTROLLER_AXIS_TRIGGERLEFT => SDL_GAMEPAD_AXIS_LEFT_TRIGGER +* SDL_CONTROLLER_AXIS_TRIGGERRIGHT => SDL_GAMEPAD_AXIS_RIGHT_TRIGGER +* SDL_CONTROLLER_BINDTYPE_AXIS => SDL_GAMEPAD_BINDTYPE_AXIS +* SDL_CONTROLLER_BINDTYPE_BUTTON => SDL_GAMEPAD_BINDTYPE_BUTTON +* SDL_CONTROLLER_BINDTYPE_HAT => SDL_GAMEPAD_BINDTYPE_HAT +* SDL_CONTROLLER_BINDTYPE_NONE => SDL_GAMEPAD_BINDTYPE_NONE +* SDL_CONTROLLER_BUTTON_A => SDL_GAMEPAD_BUTTON_SOUTH +* SDL_CONTROLLER_BUTTON_B => SDL_GAMEPAD_BUTTON_EAST +* SDL_CONTROLLER_BUTTON_BACK => SDL_GAMEPAD_BUTTON_BACK +* SDL_CONTROLLER_BUTTON_DPAD_DOWN => SDL_GAMEPAD_BUTTON_DPAD_DOWN +* SDL_CONTROLLER_BUTTON_DPAD_LEFT => SDL_GAMEPAD_BUTTON_DPAD_LEFT +* SDL_CONTROLLER_BUTTON_DPAD_RIGHT => SDL_GAMEPAD_BUTTON_DPAD_RIGHT +* SDL_CONTROLLER_BUTTON_DPAD_UP => SDL_GAMEPAD_BUTTON_DPAD_UP +* SDL_CONTROLLER_BUTTON_GUIDE => SDL_GAMEPAD_BUTTON_GUIDE +* SDL_CONTROLLER_BUTTON_INVALID => SDL_GAMEPAD_BUTTON_INVALID +* SDL_CONTROLLER_BUTTON_LEFTSHOULDER => SDL_GAMEPAD_BUTTON_LEFT_SHOULDER +* SDL_CONTROLLER_BUTTON_LEFTSTICK => SDL_GAMEPAD_BUTTON_LEFT_STICK +* SDL_CONTROLLER_BUTTON_MAX => SDL_GAMEPAD_BUTTON_MAX +* SDL_CONTROLLER_BUTTON_MISC1 => SDL_GAMEPAD_BUTTON_MISC1 +* SDL_CONTROLLER_BUTTON_PADDLE1 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 +* SDL_CONTROLLER_BUTTON_PADDLE2 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 +* SDL_CONTROLLER_BUTTON_PADDLE3 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 +* SDL_CONTROLLER_BUTTON_PADDLE4 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 +* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER => SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER +* SDL_CONTROLLER_BUTTON_RIGHTSTICK => SDL_GAMEPAD_BUTTON_RIGHT_STICK +* SDL_CONTROLLER_BUTTON_START => SDL_GAMEPAD_BUTTON_START +* SDL_CONTROLLER_BUTTON_TOUCHPAD => SDL_GAMEPAD_BUTTON_TOUCHPAD +* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_WEST +* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_NORTH +* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT +* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR +* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT +* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO +* SDL_CONTROLLER_TYPE_PS3 => SDL_GAMEPAD_TYPE_PS3 +* SDL_CONTROLLER_TYPE_PS4 => SDL_GAMEPAD_TYPE_PS4 +* SDL_CONTROLLER_TYPE_PS5 => SDL_GAMEPAD_TYPE_PS5 +* SDL_CONTROLLER_TYPE_UNKNOWN => SDL_GAMEPAD_TYPE_STANDARD +* SDL_CONTROLLER_TYPE_VIRTUAL => SDL_GAMEPAD_TYPE_VIRTUAL +* SDL_CONTROLLER_TYPE_XBOX360 => SDL_GAMEPAD_TYPE_XBOX360 +* SDL_CONTROLLER_TYPE_XBOXONE => SDL_GAMEPAD_TYPE_XBOXONE + +## SDL_gesture.h + +The gesture API has been removed. There is no replacement planned in SDL3. +However, the SDL2 code has been moved to a single-header library that can +be dropped into an SDL3 or SDL2 program, to continue to provide this +functionality to your app and aid migration. That is located in the +[SDL_gesture GitHub repository](https://github.com/libsdl-org/SDL_gesture). + +## SDL_hints.h + +SDL_AddHintCallback() now returns a standard int result instead of void, returning 0 if the function succeeds or a negative error code if there was an error. + +Calling SDL_GetHint() with the name of the hint being changed from within a hint callback will now return the new value rather than the old value. The old value is still passed as a parameter to the hint callback. + +The following hints have been removed: +* SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional +* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver instead +* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text +* SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer +* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() +* SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API. +* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled +* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead +* SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend +* SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend + +* Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER +* Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER +* The environment variables SDL_VIDEO_X11_WMCLASS and SDL_VIDEO_WAYLAND_WMCLASS have been removed and replaced with the unified hint SDL_HINT_APP_ID + +## SDL_init.h + +The following symbols have been renamed: +* SDL_INIT_GAMECONTROLLER => SDL_INIT_GAMEPAD + +The following symbols have been removed: +* SDL_INIT_NOPARACHUTE + +## SDL_joystick.h + +SDL_JoystickID has changed from Sint32 to Uint32, with an invalid ID being 0. + +Rather than iterating over joysticks using device index, there is a new function SDL_GetJoysticks() to get the current list of joysticks, and new functions to get information about joysticks from their instance ID: +```c +{ + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == 0) { + int i, num_joysticks; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks); + if (joysticks) { + for (i = 0; i < num_joysticks; ++i) { + SDL_JoystickID instance_id = joysticks[i]; + const char *name = SDL_GetJoystickInstanceName(instance_id); + const char *path = SDL_GetJoystickInstancePath(instance_id); + + SDL_Log("Joystick %" SDL_PRIu32 ": %s%s%s VID 0x%.4x, PID 0x%.4x\n", + instance_id, name ? name : "Unknown", path ? ", " : "", path ? path : "", SDL_GetJoystickInstanceVendor(instance_id), SDL_GetJoystickInstanceProduct(instance_id)); + } + SDL_free(joysticks); + } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } +} +``` + +The SDL_EVENT_JOYSTICK_ADDED event now provides the joystick instance ID in the `which` member of the jdevice event structure. + +The functions SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() have been added to directly query the list of available joysticks. + +SDL_AttachVirtualJoystick() and SDL_AttachVirtualJoystickEx() now return the joystick instance ID instead of a device index, and return 0 if there was an error. + +The following functions have been renamed: +* SDL_JoystickAttachVirtual() => SDL_AttachVirtualJoystick() +* SDL_JoystickAttachVirtualEx() => SDL_AttachVirtualJoystickEx() +* SDL_JoystickClose() => SDL_CloseJoystick() +* SDL_JoystickCurrentPowerLevel() => SDL_GetJoystickPowerLevel() +* SDL_JoystickDetachVirtual() => SDL_DetachVirtualJoystick() +* SDL_JoystickFromInstanceID() => SDL_GetJoystickFromInstanceID() +* SDL_JoystickFromPlayerIndex() => SDL_GetJoystickFromPlayerIndex() +* SDL_JoystickGetAttached() => SDL_JoystickConnected() +* SDL_JoystickGetAxis() => SDL_GetJoystickAxis() +* SDL_JoystickGetAxisInitialState() => SDL_GetJoystickAxisInitialState() +* SDL_JoystickGetButton() => SDL_GetJoystickButton() +* SDL_JoystickGetFirmwareVersion() => SDL_GetJoystickFirmwareVersion() +* SDL_JoystickGetGUID() => SDL_GetJoystickGUID() +* SDL_JoystickGetGUIDFromString() => SDL_GetJoystickGUIDFromString() +* SDL_JoystickGetGUIDString() => SDL_GetJoystickGUIDString() +* SDL_JoystickGetHat() => SDL_GetJoystickHat() +* SDL_JoystickGetPlayerIndex() => SDL_GetJoystickPlayerIndex() +* SDL_JoystickGetProduct() => SDL_GetJoystickProduct() +* SDL_JoystickGetProductVersion() => SDL_GetJoystickProductVersion() +* SDL_JoystickGetSerial() => SDL_GetJoystickSerial() +* SDL_JoystickGetType() => SDL_GetJoystickType() +* SDL_JoystickGetVendor() => SDL_GetJoystickVendor() +* SDL_JoystickInstanceID() => SDL_GetJoystickInstanceID() +* SDL_JoystickIsVirtual() => SDL_IsJoystickVirtual() +* SDL_JoystickName() => SDL_GetJoystickName() +* SDL_JoystickNumAxes() => SDL_GetNumJoystickAxes() +* SDL_JoystickNumButtons() => SDL_GetNumJoystickButtons() +* SDL_JoystickNumHats() => SDL_GetNumJoystickHats() +* SDL_JoystickOpen() => SDL_OpenJoystick() +* SDL_JoystickPath() => SDL_GetJoystickPath() +* SDL_JoystickRumble() => SDL_RumbleJoystick() +* SDL_JoystickRumbleTriggers() => SDL_RumbleJoystickTriggers() +* SDL_JoystickSendEffect() => SDL_SendJoystickEffect() +* SDL_JoystickSetLED() => SDL_SetJoystickLED() +* SDL_JoystickSetPlayerIndex() => SDL_SetJoystickPlayerIndex() +* SDL_JoystickSetVirtualAxis() => SDL_SetJoystickVirtualAxis() +* SDL_JoystickSetVirtualButton() => SDL_SetJoystickVirtualButton() +* SDL_JoystickSetVirtualHat() => SDL_SetJoystickVirtualHat() +* SDL_JoystickUpdate() => SDL_UpdateJoysticks() + +The following symbols have been renamed: +* SDL_JOYSTICK_TYPE_GAMECONTROLLER => SDL_JOYSTICK_TYPE_GAMEPAD + +The following functions have been removed: +* SDL_JoystickEventState() - replaced with SDL_SetJoystickEventsEnabled() and SDL_JoystickEventsEnabled() +* SDL_JoystickGetDeviceGUID() - replaced with SDL_GetJoystickInstanceGUID() +* SDL_JoystickGetDeviceInstanceID() +* SDL_JoystickGetDevicePlayerIndex() - replaced with SDL_GetJoystickInstancePlayerIndex() +* SDL_JoystickGetDeviceProduct() - replaced with SDL_GetJoystickInstanceProduct() +* SDL_JoystickGetDeviceProductVersion() - replaced with SDL_GetJoystickInstanceProductVersion() +* SDL_JoystickGetDeviceType() - replaced with SDL_GetJoystickInstanceType() +* SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickInstanceVendor() +* SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickInstanceName() +* SDL_JoystickNumBalls() - API has been removed, see https://github.com/libsdl-org/SDL/issues/6766 +* SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickInstancePath() +* SDL_NumJoysticks() - replaced with SDL_GetJoysticks() + +The following symbols have been removed: +* SDL_JOYBALLMOTION + +## SDL_keyboard.h + +The following functions have been renamed: +* SDL_IsScreenKeyboardShown() => SDL_ScreenKeyboardShown() +* SDL_IsTextInputActive() => SDL_TextInputActive() +* SDL_IsTextInputShown() => SDL_TextInputShown() + +## SDL_keycode.h + +The following symbols have been renamed: +* KMOD_ALT => SDL_KMOD_ALT +* KMOD_CAPS => SDL_KMOD_CAPS +* KMOD_CTRL => SDL_KMOD_CTRL +* KMOD_GUI => SDL_KMOD_GUI +* KMOD_LALT => SDL_KMOD_LALT +* KMOD_LCTRL => SDL_KMOD_LCTRL +* KMOD_LGUI => SDL_KMOD_LGUI +* KMOD_LSHIFT => SDL_KMOD_LSHIFT +* KMOD_MODE => SDL_KMOD_MODE +* KMOD_NONE => SDL_KMOD_NONE +* KMOD_NUM => SDL_KMOD_NUM +* KMOD_RALT => SDL_KMOD_RALT +* KMOD_RCTRL => SDL_KMOD_RCTRL +* KMOD_RESERVED => SDL_KMOD_RESERVED +* KMOD_RGUI => SDL_KMOD_RGUI +* KMOD_RSHIFT => SDL_KMOD_RSHIFT +* KMOD_SCROLL => SDL_KMOD_SCROLL +* KMOD_SHIFT => SDL_KMOD_SHIFT + +## SDL_loadso.h + +SDL_LoadFunction() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior. + +## SDL_main.h + +SDL3 doesn't have a static libSDLmain to link against anymore. +Instead SDL_main.h is now a header-only library **and not included by SDL.h anymore**. + +Using it is really simple: Just `#include ` in the source file with your standard +`int main(int argc, char* argv[])` function. + +## SDL_metal.h + +SDL_Metal_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. + +## SDL_mouse.h + +SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() + +SDL_GetMouseState(), SDL_GetGlobalMouseState(), SDL_GetRelativeMouseState(), SDL_WarpMouseInWindow(), and SDL_WarpMouseGlobal() all use floating point mouse positions, to provide sub-pixel precision on platforms that support it. + +The following functions have been renamed: +* SDL_FreeCursor() => SDL_DestroyCursor() + +## SDL_mutex.h + +SDL_MUTEX_MAXWAIT has been removed; it suggested there was a maximum timeout one could outlive, instead of an infinite wait. Instead, pass a -1 to functions that accepted this symbol. + +SDL_LockMutex and SDL_UnlockMutex now return void; if the mutex is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the mutex is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior. + +The following functions have been renamed: +* SDL_CondBroadcast() => SDL_BroadcastCondition() +* SDL_CondSignal() => SDL_SignalCondition() +* SDL_CondWait() => SDL_WaitCondition() +* SDL_CondWaitTimeout() => SDL_WaitConditionTimeout() +* SDL_CreateCond() => SDL_CreateCondition() +* SDL_DestroyCond() => SDL_DestroyCondition() +* SDL_SemPost() => SDL_PostSemaphore() +* SDL_SemTryWait() => SDL_TryWaitSemaphore() +* SDL_SemValue() => SDL_GetSemaphoreValue() +* SDL_SemWait() => SDL_WaitSemaphore() +* SDL_SemWaitTimeout() => SDL_WaitSemaphoreTimeout() + +The following symbols have been renamed: +* SDL_cond => SDL_Condition +* SDL_mutex => SDL_Mutex +* SDL_sem => SDL_Semaphore + +## SDL_pixels.h + +SDL_CalculateGammaRamp has been removed, because SDL_SetWindowGammaRamp has been removed as well due to poor support in modern operating systems (see [SDL_video.h](#sdl_videoh)). + +The following functions have been renamed: +* SDL_AllocFormat() => SDL_CreatePixelFormat() +* SDL_AllocPalette() => SDL_CreatePalette() +* SDL_FreeFormat() => SDL_DestroyPixelFormat() +* SDL_FreePalette() => SDL_DestroyPalette() +* SDL_MasksToPixelFormatEnum() => SDL_GetPixelFormatEnumForMasks() +* SDL_PixelFormatEnumToMasks() => SDL_GetMasksForPixelFormatEnum() + +The following symbols have been renamed: +* SDL_DISPLAYEVENT_DISCONNECTED => SDL_EVENT_DISPLAY_REMOVED +* SDL_DISPLAYEVENT_MOVED => SDL_EVENT_DISPLAY_MOVED +* SDL_DISPLAYEVENT_ORIENTATION => SDL_EVENT_DISPLAY_ORIENTATION +* SDL_WINDOWEVENT_CLOSE => SDL_EVENT_WINDOW_CLOSE_REQUESTED +* SDL_WINDOWEVENT_DISPLAY_CHANGED => SDL_EVENT_WINDOW_DISPLAY_CHANGED +* SDL_WINDOWEVENT_ENTER => SDL_EVENT_WINDOW_ENTER +* SDL_WINDOWEVENT_EXPOSED => SDL_EVENT_WINDOW_EXPOSED +* SDL_WINDOWEVENT_FOCUS_GAINED => SDL_EVENT_WINDOW_FOCUS_GAINED +* SDL_WINDOWEVENT_FOCUS_LOST => SDL_EVENT_WINDOW_FOCUS_LOST +* SDL_WINDOWEVENT_HIDDEN => SDL_EVENT_WINDOW_HIDDEN +* SDL_WINDOWEVENT_HIT_TEST => SDL_EVENT_WINDOW_HIT_TEST +* SDL_WINDOWEVENT_ICCPROF_CHANGED => SDL_EVENT_WINDOW_ICCPROF_CHANGED +* SDL_WINDOWEVENT_LEAVE => SDL_EVENT_WINDOW_LEAVE +* SDL_WINDOWEVENT_MAXIMIZED => SDL_EVENT_WINDOW_MAXIMIZED +* SDL_WINDOWEVENT_MINIMIZED => SDL_EVENT_WINDOW_MINIMIZED +* SDL_WINDOWEVENT_MOVED => SDL_EVENT_WINDOW_MOVED +* SDL_WINDOWEVENT_RESIZED => SDL_EVENT_WINDOW_RESIZED +* SDL_WINDOWEVENT_RESTORED => SDL_EVENT_WINDOW_RESTORED +* SDL_WINDOWEVENT_SHOWN => SDL_EVENT_WINDOW_SHOWN +* SDL_WINDOWEVENT_SIZE_CHANGED => SDL_EVENT_WINDOW_SIZE_CHANGED +* SDL_WINDOWEVENT_TAKE_FOCUS => SDL_EVENT_WINDOW_TAKE_FOCUS + + +## SDL_platform.h + +The preprocessor symbol `__MACOSX__` has been renamed `__MACOS__`, and `__IPHONEOS__` has been renamed `__IOS__` + +## SDL_rect.h + +The following functions have been renamed: +* SDL_EncloseFPoints() => SDL_GetRectEnclosingPointsFloat() +* SDL_EnclosePoints() => SDL_GetRectEnclosingPoints() +* SDL_FRectEmpty() => SDL_RectEmptyFloat() +* SDL_FRectEquals() => SDL_RectsEqualFloat() +* SDL_FRectEqualsEpsilon() => SDL_RectsEqualEpsilon() +* SDL_HasIntersection() => SDL_HasRectIntersection() +* SDL_HasIntersectionF() => SDL_HasRectIntersectionFloat() +* SDL_IntersectFRect() => SDL_GetRectIntersectionFloat() +* SDL_IntersectFRectAndLine() => SDL_GetRectAndLineIntersectionFloat() +* SDL_IntersectRect() => SDL_GetRectIntersection() +* SDL_IntersectRectAndLine() => SDL_GetRectAndLineIntersection() +* SDL_PointInFRect() => SDL_PointInRectFloat() +* SDL_RectEquals() => SDL_RectsEqual() +* SDL_UnionFRect() => SDL_GetRectUnionFloat() +* SDL_UnionRect() => SDL_GetRectUnion() + +## SDL_render.h + +The 2D renderer API always uses batching in SDL3. There is no magic to turn +it on and off; it doesn't matter if you select a specific renderer or try to +use any hint. This means that all apps that use SDL3's 2D renderer and also +want to call directly into the platform's lower-layer graphics API _must_ call +SDL_RenderFlush() before doing so. This will make sure any pending rendering +work from SDL is done before the app starts directly drawing. + +SDL_GetRenderDriverInfo() has been removed, since most of the information it reported were +estimates and could not be accurate before creating a renderer. Often times this function +was used to figure out the index of a driver, so one would call it in a for-loop, looking +for the driver named "opengl" or whatnot. SDL_GetRenderDriver() has been added for this +functionality, which returns only the name of the driver. + +Additionally, SDL_CreateRenderer()'s second argument is no longer an integer index, but a +`const char *` representing a renderer's name; if you were just using a for-loop to find +which index is the "opengl" or whatnot driver, you can just pass that string directly +here, now. Passing NULL is the same as passing -1 here in SDL2, to signify you want SDL +to decide for you. + +The SDL_RENDERER_TARGETTEXTURE flag has been removed, all current renderers support target texture functionality. + +When a renderer is created, it will automatically set the logical size to the size of +the window in points. For high DPI displays, this will set up scaling from points to +pixels. You can disable this scaling with: +```c + SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST); +``` + +Mouse and touch events are no longer filtered to change their coordinates, instead you +can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into +the rendering viewport. + +SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions. + +The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active. + +The following functions have been renamed: +* SDL_GetRendererOutputSize() => SDL_GetCurrentRenderOutputSize() +* SDL_RenderCopy() => SDL_RenderTexture() +* SDL_RenderCopyEx() => SDL_RenderTextureRotated() +* SDL_RenderCopyExF() => SDL_RenderTextureRotated() +* SDL_RenderCopyF() => SDL_RenderTexture() +* SDL_RenderDrawLine() => SDL_RenderLine() +* SDL_RenderDrawLineF() => SDL_RenderLine() +* SDL_RenderDrawLines() => SDL_RenderLines() +* SDL_RenderDrawLinesF() => SDL_RenderLines() +* SDL_RenderDrawPoint() => SDL_RenderPoint() +* SDL_RenderDrawPointF() => SDL_RenderPoint() +* SDL_RenderDrawPoints() => SDL_RenderPoints() +* SDL_RenderDrawPointsF() => SDL_RenderPoints() +* SDL_RenderDrawRect() => SDL_RenderRect() +* SDL_RenderDrawRectF() => SDL_RenderRect() +* SDL_RenderDrawRects() => SDL_RenderRects() +* SDL_RenderDrawRectsF() => SDL_RenderRects() +* SDL_RenderFillRectF() => SDL_RenderFillRect() +* SDL_RenderFillRectsF() => SDL_RenderFillRects() +* SDL_RenderGetClipRect() => SDL_GetRenderClipRect() +* SDL_RenderGetIntegerScale() => SDL_GetRenderIntegerScale() +* SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalPresentation() +* SDL_RenderGetMetalCommandEncoder() => SDL_GetRenderMetalCommandEncoder() +* SDL_RenderGetMetalLayer() => SDL_GetRenderMetalLayer() +* SDL_RenderGetScale() => SDL_GetRenderScale() +* SDL_RenderGetViewport() => SDL_GetRenderViewport() +* SDL_RenderGetWindow() => SDL_GetRenderWindow() +* SDL_RenderIsClipEnabled() => SDL_RenderClipEnabled() +* SDL_RenderLogicalToWindow() => SDL_RenderCoordinatesToWindow() +* SDL_RenderSetClipRect() => SDL_SetRenderClipRect() +* SDL_RenderSetIntegerScale() => SDL_SetRenderIntegerScale() +* SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalPresentation() +* SDL_RenderSetScale() => SDL_SetRenderScale() +* SDL_RenderSetVSync() => SDL_SetRenderVSync() +* SDL_RenderSetViewport() => SDL_SetRenderViewport() +* SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow() + +The following functions have been removed: +* SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead +* SDL_RenderGetIntegerScale() +* SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE +* SDL_RenderTargetSupported() - render targets are always supported +* SDL_SetTextureUserData() - use SDL_GetTextureProperties() instead + +The following symbols have been renamed: +* SDL_ScaleModeBest => SDL_SCALEMODE_BEST +* SDL_ScaleModeLinear => SDL_SCALEMODE_LINEAR +* SDL_ScaleModeNearest => SDL_SCALEMODE_NEAREST + +## SDL_rwops.h + +The following symbols have been renamed: +* RW_SEEK_CUR => SDL_RW_SEEK_CUR +* RW_SEEK_END => SDL_RW_SEEK_END +* RW_SEEK_SET => SDL_RW_SEEK_SET + +SDL_RWread and SDL_RWwrite (and SDL_RWops::read, SDL_RWops::write) have a different function signature in SDL3. + +Previously they looked more like stdio: + +```c +size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum); +size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxnum); +``` + +But now they look more like POSIX: + +```c +size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size); +size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size); +``` + +Code that used to look like this: +``` +size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) +{ + return SDL_RWread(stream, ptr, size, nitems); +} +``` +should be changed to: +``` +size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) +{ + if (size > 0 && nitems > 0) { + return SDL_RWread(stream, ptr, size * nitems) / size; + } + return 0; +} +``` + +SDL_RWFromFP has been removed from the API, due to issues when the SDL library uses a different C runtime from the application. + +You can implement this in your own code easily: +```c +#include + + +static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence) +{ + int stdiowhence; + + switch (whence) { + case SDL_RW_SEEK_SET: + stdiowhence = SEEK_SET; + break; + case SDL_RW_SEEK_CUR: + stdiowhence = SEEK_CUR; + break; + case SDL_RW_SEEK_END: + stdiowhence = SEEK_END; + break; + default: + return SDL_SetError("Unknown value for 'whence'"); + } + + if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) { + Sint64 pos = ftell((FILE *)context->hidden.stdio.fp); + if (pos < 0) { + return SDL_SetError("Couldn't get stream offset"); + } + return pos; + } + return SDL_Error(SDL_EFSEEK); +} + +static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size) +{ + size_t bytes; + + bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp); + if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { + SDL_Error(SDL_EFREAD); + } + return bytes; +} + +static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size) +{ + size_t bytes; + + bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp); + if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { + SDL_Error(SDL_EFWRITE); + } + return bytes; +} + +static int SDLCALL stdio_close(SDL_RWops *context) +{ + int status = 0; + if (context->hidden.stdio.autoclose) { + if (fclose((FILE *)context->hidden.stdio.fp) != 0) { + status = SDL_Error(SDL_EFWRITE); + } + } + SDL_DestroyRW(context); + return status; +} + +SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose) +{ + SDL_RWops *rwops = NULL; + + rwops = SDL_CreateRW(); + if (rwops != NULL) { + rwops->seek = stdio_seek; + rwops->read = stdio_read; + rwops->write = stdio_write; + rwops->close = stdio_close; + rwops->hidden.stdio.fp = fp; + rwops->hidden.stdio.autoclose = autoclose; + rwops->type = SDL_RWOPS_STDFILE; + } + return rwops; +} +``` + +The functions SDL_ReadU8(), SDL_ReadU16LE(), SDL_ReadU16BE(), SDL_ReadU32LE(), SDL_ReadU32BE(), SDL_ReadU64LE(), and SDL_ReadU64BE() now return SDL_TRUE if the read succeeded and SDL_FALSE if it didn't, and store the data in a pointer passed in as a parameter. + +The following functions have been renamed: +* SDL_AllocRW() => SDL_CreateRW() +* SDL_FreeRW() => SDL_DestroyRW() +* SDL_ReadBE16() => SDL_ReadU16BE() +* SDL_ReadBE32() => SDL_ReadU32BE() +* SDL_ReadBE64() => SDL_ReadU64BE() +* SDL_ReadLE16() => SDL_ReadU16LE() +* SDL_ReadLE32() => SDL_ReadU32LE() +* SDL_ReadLE64() => SDL_ReadU64LE() +* SDL_WriteBE16() => SDL_WriteU16BE() +* SDL_WriteBE32() => SDL_WriteU32BE() +* SDL_WriteBE64() => SDL_WriteU64BE() +* SDL_WriteLE16() => SDL_WriteU16LE() +* SDL_WriteLE32() => SDL_WriteU32LE() +* SDL_WriteLE64() => SDL_WriteU64LE() + +## SDL_sensor.h + +SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0. + +Rather than iterating over sensors using device index, there is a new function SDL_GetSensors() to get the current list of sensors, and new functions to get information about sensors from their instance ID: +```c +{ + if (SDL_InitSubSystem(SDL_INIT_SENSOR) == 0) { + int i, num_sensors; + SDL_SensorID *sensors = SDL_GetSensors(&num_sensors); + if (sensors) { + for (i = 0; i < num_sensors; ++i) { + SDL_Log("Sensor %" SDL_PRIu32 ": %s, type %d, platform type %d\n", + sensors[i], + SDL_GetSensorInstanceName(sensors[i]), + SDL_GetSensorInstanceType(sensors[i]), + SDL_GetSensorInstanceNonPortableType(sensors[i])); + } + SDL_free(sensors); + } + SDL_QuitSubSystem(SDL_INIT_SENSOR); + } +} +``` + +Removed SDL_SensorGetDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_SENSOR_UPDATE events. + + +The following functions have been renamed: +* SDL_SensorClose() => SDL_CloseSensor() +* SDL_SensorFromInstanceID() => SDL_GetSensorFromInstanceID() +* SDL_SensorGetData() => SDL_GetSensorData() +* SDL_SensorGetInstanceID() => SDL_GetSensorInstanceID() +* SDL_SensorGetName() => SDL_GetSensorName() +* SDL_SensorGetNonPortableType() => SDL_GetSensorNonPortableType() +* SDL_SensorGetType() => SDL_GetSensorType() +* SDL_SensorOpen() => SDL_OpenSensor() +* SDL_SensorUpdate() => SDL_UpdateSensors() + +The following functions have been removed: +* SDL_LockSensors() +* SDL_NumSensors() - replaced with SDL_GetSensors() +* SDL_SensorGetDeviceInstanceID() +* SDL_SensorGetDeviceName() - replaced with SDL_GetSensorInstanceName() +* SDL_SensorGetDeviceNonPortableType() - replaced with SDL_GetSensorInstanceNonPortableType() +* SDL_SensorGetDeviceType() - replaced with SDL_GetSensorInstanceType() +* SDL_UnlockSensors() + +## SDL_shape.h + +This header has been removed. You can create a window with the SDL_WINDOW_TRANSPARENT flag and then render using the alpha channel to achieve a similar effect. You can see an example of this in test/testshape.c + +## SDL_stdinc.h + +The standard C headers like stdio.h and stdlib.h are no longer included, you should include them directly in your project if you use non-SDL C runtime functions. +M_PI is no longer defined in SDL_stdinc.h, you can use the new symbols SDL_PI_D (double) and SDL_PI_F (float) instead. + + +The following functions have been renamed: +* SDL_strtokr() => SDL_strtok_r() + +## SDL_surface.h + +The userdata member of SDL_Surface has been replaced with a more general properties interface, which can be queried with SDL_GetSurfaceProperties() + +Removed unused 'flags' parameter from SDL_ConvertSurface and SDL_ConvertSurfaceFormat. + +SDL_CreateRGBSurface() and SDL_CreateRGBSurfaceWithFormat() have been combined into a new function SDL_CreateSurface(). +SDL_CreateRGBSurfaceFrom() and SDL_CreateRGBSurfaceWithFormatFrom() have been combined into a new function SDL_CreateSurfaceFrom(). + +You can implement the old functions in your own code easily: +```c +SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + return SDL_CreateSurface(width, height, + SDL_GetPixelFormatEnumForMasks(depth, Rmask, Gmask, Bmask, Amask)); +} + +SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format) +{ + return SDL_CreateSurface(width, height, format); +} + +SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + return SDL_CreateSurfaceFrom(pixels, width, height, pitch, + SDL_GetPixelFormatEnumForMasks(depth, Rmask, Gmask, Bmask, Amask)); +} + +SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format) +{ + return SDL_CreateSurfaceFrom(pixels, width, height, pitch, format); +} + +``` + +But if you're migrating your code which uses masks, you probably have a format in mind, possibly one of these: +```c +// Various mask (R, G, B, A) and their corresponding format: +0xFF000000 0x00FF0000 0x0000FF00 0x000000FF => SDL_PIXELFORMAT_RGBA8888 +0x00FF0000 0x0000FF00 0x000000FF 0xFF000000 => SDL_PIXELFORMAT_ARGB8888 +0x0000FF00 0x00FF0000 0xFF000000 0x000000FF => SDL_PIXELFORMAT_BGRA8888 +0x000000FF 0x0000FF00 0x00FF0000 0xFF000000 => SDL_PIXELFORMAT_ABGR8888 +0x0000F800 0x000007E0 0x0000001F 0x00000000 => SDL_PIXELFORMAT_RGB565 +``` + + +The following functions have been renamed: +* SDL_FillRect() => SDL_FillSurfaceRect() +* SDL_FillRects() => SDL_FillSurfaceRects() +* SDL_FreeSurface() => SDL_DestroySurface() +* SDL_GetClipRect() => SDL_GetSurfaceClipRect() +* SDL_GetColorKey() => SDL_GetSurfaceColorKey() +* SDL_HasColorKey() => SDL_SurfaceHasColorKey() +* SDL_HasSurfaceRLE() => SDL_SurfaceHasRLE() +* SDL_LowerBlit() => SDL_BlitSurfaceUnchecked() +* SDL_LowerBlitScaled() => SDL_BlitSurfaceUncheckedScaled() +* SDL_SetClipRect() => SDL_SetSurfaceClipRect() +* SDL_SetColorKey() => SDL_SetSurfaceColorKey() +* SDL_UpperBlit() => SDL_BlitSurface() +* SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled() + +## SDL_system.h + +SDL_WindowsMessageHook has changed signatures so the message may be modified and it can block further message processing. + +SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. + +The following functions have been removed: +* SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property +* SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property +* SDL_RenderGetD3D9Device() - replaced with the "SDL.renderer.d3d9.device" property + +## SDL_syswm.h + +This header has been removed. + +The Windows and X11 events are now available via callbacks which you can set with SDL_SetWindowsMessageHook() and SDL_SetX11EventHook(). + +The information previously available in SDL_GetWindowWMInfo() is now available as window properties, e.g. +```c + HWND hwnd = NULL; + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { + hwnd = info.info.win.window; + } + if (hwnd) { + ... + } +``` +becomes: +```c + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); + if (hwnd) { + ... + } +``` + +## SDL_thread.h + +The following functions have been renamed: +* SDL_TLSCleanup() => SDL_CleanupTLS() +* SDL_TLSCreate() => SDL_CreateTLS() +* SDL_TLSGet() => SDL_GetTLS() +* SDL_TLSSet() => SDL_SetTLS() + +## SDL_timer.h + +SDL_GetTicks() now returns a 64-bit value. Instead of using the SDL_TICKS_PASSED macro, you can directly compare tick values, e.g. +```c +Uint32 deadline = SDL_GetTicks() + 1000; +... +if (SDL_TICKS_PASSED(SDL_GetTicks(), deadline)) { + ... +} +``` +becomes: +```c +Uint64 deadline = SDL_GetTicks() + 1000 +... +if (SDL_GetTicks() >= deadline) { + ... +} +``` + +If you were using this macro for other things besides SDL ticks values, you can define it in your own code as: +```c +#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) +``` + +## SDL_touch.h + +SDL_GetNumTouchFingers() returns a negative error code if there was an error. + +## SDL_version.h + +SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0. + + +## SDL_video.h + +SDL_VideoInit() and SDL_VideoQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_VIDEO, which will properly refcount the subsystems. You can choose a specific video driver using SDL_VIDEO_DRIVER hint. + +Rather than iterating over displays using display index, there is a new function SDL_GetDisplays() to get the current list of displays, and functions which used to take a display index now take SDL_DisplayID, with an invalid ID being 0. +```c +{ + if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0) { + int i, num_displays = 0; + SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); + if (displays) { + for (i = 0; i < num_displays; ++i) { + SDL_DisplayID instance_id = displays[i]; + const char *name = SDL_GetDisplayName(instance_id); + + SDL_Log("Display %" SDL_PRIu32 ": %s\n", instance_id, name ? name : "Unknown"); + } + SDL_free(displays); + } + SDL_QuitSubSystem(SDL_INIT_VIDEO); + } +} +``` + +SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it. + +The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. + +The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag. + +The SDL_WINDOW_SKIP_TASKBAR flag has been replaced by the SDL_WINDOW_UTILITY flag, which has the same functionality. + +SDL_DisplayMode now includes the pixel density which can be greater than 1.0 for display modes that have a higher pixel size than the mode size. You should use SDL_GetWindowSizeInPixels() to get the actual pixel size of the window back buffer. + +The refresh rate in SDL_DisplayMode is now a float. + +Rather than iterating over display modes using an index, there is a new function SDL_GetFullscreenDisplayModes() to get the list of available fullscreen modes on a display. +```c +{ + SDL_DisplayID display = SDL_GetPrimaryDisplay(); + int num_modes = 0; + SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &num_modes); + if (modes) { + for (i = 0; i < num_modes; ++i) { + SDL_DisplayMode *mode = modes[i]; + SDL_Log("Display %" SDL_PRIu32 " mode %d: %dx%d@%gx %gHz\n", + display, i, mode->w, mode->h, mode->pixel_density, mode->refresh_rate); + } + SDL_free(modes); + } +} +``` + +SDL_GetDesktopDisplayMode() and SDL_GetCurrentDisplayMode() return pointers to display modes rather than filling in application memory. + +Windows now have an explicit fullscreen mode that is set, using SDL_SetWindowFullscreenMode(). The fullscreen mode for a window can be queried with SDL_GetWindowFullscreenMode(), which returns a pointer to the mode, or NULL if the window will be fullscreen desktop. SDL_SetWindowFullscreen() just takes a boolean value, setting the correct fullscreen state based on the selected mode. + +SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, and you can call SDL_GetWindowFullscreenMode() to see whether an exclusive fullscreen mode will be used or the fullscreen desktop mode will be used when the window is fullscreen. + +SDL_SetWindowBrightness and SDL_SetWindowGammaRamp have been removed from the API, because they interact poorly with modern operating systems and aren't able to limit their effects to the SDL window. + +Programs which have access to shaders can implement more robust versions of those functions using custom shader code rendered as a post-process effect. + +Removed SDL_GL_CONTEXT_EGL from OpenGL configuration attributes. You can instead use `SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);` + +SDL_GL_GetProcAddress() and SDL_EGL_GetProcAddress() now return `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior. + +SDL_GL_SwapWindow() returns 0 if the function succeeds or a negative error code if there was an error. + +SDL_GL_GetSwapInterval() takes the interval as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. + +SDL_GL_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. + +The SDL_WINDOW_TOOLTIP and SDL_WINDOW_POPUP_MENU window flags are now supported on Windows, Mac (Cocoa), X11, and Wayland. Creating windows with these flags must happen via the `SDL_CreatePopupWindow()` function. This function requires passing in the handle to a valid parent window for the popup, and the popup window is positioned relative to the parent. + +The following functions have been renamed: +* SDL_GetClosestDisplayMode() => SDL_GetClosestFullscreenDisplayMode() +* SDL_GetDisplayOrientation() => SDL_GetCurrentDisplayOrientation() +* SDL_GetPointDisplayIndex() => SDL_GetDisplayForPoint() +* SDL_GetRectDisplayIndex() => SDL_GetDisplayForRect() +* SDL_GetWindowDisplayIndex() => SDL_GetDisplayForWindow() +* SDL_GetWindowDisplayMode() => SDL_GetWindowFullscreenMode() +* SDL_IsScreenSaverEnabled() => SDL_ScreenSaverEnabled() +* SDL_SetWindowDisplayMode() => SDL_SetWindowFullscreenMode() + +The following functions have been removed: +* SDL_GetClosestFullscreenDisplayMode() +* SDL_GetDisplayDPI() - not reliable across platforms, approximately replaced by multiplying `display_scale` in the structure returned by SDL_GetDesktopDisplayMode() times 160 on iPhone and Android, and 96 on other platforms. +* SDL_GetDisplayMode() +* SDL_GetNumDisplayModes() - replaced with SDL_GetFullscreenDisplayModes() +* SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() +* SDL_GetWindowData() - use SDL_GetWindowProperties() instead +* SDL_SetWindowData() - use SDL_GetWindowProperties() instead +* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window + +SDL_Window id type is named SDL_WindowID + +The following symbols have been renamed: +* SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY +* SDL_WINDOW_INPUT_GRABBED => SDL_WINDOW_MOUSE_GRABBED + +## SDL_vulkan.h + +SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no longer makes the app allocate query/allocate space for the result, instead returning a static const internal string. + +SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr. + +SDL_Vulkan_CreateSurface() now takes a VkAllocationCallbacks pointer as its third parameter. If you don't have an allocator to supply, pass a NULL here to use the system default allocator (SDL2 always used the system default allocator here). + +SDL_Vulkan_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. diff --git a/docs/README-n3ds.md b/docs/README-n3ds.md index 80da3802d4253..8f95473909196 100644 --- a/docs/README-n3ds.md +++ b/docs/README-n3ds.md @@ -1,28 +1,28 @@ -# Nintendo 3DS - -SDL port for the Nintendo 3DS [Homebrew toolchain](https://devkitpro.org/) contributed by: - -- [Pierre Wendling](https://github.com/FtZPetruska) - -Credits to: - -- The awesome people who ported SDL to other homebrew platforms. -- The Devkitpro team for making all the tools necessary to achieve this. - -## Building - -To build for the Nintendo 3DS, make sure you have devkitARM and cmake installed and run: - -```bash -cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/3DS.cmake" -DCMAKE_BUILD_TYPE=Release -cmake --build build -cmake --install build -``` - -## Notes - -- Currently only software rendering is supported. -- SDL3_main should be used to ensure ROMFS is enabled - this is done with `#include ` in the source file that contains your main function. -- By default, the extra L2 cache and higher clock speeds of the New 2/3DS lineup are enabled. If you wish to turn it off, use `osSetSpeedupEnable(false)` in your main function. -- `SDL_GetBasePath` returns the romfs root instead of the executable's directory. -- The Nintendo 3DS uses a cooperative threading model on a single core, meaning a thread will never yield unless done manually through the `SDL_Delay` functions, or blocking waits (`SDL_LockMutex`, `SDL_WaitSemaphore`, `SDL_WaitCondition`, `SDL_WaitThread`). To avoid starving other threads, `SDL_TryWaitSemaphore` and `SDL_WaitSemaphoreTimeout` will yield if they fail to acquire the semaphore, see https://github.com/libsdl-org/SDL/pull/6776 for more information. +# Nintendo 3DS + +SDL port for the Nintendo 3DS [Homebrew toolchain](https://devkitpro.org/) contributed by: + +- [Pierre Wendling](https://github.com/FtZPetruska) + +Credits to: + +- The awesome people who ported SDL to other homebrew platforms. +- The Devkitpro team for making all the tools necessary to achieve this. + +## Building + +To build for the Nintendo 3DS, make sure you have devkitARM and cmake installed and run: + +```bash +cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/3DS.cmake" -DCMAKE_BUILD_TYPE=Release +cmake --build build +cmake --install build +``` + +## Notes + +- Currently only software rendering is supported. +- SDL3_main should be used to ensure ROMFS is enabled - this is done with `#include ` in the source file that contains your main function. +- By default, the extra L2 cache and higher clock speeds of the New 2/3DS lineup are enabled. If you wish to turn it off, use `osSetSpeedupEnable(false)` in your main function. +- `SDL_GetBasePath` returns the romfs root instead of the executable's directory. +- The Nintendo 3DS uses a cooperative threading model on a single core, meaning a thread will never yield unless done manually through the `SDL_Delay` functions, or blocking waits (`SDL_LockMutex`, `SDL_WaitSemaphore`, `SDL_WaitCondition`, `SDL_WaitThread`). To avoid starving other threads, `SDL_TryWaitSemaphore` and `SDL_WaitSemaphoreTimeout` will yield if they fail to acquire the semaphore, see https://github.com/libsdl-org/SDL/pull/6776 for more information. diff --git a/docs/README-ngage.md b/docs/README-ngage.md index ec4a7121a3799..363760b992aec 100644 --- a/docs/README-ngage.md +++ b/docs/README-ngage.md @@ -1,44 +1,44 @@ -Nokia N-Gage -============ - -SDL port for Symbian S60v1 and v2 with a main focus on the Nokia N-Gage -(Classic and QD) by [Michael Fitzmayer](https://github.com/mupfdev). - -Compiling ---------- - -SDL is part of the [N-Gage SDK.](https://github.com/ngagesdk) project. -The library is included in the -[toolchain](https://github.com/ngagesdk/ngage-toolchain) as a -sub-module. - -A complete example project based on SDL can be found in the GitHub -account of the SDK: [Wordle](https://github.com/ngagesdk/wordle). - -Current level of implementation -------------------------------- - -The video driver currently provides full screen video support with -keyboard input. - -At the moment only the software renderer works. - -Audio is not yet implemented. - -Acknowledgements ----------------- - -Thanks to Hannu Viitala, Kimmo Kinnunen and Markus Mertama for the -valuable insight into Symbian programming. Without the SDL 1.2 port -which was specially developed for CDoom (Doom for the Nokia 9210), this -adaptation would not have been possible. - -I would like to thank my friends -[Razvan](https://twitter.com/bewarerazvan) and [Dan -Whelan](https://danwhelan.ie/), for their continuous support. Without -you and the [N-Gage community](https://discord.gg/dbUzqJ26vs), I would -have lost my patience long ago. - -Last but not least, I would like to thank the development team of -[EKA2L1](https://12z1.com/) (an experimental Symbian OS emulator). Your -patience and support in troubleshooting helped me a lot. +Nokia N-Gage +============ + +SDL port for Symbian S60v1 and v2 with a main focus on the Nokia N-Gage +(Classic and QD) by [Michael Fitzmayer](https://github.com/mupfdev). + +Compiling +--------- + +SDL is part of the [N-Gage SDK.](https://github.com/ngagesdk) project. +The library is included in the +[toolchain](https://github.com/ngagesdk/ngage-toolchain) as a +sub-module. + +A complete example project based on SDL can be found in the GitHub +account of the SDK: [Wordle](https://github.com/ngagesdk/wordle). + +Current level of implementation +------------------------------- + +The video driver currently provides full screen video support with +keyboard input. + +At the moment only the software renderer works. + +Audio is not yet implemented. + +Acknowledgements +---------------- + +Thanks to Hannu Viitala, Kimmo Kinnunen and Markus Mertama for the +valuable insight into Symbian programming. Without the SDL 1.2 port +which was specially developed for CDoom (Doom for the Nokia 9210), this +adaptation would not have been possible. + +I would like to thank my friends +[Razvan](https://twitter.com/bewarerazvan) and [Dan +Whelan](https://danwhelan.ie/), for their continuous support. Without +you and the [N-Gage community](https://discord.gg/dbUzqJ26vs), I would +have lost my patience long ago. + +Last but not least, I would like to thank the development team of +[EKA2L1](https://12z1.com/) (an experimental Symbian OS emulator). Your +patience and support in troubleshooting helped me a lot. diff --git a/docs/README-platforms.md b/docs/README-platforms.md index 711557dc046f4..14454ec5d5c46 100644 --- a/docs/README-platforms.md +++ b/docs/README-platforms.md @@ -1,8 +1,8 @@ -Platforms -========= - -We maintain the list of supported platforms on our wiki now, and how to -build and install SDL for those platforms: - - https://wiki.libsdl.org/Installation - +Platforms +========= + +We maintain the list of supported platforms on our wiki now, and how to +build and install SDL for those platforms: + + https://wiki.libsdl.org/Installation + diff --git a/docs/README-porting.md b/docs/README-porting.md index e2e4d0faa77f4..db6b6141329d5 100644 --- a/docs/README-porting.md +++ b/docs/README-porting.md @@ -1,65 +1,65 @@ -Porting -======= - -* Porting To A New Platform - - The first thing you have to do when porting to a new platform, is look at -include/SDL_platform.h and create an entry there for your operating system. -The standard format is "__PLATFORM__", where PLATFORM is the name of the OS. -Ideally SDL_platform_defines.h will be able to auto-detect the system it's building -on based on C preprocessor symbols. - -There are two basic ways of building SDL at the moment: - -1. CMake: cmake -S . -B build && cmake --build build && cmake --install install - - If you have a system that supports CMake, then you might try this. Edit CMakeLists.txt, - - take a look at the large section labelled: - - "Platform-specific options and settings!" - - Add a section for your platform, and then re-run 'cmake -S . -B build' and build! - -2. Using an IDE: - - If you're using an IDE or other non-configure build system, you'll probably want to create a custom `SDL_build_config.h` for your platform. Edit `include/build_config/SDL_build_config.h`, add a section for your platform, and create a custom `SDL_build_config_{platform}.h`, based on `SDL_build_config_minimal.h` and `SDL_build_config.h.cmake` - - Add the top level include directory to the header search path, and then add - the following sources to the project: - - src/*.c - src/atomic/*.c - src/audio/*.c - src/cpuinfo/*.c - src/events/*.c - src/file/*.c - src/haptic/*.c - src/joystick/*.c - src/power/*.c - src/render/*.c - src/render/software/*.c - src/stdlib/*.c - src/thread/*.c - src/timer/*.c - src/video/*.c - src/audio/disk/*.c - src/audio/dummy/*.c - src/filesystem/dummy/*.c - src/video/dummy/*.c - src/haptic/dummy/*.c - src/joystick/dummy/*.c - src/thread/generic/*.c - src/timer/dummy/*.c - src/loadso/dummy/*.c - - -Once you have a working library without any drivers, you can go back to each -of the major subsystems and start implementing drivers for your platform. - -If you have any questions, don't hesitate to ask on the SDL mailing list: - http://www.libsdl.org/mailing-list.php - -Enjoy! - Sam Lantinga (slouken@libsdl.org) - +Porting +======= + +* Porting To A New Platform + + The first thing you have to do when porting to a new platform, is look at +include/SDL_platform.h and create an entry there for your operating system. +The standard format is "__PLATFORM__", where PLATFORM is the name of the OS. +Ideally SDL_platform_defines.h will be able to auto-detect the system it's building +on based on C preprocessor symbols. + +There are two basic ways of building SDL at the moment: + +1. CMake: cmake -S . -B build && cmake --build build && cmake --install install + + If you have a system that supports CMake, then you might try this. Edit CMakeLists.txt, + + take a look at the large section labelled: + + "Platform-specific options and settings!" + + Add a section for your platform, and then re-run 'cmake -S . -B build' and build! + +2. Using an IDE: + + If you're using an IDE or other non-configure build system, you'll probably want to create a custom `SDL_build_config.h` for your platform. Edit `include/build_config/SDL_build_config.h`, add a section for your platform, and create a custom `SDL_build_config_{platform}.h`, based on `SDL_build_config_minimal.h` and `SDL_build_config.h.cmake` + + Add the top level include directory to the header search path, and then add + the following sources to the project: + + src/*.c + src/atomic/*.c + src/audio/*.c + src/cpuinfo/*.c + src/events/*.c + src/file/*.c + src/haptic/*.c + src/joystick/*.c + src/power/*.c + src/render/*.c + src/render/software/*.c + src/stdlib/*.c + src/thread/*.c + src/timer/*.c + src/video/*.c + src/audio/disk/*.c + src/audio/dummy/*.c + src/filesystem/dummy/*.c + src/video/dummy/*.c + src/haptic/dummy/*.c + src/joystick/dummy/*.c + src/thread/generic/*.c + src/timer/dummy/*.c + src/loadso/dummy/*.c + + +Once you have a working library without any drivers, you can go back to each +of the major subsystems and start implementing drivers for your platform. + +If you have any questions, don't hesitate to ask on the SDL mailing list: + http://www.libsdl.org/mailing-list.php + +Enjoy! + Sam Lantinga (slouken@libsdl.org) + diff --git a/docs/README-ps2.md b/docs/README-ps2.md index 579ad9860209a..ade0b6d850395 100644 --- a/docs/README-ps2.md +++ b/docs/README-ps2.md @@ -1,51 +1,51 @@ -PS2 -====== -SDL port for the Sony Playstation 2 contributed by: -- Francisco Javier Trujillo Mata - - -Credit to - - The guys that ported SDL to PSP & Vita because I'm taking them as reference. - - David G. F. for helping me with several issues and tests. - -## Building -To build SDL library for the PS2, make sure you have the latest PS2Dev status and run: -```bash -cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$PS2DEV/ps2sdk/ps2dev.cmake -cmake --build build -cmake --install build -``` - -## Hints -The PS2 port has a special Hint for having a dynamic VSYNC. The Hint is `SDL_HINT_PS2_DYNAMIC_VSYNC`. -If you enabled the dynamic vsync having as well `SDL_RENDERER_PRESENTVSYNC` enabled, then if the app is not able to run at 60 FPS, automatically the `vsync` will be disabled having a better performance, instead of dropping FPS to 30. - -## Notes -If you trying to debug a SDL app through [ps2client](https://github.com/ps2dev/ps2client) you need to avoid the IOP reset, otherwise you will lose the connection with your computer. -So to avoid the reset of the IOP CPU, you need to call to the macro `SDL_PS2_SKIP_IOP_RESET();`. -It could be something similar as: -```c -..... - -SDL_PS2_SKIP_IOP_RESET(); - -int main(int argc, char *argv[]) -{ -..... -``` -For a release binary is recommendable to reset the IOP always. - -Remember to do a clean compilation everytime you enable or disable the `SDL_PS2_SKIP_IOP_RESET` otherwise the change won't be reflected. - -## Getting PS2 Dev -[Installing PS2 Dev](https://github.com/ps2dev/ps2dev) - -## Running on PCSX2 Emulator -[PCSX2](https://github.com/PCSX2/pcsx2) - -[More PCSX2 information](https://pcsx2.net/) - -## To Do -- PS2 Screen Keyboard -- Dialogs -- Others +PS2 +====== +SDL port for the Sony Playstation 2 contributed by: +- Francisco Javier Trujillo Mata + + +Credit to + - The guys that ported SDL to PSP & Vita because I'm taking them as reference. + - David G. F. for helping me with several issues and tests. + +## Building +To build SDL library for the PS2, make sure you have the latest PS2Dev status and run: +```bash +cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$PS2DEV/ps2sdk/ps2dev.cmake +cmake --build build +cmake --install build +``` + +## Hints +The PS2 port has a special Hint for having a dynamic VSYNC. The Hint is `SDL_HINT_PS2_DYNAMIC_VSYNC`. +If you enabled the dynamic vsync having as well `SDL_RENDERER_PRESENTVSYNC` enabled, then if the app is not able to run at 60 FPS, automatically the `vsync` will be disabled having a better performance, instead of dropping FPS to 30. + +## Notes +If you trying to debug a SDL app through [ps2client](https://github.com/ps2dev/ps2client) you need to avoid the IOP reset, otherwise you will lose the connection with your computer. +So to avoid the reset of the IOP CPU, you need to call to the macro `SDL_PS2_SKIP_IOP_RESET();`. +It could be something similar as: +```c +..... + +SDL_PS2_SKIP_IOP_RESET(); + +int main(int argc, char *argv[]) +{ +..... +``` +For a release binary is recommendable to reset the IOP always. + +Remember to do a clean compilation everytime you enable or disable the `SDL_PS2_SKIP_IOP_RESET` otherwise the change won't be reflected. + +## Getting PS2 Dev +[Installing PS2 Dev](https://github.com/ps2dev/ps2dev) + +## Running on PCSX2 Emulator +[PCSX2](https://github.com/PCSX2/pcsx2) + +[More PCSX2 information](https://pcsx2.net/) + +## To Do +- PS2 Screen Keyboard +- Dialogs +- Others diff --git a/docs/README-psp.md b/docs/README-psp.md index e10f5c2dd80ae..c010c6093ee24 100644 --- a/docs/README-psp.md +++ b/docs/README-psp.md @@ -1,36 +1,36 @@ -PSP -====== -SDL port for the Sony PSP contributed by: -- Captian Lex -- Francisco Javier Trujillo Mata -- Wouter Wijsman - - -Credit to - Marcus R.Brown,Jim Paris,Matthew H for the original SDL 1.2 for PSP - Geecko for his PSP GU lib "Glib2d" - -## Building -To build SDL library for the PSP, make sure you have the latest PSPDev status and run: -```bash -cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake -cmake --build build -cmake --install build -``` - - -## Getting PSP Dev -[Installing PSP Dev](https://github.com/pspdev/pspdev) - -## Running on PPSSPP Emulator -[PPSSPP](https://github.com/hrydgard/ppsspp) - -[Build Instructions](https://github.com/hrydgard/ppsspp/wiki/Build-instructions) - - -## Compiling a HelloWorld -[PSP Hello World](https://psp-dev.org/doku.php?id=tutorial:hello_world) - -## To Do -- PSP Screen Keyboard -- Dialogs +PSP +====== +SDL port for the Sony PSP contributed by: +- Captian Lex +- Francisco Javier Trujillo Mata +- Wouter Wijsman + + +Credit to + Marcus R.Brown,Jim Paris,Matthew H for the original SDL 1.2 for PSP + Geecko for his PSP GU lib "Glib2d" + +## Building +To build SDL library for the PSP, make sure you have the latest PSPDev status and run: +```bash +cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake +cmake --build build +cmake --install build +``` + + +## Getting PSP Dev +[Installing PSP Dev](https://github.com/pspdev/pspdev) + +## Running on PPSSPP Emulator +[PPSSPP](https://github.com/hrydgard/ppsspp) + +[Build Instructions](https://github.com/hrydgard/ppsspp/wiki/Build-instructions) + + +## Compiling a HelloWorld +[PSP Hello World](https://psp-dev.org/doku.php?id=tutorial:hello_world) + +## To Do +- PSP Screen Keyboard +- Dialogs diff --git a/docs/README-raspberrypi.md b/docs/README-raspberrypi.md index 94093f023cd31..9984ec6d1da2f 100644 --- a/docs/README-raspberrypi.md +++ b/docs/README-raspberrypi.md @@ -1,180 +1,180 @@ -Raspberry Pi -============ - -Requirements: - -Raspbian (other Linux distros may work as well). - -Features --------- - -* Works without X11 -* Hardware accelerated OpenGL ES 2.x -* Sound via ALSA -* Input (mouse/keyboard/joystick) via EVDEV -* Hotplugging of input devices via UDEV - - -Raspbian Build Dependencies ---------------------------- - -sudo apt-get install libudev-dev libasound2-dev libdbus-1-dev - -You also need the VideoCore binary stuff that ships in /opt/vc for EGL and -OpenGL ES 2.x, it usually comes pre-installed, but in any case: - -sudo apt-get install libraspberrypi0 libraspberrypi-bin libraspberrypi-dev - - -NEON ----- - -If your Pi has NEON support, make sure you add -mfpu=neon to your CFLAGS so -that SDL will select some otherwise-disabled highly-optimized code. The -original Pi units don't have NEON, the Pi2 probably does, and the Pi3 -definitely does. - - -Cross compiling from x86 Linux ------------------------------- - -To cross compile SDL for Raspbian from your desktop machine, you'll need a -Raspbian system root and the cross compilation tools. We'll assume these tools -will be placed in /opt/rpi-tools - - sudo git clone --depth 1 https://github.com/raspberrypi/tools /opt/rpi-tools - -You'll also need a Raspbian binary image. -Get it from: http://downloads.raspberrypi.org/raspbian_latest -After unzipping, you'll get file with a name like: "-wheezy-raspbian.img" -Let's assume the sysroot will be built in /opt/rpi-sysroot. - - export SYSROOT=/opt/rpi-sysroot - sudo kpartx -a -v .img - sudo mount -o loop /dev/mapper/loop0p2 /mnt - sudo cp -r /mnt $SYSROOT - sudo apt-get install qemu binfmt-support qemu-user-static - sudo cp /usr/bin/qemu-arm-static $SYSROOT/usr/bin - sudo mount --bind /dev $SYSROOT/dev - sudo mount --bind /proc $SYSROOT/proc - sudo mount --bind /sys $SYSROOT/sys - -Now, before chrooting into the ARM sysroot, you'll need to apply a workaround, -edit $SYSROOT/etc/ld.so.preload and comment out all lines in it. - - sudo chroot $SYSROOT - apt-get install libudev-dev libasound2-dev libdbus-1-dev libraspberrypi0 libraspberrypi-bin libraspberrypi-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxss-dev - exit - sudo umount $SYSROOT/dev - sudo umount $SYSROOT/proc - sudo umount $SYSROOT/sys - sudo umount /mnt - -There's one more fix required, as the libdl.so symlink uses an absolute path -which doesn't quite work in our setup. - - sudo rm -rf $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so - sudo ln -s ../../../lib/arm-linux-gnueabihf/libdl.so.2 $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so - -The final step is compiling SDL itself. - - export CC="/opt/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc --sysroot=$SYSROOT -I$SYSROOT/opt/vc/include -I$SYSROOT/usr/include -I$SYSROOT/opt/vc/include/interface/vcos/pthreads -I$SYSROOT/opt/vc/include/interface/vmcs_host/linux" - cd - mkdir -p build;cd build - LDFLAGS="-L$SYSROOT/opt/vc/lib" ../configure --with-sysroot=$SYSROOT --host=arm-raspberry-linux-gnueabihf --prefix=$PWD/rpi-sdl3-installed --disable-pulseaudio --disable-esd - make - make install - -To be able to deploy this to /usr/local in the Raspbian system you need to fix up a few paths: - - perl -w -pi -e "s#$PWD/rpi-sdl3-installed#/usr/local#g;" ./rpi-sdl3-installed/lib/libSDL3.la ./rpi-sdl3-installed/lib/pkgconfig/sdl3.pc - -Apps don't work or poor video/audio performance ------------------------------------------------ - -If you get sound problems, buffer underruns, etc, run "sudo rpi-update" to -update the RPi's firmware. Note that doing so will fix these problems, but it -will also render the CMA - Dynamic Memory Split functionality useless. - -Also, by default the Raspbian distro configures the GPU RAM at 64MB, this is too -low in general, specially if a 1080p TV is hooked up. - -See here how to configure this setting: http://elinux.org/RPiconfig - -Using a fixed gpu_mem=128 is the best option (specially if you updated the -firmware, using CMA probably won't work, at least it's the current case). - -No input --------- - -Make sure you belong to the "input" group. - - sudo usermod -aG input `whoami` - -No HDMI Audio -------------- - -If you notice that ALSA works but there's no audio over HDMI, try adding: - - hdmi_drive=2 - -to your config.txt file and reboot. - -Reference: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=5062 - -Text Input API support ----------------------- - -The Text Input API is supported, with translation of scan codes done via the -kernel symbol tables. For this to work, SDL needs access to a valid console. -If you notice there's no SDL_EVENT_TEXT_INPUT message being emitted, double check that -your app has read access to one of the following: - -* /proc/self/fd/0 -* /dev/tty -* /dev/tty[0...6] -* /dev/vc/0 -* /dev/console - -This is usually not a problem if you run from the physical terminal (as opposed -to running from a pseudo terminal, such as via SSH). If running from a PTS, a -quick workaround is to run your app as root or add yourself to the tty group, -then re-login to the system. - - sudo usermod -aG tty `whoami` - -The keyboard layout used by SDL is the same as the one the kernel uses. -To configure the layout on Raspbian: - - sudo dpkg-reconfigure keyboard-configuration - -To configure the locale, which controls which keys are interpreted as letters, -this determining the CAPS LOCK behavior: - - sudo dpkg-reconfigure locales - - -OpenGL problems ---------------- - -If you have desktop OpenGL headers installed at build time in your RPi or cross -compilation environment, support for it will be built in. However, the chipset -does not actually have support for it, which causes issues in certain SDL apps -since the presence of OpenGL support supersedes the ES/ES2 variants. -The workaround is to disable OpenGL at configuration time: - - ./configure --disable-video-opengl - -Or if the application uses the Render functions, you can use the SDL_RENDER_DRIVER -environment variable: - - export SDL_RENDER_DRIVER=opengles2 - -Notes ------ - -* When launching apps remotely (via SSH), SDL can prevent local keystrokes from - leaking into the console only if it has root privileges. Launching apps locally - does not suffer from this issue. - - +Raspberry Pi +============ + +Requirements: + +Raspbian (other Linux distros may work as well). + +Features +-------- + +* Works without X11 +* Hardware accelerated OpenGL ES 2.x +* Sound via ALSA +* Input (mouse/keyboard/joystick) via EVDEV +* Hotplugging of input devices via UDEV + + +Raspbian Build Dependencies +--------------------------- + +sudo apt-get install libudev-dev libasound2-dev libdbus-1-dev + +You also need the VideoCore binary stuff that ships in /opt/vc for EGL and +OpenGL ES 2.x, it usually comes pre-installed, but in any case: + +sudo apt-get install libraspberrypi0 libraspberrypi-bin libraspberrypi-dev + + +NEON +---- + +If your Pi has NEON support, make sure you add -mfpu=neon to your CFLAGS so +that SDL will select some otherwise-disabled highly-optimized code. The +original Pi units don't have NEON, the Pi2 probably does, and the Pi3 +definitely does. + + +Cross compiling from x86 Linux +------------------------------ + +To cross compile SDL for Raspbian from your desktop machine, you'll need a +Raspbian system root and the cross compilation tools. We'll assume these tools +will be placed in /opt/rpi-tools + + sudo git clone --depth 1 https://github.com/raspberrypi/tools /opt/rpi-tools + +You'll also need a Raspbian binary image. +Get it from: http://downloads.raspberrypi.org/raspbian_latest +After unzipping, you'll get file with a name like: "-wheezy-raspbian.img" +Let's assume the sysroot will be built in /opt/rpi-sysroot. + + export SYSROOT=/opt/rpi-sysroot + sudo kpartx -a -v .img + sudo mount -o loop /dev/mapper/loop0p2 /mnt + sudo cp -r /mnt $SYSROOT + sudo apt-get install qemu binfmt-support qemu-user-static + sudo cp /usr/bin/qemu-arm-static $SYSROOT/usr/bin + sudo mount --bind /dev $SYSROOT/dev + sudo mount --bind /proc $SYSROOT/proc + sudo mount --bind /sys $SYSROOT/sys + +Now, before chrooting into the ARM sysroot, you'll need to apply a workaround, +edit $SYSROOT/etc/ld.so.preload and comment out all lines in it. + + sudo chroot $SYSROOT + apt-get install libudev-dev libasound2-dev libdbus-1-dev libraspberrypi0 libraspberrypi-bin libraspberrypi-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxss-dev + exit + sudo umount $SYSROOT/dev + sudo umount $SYSROOT/proc + sudo umount $SYSROOT/sys + sudo umount /mnt + +There's one more fix required, as the libdl.so symlink uses an absolute path +which doesn't quite work in our setup. + + sudo rm -rf $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so + sudo ln -s ../../../lib/arm-linux-gnueabihf/libdl.so.2 $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so + +The final step is compiling SDL itself. + + export CC="/opt/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc --sysroot=$SYSROOT -I$SYSROOT/opt/vc/include -I$SYSROOT/usr/include -I$SYSROOT/opt/vc/include/interface/vcos/pthreads -I$SYSROOT/opt/vc/include/interface/vmcs_host/linux" + cd + mkdir -p build;cd build + LDFLAGS="-L$SYSROOT/opt/vc/lib" ../configure --with-sysroot=$SYSROOT --host=arm-raspberry-linux-gnueabihf --prefix=$PWD/rpi-sdl3-installed --disable-pulseaudio --disable-esd + make + make install + +To be able to deploy this to /usr/local in the Raspbian system you need to fix up a few paths: + + perl -w -pi -e "s#$PWD/rpi-sdl3-installed#/usr/local#g;" ./rpi-sdl3-installed/lib/libSDL3.la ./rpi-sdl3-installed/lib/pkgconfig/sdl3.pc + +Apps don't work or poor video/audio performance +----------------------------------------------- + +If you get sound problems, buffer underruns, etc, run "sudo rpi-update" to +update the RPi's firmware. Note that doing so will fix these problems, but it +will also render the CMA - Dynamic Memory Split functionality useless. + +Also, by default the Raspbian distro configures the GPU RAM at 64MB, this is too +low in general, specially if a 1080p TV is hooked up. + +See here how to configure this setting: http://elinux.org/RPiconfig + +Using a fixed gpu_mem=128 is the best option (specially if you updated the +firmware, using CMA probably won't work, at least it's the current case). + +No input +-------- + +Make sure you belong to the "input" group. + + sudo usermod -aG input `whoami` + +No HDMI Audio +------------- + +If you notice that ALSA works but there's no audio over HDMI, try adding: + + hdmi_drive=2 + +to your config.txt file and reboot. + +Reference: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=5062 + +Text Input API support +---------------------- + +The Text Input API is supported, with translation of scan codes done via the +kernel symbol tables. For this to work, SDL needs access to a valid console. +If you notice there's no SDL_EVENT_TEXT_INPUT message being emitted, double check that +your app has read access to one of the following: + +* /proc/self/fd/0 +* /dev/tty +* /dev/tty[0...6] +* /dev/vc/0 +* /dev/console + +This is usually not a problem if you run from the physical terminal (as opposed +to running from a pseudo terminal, such as via SSH). If running from a PTS, a +quick workaround is to run your app as root or add yourself to the tty group, +then re-login to the system. + + sudo usermod -aG tty `whoami` + +The keyboard layout used by SDL is the same as the one the kernel uses. +To configure the layout on Raspbian: + + sudo dpkg-reconfigure keyboard-configuration + +To configure the locale, which controls which keys are interpreted as letters, +this determining the CAPS LOCK behavior: + + sudo dpkg-reconfigure locales + + +OpenGL problems +--------------- + +If you have desktop OpenGL headers installed at build time in your RPi or cross +compilation environment, support for it will be built in. However, the chipset +does not actually have support for it, which causes issues in certain SDL apps +since the presence of OpenGL support supersedes the ES/ES2 variants. +The workaround is to disable OpenGL at configuration time: + + ./configure --disable-video-opengl + +Or if the application uses the Render functions, you can use the SDL_RENDER_DRIVER +environment variable: + + export SDL_RENDER_DRIVER=opengles2 + +Notes +----- + +* When launching apps remotely (via SSH), SDL can prevent local keystrokes from + leaking into the console only if it has root privileges. Launching apps locally + does not suffer from this issue. + + diff --git a/docs/README-riscos.md b/docs/README-riscos.md index 48304220601b7..5af80a7f31a0a 100644 --- a/docs/README-riscos.md +++ b/docs/README-riscos.md @@ -1,35 +1,35 @@ -RISC OS -======= - -Requirements: - -* RISC OS 3.5 or later. -* [SharedUnixLibrary](http://www.riscos.info/packages/LibraryDetails.html#SharedUnixLibraryarm). -* [DigitalRenderer](http://www.riscos.info/packages/LibraryDetails.html#DRendererarm), for audio support. -* [Iconv](http://www.netsurf-browser.org/projects/iconv/), for `SDL_iconv` and related functions. - - -Compiling: ----------- - -Currently, SDL for RISC OS only supports compiling with GCCSDK under Linux. - -The following commands can be used to build SDL for RISC OS using CMake: - - cmake -Bbuild-riscos -DCMAKE_TOOLCHAIN_FILE=$GCCSDK_INSTALL_ENV/toolchain-riscos.cmake -DRISCOS=ON -DCMAKE_INSTALL_PREFIX=$GCCSDK_INSTALL_ENV -DCMAKE_BUILD_TYPE=Release - cmake --build build-riscos - cmake --install build-riscos - -When using GCCSDK 4.7.4 release 6 or earlier versions, the builtin atomic functions are broken, meaning it's currently necessary to compile with `-DSDL_GCC_ATOMICS=OFF` using CMake. Newer versions of GCCSDK don't have this problem. - - -Current level of implementation -------------------------------- - -The video driver currently provides full screen video support with keyboard and mouse input. Windowed mode is not yet supported, but is planned in the future. Only software rendering is supported. - -The filesystem APIs return either Unix-style paths or RISC OS-style paths based on the value of the `__riscosify_control` symbol, as is standard for UnixLib functions. - -The audio, loadso, thread and timer APIs are currently provided by UnixLib. - -The joystick, locale and power APIs are not yet implemented. +RISC OS +======= + +Requirements: + +* RISC OS 3.5 or later. +* [SharedUnixLibrary](http://www.riscos.info/packages/LibraryDetails.html#SharedUnixLibraryarm). +* [DigitalRenderer](http://www.riscos.info/packages/LibraryDetails.html#DRendererarm), for audio support. +* [Iconv](http://www.netsurf-browser.org/projects/iconv/), for `SDL_iconv` and related functions. + + +Compiling: +---------- + +Currently, SDL for RISC OS only supports compiling with GCCSDK under Linux. + +The following commands can be used to build SDL for RISC OS using CMake: + + cmake -Bbuild-riscos -DCMAKE_TOOLCHAIN_FILE=$GCCSDK_INSTALL_ENV/toolchain-riscos.cmake -DRISCOS=ON -DCMAKE_INSTALL_PREFIX=$GCCSDK_INSTALL_ENV -DCMAKE_BUILD_TYPE=Release + cmake --build build-riscos + cmake --install build-riscos + +When using GCCSDK 4.7.4 release 6 or earlier versions, the builtin atomic functions are broken, meaning it's currently necessary to compile with `-DSDL_GCC_ATOMICS=OFF` using CMake. Newer versions of GCCSDK don't have this problem. + + +Current level of implementation +------------------------------- + +The video driver currently provides full screen video support with keyboard and mouse input. Windowed mode is not yet supported, but is planned in the future. Only software rendering is supported. + +The filesystem APIs return either Unix-style paths or RISC OS-style paths based on the value of the `__riscosify_control` symbol, as is standard for UnixLib functions. + +The audio, loadso, thread and timer APIs are currently provided by UnixLib. + +The joystick, locale and power APIs are not yet implemented. diff --git a/docs/README-touch.md b/docs/README-touch.md index 94d4e7233d398..569feb6063048 100644 --- a/docs/README-touch.md +++ b/docs/README-touch.md @@ -1,81 +1,81 @@ -Touch -=========================================================================== -System Specific Notes -=========================================================================== -Linux: -The linux touch system is currently based off event streams, and proc/bus/devices. The active user must be given permissions to read /dev/input/TOUCHDEVICE, where TOUCHDEVICE is the event stream for your device. Currently only Wacom tablets are supported. If you have an unsupported tablet contact me at jim.tla+sdl_touch@gmail.com and I will help you get support for it. - -Mac: -The Mac and iPhone APIs are pretty. If your touch device supports them then you'll be fine. If it doesn't, then there isn't much we can do. - -iPhone: -Works out of box. - -Windows: -Unfortunately there is no windows support as of yet. Support for Windows 7 is planned, but we currently have no way to test. If you have a Windows 7 WM_TOUCH supported device, and are willing to help test please contact me at jim.tla+sdl_touch@gmail.com - -=========================================================================== -Events -=========================================================================== -SDL_EVENT_FINGER_DOWN: -Sent when a finger (or stylus) is placed on a touch device. -Fields: -* event.tfinger.touchId - the Id of the touch device. -* event.tfinger.fingerId - the Id of the finger which just went down. -* event.tfinger.x - the x coordinate of the touch (0..1) -* event.tfinger.y - the y coordinate of the touch (0..1) -* event.tfinger.pressure - the pressure of the touch (0..1) - -SDL_EVENT_FINGER_MOTION: -Sent when a finger (or stylus) is moved on the touch device. -Fields: -Same as SDL_EVENT_FINGER_DOWN but with additional: -* event.tfinger.dx - change in x coordinate during this motion event. -* event.tfinger.dy - change in y coordinate during this motion event. - -SDL_EVENT_FINGER_UP: -Sent when a finger (or stylus) is lifted from the touch device. -Fields: -Same as SDL_EVENT_FINGER_DOWN. - - -=========================================================================== -Functions -=========================================================================== -SDL provides the ability to access the underlying SDL_Finger structures. -These structures should _never_ be modified. - -The following functions are included from SDL_touch.h - -To get a SDL_TouchID call SDL_GetTouchDevice(int index). -This returns a SDL_TouchID. -IMPORTANT: If the touch has been removed, or there is no touch with the given index, SDL_GetTouchDevice() will return 0. Be sure to check for this! - -The number of touch devices can be queried with SDL_GetNumTouchDevices(). - -A SDL_TouchID may be used to get pointers to SDL_Finger. - -SDL_GetNumTouchFingers(touchID) may be used to get the number of fingers currently down on the device. - -The most common reason to access SDL_Finger is to query the fingers outside the event. In most cases accessing the fingers is using the event. This would be accomplished by code like the following: - - float x = event.tfinger.x; - float y = event.tfinger.y; - - - -To get a SDL_Finger, call SDL_GetTouchFinger(SDL_TouchID touchID, int index), where touchID is a SDL_TouchID, and index is the requested finger. -This returns a SDL_Finger *, or NULL if the finger does not exist, or has been removed. -A SDL_Finger is guaranteed to be persistent for the duration of a touch, but it will be de-allocated as soon as the finger is removed. This occurs when the SDL_EVENT_FINGER_UP event is _added_ to the event queue, and thus _before_ the SDL_EVENT_FINGER_UP event is polled. -As a result, be very careful to check for NULL return values. - -A SDL_Finger has the following fields: -* x, y: - The current coordinates of the touch. -* pressure: - The pressure of the touch. - - -Please direct questions/comments to: - jim.tla+sdl_touch@gmail.com - (original author, API was changed since) +Touch +=========================================================================== +System Specific Notes +=========================================================================== +Linux: +The linux touch system is currently based off event streams, and proc/bus/devices. The active user must be given permissions to read /dev/input/TOUCHDEVICE, where TOUCHDEVICE is the event stream for your device. Currently only Wacom tablets are supported. If you have an unsupported tablet contact me at jim.tla+sdl_touch@gmail.com and I will help you get support for it. + +Mac: +The Mac and iPhone APIs are pretty. If your touch device supports them then you'll be fine. If it doesn't, then there isn't much we can do. + +iPhone: +Works out of box. + +Windows: +Unfortunately there is no windows support as of yet. Support for Windows 7 is planned, but we currently have no way to test. If you have a Windows 7 WM_TOUCH supported device, and are willing to help test please contact me at jim.tla+sdl_touch@gmail.com + +=========================================================================== +Events +=========================================================================== +SDL_EVENT_FINGER_DOWN: +Sent when a finger (or stylus) is placed on a touch device. +Fields: +* event.tfinger.touchId - the Id of the touch device. +* event.tfinger.fingerId - the Id of the finger which just went down. +* event.tfinger.x - the x coordinate of the touch (0..1) +* event.tfinger.y - the y coordinate of the touch (0..1) +* event.tfinger.pressure - the pressure of the touch (0..1) + +SDL_EVENT_FINGER_MOTION: +Sent when a finger (or stylus) is moved on the touch device. +Fields: +Same as SDL_EVENT_FINGER_DOWN but with additional: +* event.tfinger.dx - change in x coordinate during this motion event. +* event.tfinger.dy - change in y coordinate during this motion event. + +SDL_EVENT_FINGER_UP: +Sent when a finger (or stylus) is lifted from the touch device. +Fields: +Same as SDL_EVENT_FINGER_DOWN. + + +=========================================================================== +Functions +=========================================================================== +SDL provides the ability to access the underlying SDL_Finger structures. +These structures should _never_ be modified. + +The following functions are included from SDL_touch.h + +To get a SDL_TouchID call SDL_GetTouchDevice(int index). +This returns a SDL_TouchID. +IMPORTANT: If the touch has been removed, or there is no touch with the given index, SDL_GetTouchDevice() will return 0. Be sure to check for this! + +The number of touch devices can be queried with SDL_GetNumTouchDevices(). + +A SDL_TouchID may be used to get pointers to SDL_Finger. + +SDL_GetNumTouchFingers(touchID) may be used to get the number of fingers currently down on the device. + +The most common reason to access SDL_Finger is to query the fingers outside the event. In most cases accessing the fingers is using the event. This would be accomplished by code like the following: + + float x = event.tfinger.x; + float y = event.tfinger.y; + + + +To get a SDL_Finger, call SDL_GetTouchFinger(SDL_TouchID touchID, int index), where touchID is a SDL_TouchID, and index is the requested finger. +This returns a SDL_Finger *, or NULL if the finger does not exist, or has been removed. +A SDL_Finger is guaranteed to be persistent for the duration of a touch, but it will be de-allocated as soon as the finger is removed. This occurs when the SDL_EVENT_FINGER_UP event is _added_ to the event queue, and thus _before_ the SDL_EVENT_FINGER_UP event is polled. +As a result, be very careful to check for NULL return values. + +A SDL_Finger has the following fields: +* x, y: + The current coordinates of the touch. +* pressure: + The pressure of the touch. + + +Please direct questions/comments to: + jim.tla+sdl_touch@gmail.com + (original author, API was changed since) diff --git a/docs/README-versions.md b/docs/README-versions.md index d54bf40c1ce40..097dba1c7b73d 100644 --- a/docs/README-versions.md +++ b/docs/README-versions.md @@ -1,60 +1,60 @@ -# Versioning - -## Since 2.23.0 - -SDL follows an "odd/even" versioning policy, similar to GLib, GTK, Flatpak -and older versions of the Linux kernel: - -* The major version (first part) increases when backwards compatibility - is broken, which will happen infrequently. - -* If the minor version (second part) is divisible by 2 - (for example 2.24.x, 2.26.x), this indicates a version of SDL that - is believed to be stable and suitable for production use. - - * In stable releases, the patchlevel or micro version (third part) - indicates bugfix releases. Bugfix releases should not add or - remove ABI, so the ".0" release (for example 2.24.0) should be - forwards-compatible with all the bugfix releases from the - same cycle (for example 2.24.1). - - * The minor version increases when new API or ABI is added, or when - other significant changes are made. Newer minor versions are - backwards-compatible, but not fully forwards-compatible. - For example, programs built against SDL 2.24.x should work fine - with SDL 2.26.x, but programs built against SDL 2.26.x will not - necessarily work with 2.24.x. - -* If the minor version (second part) is not divisible by 2 - (for example 2.23.x, 2.25.x), this indicates a development prerelease - of SDL that is not suitable for stable software distributions. - Use with caution. - - * The patchlevel or micro version (third part) increases with - each prerelease. - - * Each prerelease might add new API and/or ABI. - - * Prereleases are backwards-compatible with older stable branches. - For example, 2.25.x will be backwards-compatible with 2.24.x. - - * Prereleases are not guaranteed to be backwards-compatible with - each other. For example, new API or ABI added in 2.25.1 - might be removed or changed in 2.25.2. - If this would be a problem for you, please do not use prereleases. - - * Only upgrade to a prerelease if you can guarantee that you will - promptly upgrade to the stable release that follows it. - For example, do not upgrade to 2.23.x unless you will be able to - upgrade to 2.24.0 when it becomes available. - - * Software distributions that have a freeze policy (in particular Linux - distributions with a release cycle, such as Debian and Fedora) - should usually only package stable releases, and not prereleases. - -## Before 2.23.0 - -Older versions of SDL followed a similar policy, but instead of the -odd/even rule applying to the minor version, it applied to the patchlevel -(micro version, third part). For example, 2.0.22 was a stable release -and 2.0.21 was a prerelease. +# Versioning + +## Since 2.23.0 + +SDL follows an "odd/even" versioning policy, similar to GLib, GTK, Flatpak +and older versions of the Linux kernel: + +* The major version (first part) increases when backwards compatibility + is broken, which will happen infrequently. + +* If the minor version (second part) is divisible by 2 + (for example 2.24.x, 2.26.x), this indicates a version of SDL that + is believed to be stable and suitable for production use. + + * In stable releases, the patchlevel or micro version (third part) + indicates bugfix releases. Bugfix releases should not add or + remove ABI, so the ".0" release (for example 2.24.0) should be + forwards-compatible with all the bugfix releases from the + same cycle (for example 2.24.1). + + * The minor version increases when new API or ABI is added, or when + other significant changes are made. Newer minor versions are + backwards-compatible, but not fully forwards-compatible. + For example, programs built against SDL 2.24.x should work fine + with SDL 2.26.x, but programs built against SDL 2.26.x will not + necessarily work with 2.24.x. + +* If the minor version (second part) is not divisible by 2 + (for example 2.23.x, 2.25.x), this indicates a development prerelease + of SDL that is not suitable for stable software distributions. + Use with caution. + + * The patchlevel or micro version (third part) increases with + each prerelease. + + * Each prerelease might add new API and/or ABI. + + * Prereleases are backwards-compatible with older stable branches. + For example, 2.25.x will be backwards-compatible with 2.24.x. + + * Prereleases are not guaranteed to be backwards-compatible with + each other. For example, new API or ABI added in 2.25.1 + might be removed or changed in 2.25.2. + If this would be a problem for you, please do not use prereleases. + + * Only upgrade to a prerelease if you can guarantee that you will + promptly upgrade to the stable release that follows it. + For example, do not upgrade to 2.23.x unless you will be able to + upgrade to 2.24.0 when it becomes available. + + * Software distributions that have a freeze policy (in particular Linux + distributions with a release cycle, such as Debian and Fedora) + should usually only package stable releases, and not prereleases. + +## Before 2.23.0 + +Older versions of SDL followed a similar policy, but instead of the +odd/even rule applying to the minor version, it applied to the patchlevel +(micro version, third part). For example, 2.0.22 was a stable release +and 2.0.21 was a prerelease. diff --git a/docs/README-visualc.md b/docs/README-visualc.md index 276c83bce77e0..7890421474197 100644 --- a/docs/README-visualc.md +++ b/docs/README-visualc.md @@ -1,113 +1,113 @@ -Using SDL with Microsoft Visual C++ -=================================== - -### by Lion Kimbro with additions by James Turk - -You can either use the precompiled libraries from the [SDL](https://www.libsdl.org/download.php) web site, or you can build SDL -yourself. - -### Building SDL - -0. To build SDL, your machine must, at a minimum, have the DirectX9.0c SDK installed. It may or may not be retrievable from -the [Microsoft](https://www.microsoft.com) website, so you might need to locate it [online](https://duckduckgo.com/?q=directx9.0c+sdk+download&t=h_&ia=web). -_Editor's note: I've been able to successfully build SDL using Visual Studio 2019 **without** the DX9.0c SDK_ - -1. Open the Visual Studio solution file at `./VisualC/SDL.sln`. - -2. Your IDE will likely prompt you to upgrade this solution file to whatever later version of the IDE you're using. In the `Retarget Projects` dialog, -all of the affected project files should be checked allowing you to use the latest `Windows SDK Version` you have installed, along with -the `Platform Toolset`. - -If you choose *NOT* to upgrade to use the latest `Windows SDK Version` or `Platform Toolset`, then you'll need the `Visual Studio 2010 Platform Toolset`. - -3. Build the `.dll` and `.lib` files by right clicking on each project in turn (Projects are listed in the _Workspace_ -panel in the _FileView_ tab), and selecting `Build`. - -You may get a few warnings, but you should not get any errors. - -Later, we will refer to the following `.lib` and `.dll` files that have just been generated: - -- `./VisualC/Win32/Debug/SDL3.dll` or `./VisualC/Win32/Release/SDL3.dll` -- `./VisualC/Win32/Debug/SDL3.lib` or `./VisualC/Win32/Release/SDL3.lib` - -_Note for the `x64` versions, just replace `Win32` in the path with `x64`_ - -### Creating a Project with SDL - -- Create a project as a `Win32 Application`. - -- Create a C++ file for your project. - -- Set the C runtime to `Multi-threaded DLL` in the menu: -`Project|Settings|C/C++ tab|Code Generation|Runtime Library `. - -- Add the SDL `include` directory to your list of includes in the menu: -`Project|Settings|C/C++ tab|Preprocessor|Additional include directories ` - -*VC7 Specific: Instead of doing this, I find it easier to add the -include and library directories to the list that VC7 keeps. Do this by -selecting Tools|Options|Projects|VC++ Directories and under the "Show -Directories For:" dropbox select "Include Files", and click the "New -Directory Icon" and add the [SDLROOT]\\include directory (e.g. If you -installed to c:\\SDL\\ add c:\\SDL\\include). Proceed to change the -dropbox selection to "Library Files" and add [SDLROOT]\\lib.* - -The "include directory" I am referring to is the `./include` folder. - -Now we're going to use the files that we had created earlier in the *Build SDL* step. - -Copy the following file into your Project directory: - -- `SDL3.dll` - -Add the following file to your project (It is not necessary to copy it to your project directory): - -- `SDL3.lib` - -To add them to your project, right click on your project, and select -`Add files to project`. - -**Instead of adding the files to your project, it is more desirable to add them to the linker options: Project|Properties|Linker|Command Line -and type the names of the libraries to link with in the "Additional Options:" box. Note: This must be done for each build configuration -(e.g. Release,Debug).** - -### Hello SDL - -Here's a sample SDL snippet to verify everything is setup in your IDE: - -``` - #include - #include // only include this one in the source file with main()! - - int main( int argc, char* argv[] ) - { - const int WIDTH = 640; - const int HEIGHT = 480; - SDL_Window* window = NULL; - SDL_Renderer* renderer = NULL; - - SDL_Init(SDL_INIT_VIDEO); - window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, 0); - renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); - return 0; - } - ``` - -### That's it! - -I hope that this document has helped you get through the most difficult part of using the SDL: installing it. -Suggestions for improvements should be posted to the [Github Issues](https://github.com/libsdl-org/SDL/issues). - -### Credits - -Thanks to [Paulus Esterhazy](mailto:pesterhazy@gmx.net), for the work on VC++ port. - -This document was originally called "VisualC.txt", and was written by [Sam Lantinga](mailto:slouken@libsdl.org). - -Later, it was converted to HTML and expanded into the document that you see today by [Lion Kimbro](mailto:snowlion@sprynet.com). - -Minor Fixes and Visual C++ 7 Information (In Green) was added by [James Turk](mailto:james@conceptofzero.net) +Using SDL with Microsoft Visual C++ +=================================== + +### by Lion Kimbro with additions by James Turk + +You can either use the precompiled libraries from the [SDL](https://www.libsdl.org/download.php) web site, or you can build SDL +yourself. + +### Building SDL + +0. To build SDL, your machine must, at a minimum, have the DirectX9.0c SDK installed. It may or may not be retrievable from +the [Microsoft](https://www.microsoft.com) website, so you might need to locate it [online](https://duckduckgo.com/?q=directx9.0c+sdk+download&t=h_&ia=web). +_Editor's note: I've been able to successfully build SDL using Visual Studio 2019 **without** the DX9.0c SDK_ + +1. Open the Visual Studio solution file at `./VisualC/SDL.sln`. + +2. Your IDE will likely prompt you to upgrade this solution file to whatever later version of the IDE you're using. In the `Retarget Projects` dialog, +all of the affected project files should be checked allowing you to use the latest `Windows SDK Version` you have installed, along with +the `Platform Toolset`. + +If you choose *NOT* to upgrade to use the latest `Windows SDK Version` or `Platform Toolset`, then you'll need the `Visual Studio 2010 Platform Toolset`. + +3. Build the `.dll` and `.lib` files by right clicking on each project in turn (Projects are listed in the _Workspace_ +panel in the _FileView_ tab), and selecting `Build`. + +You may get a few warnings, but you should not get any errors. + +Later, we will refer to the following `.lib` and `.dll` files that have just been generated: + +- `./VisualC/Win32/Debug/SDL3.dll` or `./VisualC/Win32/Release/SDL3.dll` +- `./VisualC/Win32/Debug/SDL3.lib` or `./VisualC/Win32/Release/SDL3.lib` + +_Note for the `x64` versions, just replace `Win32` in the path with `x64`_ + +### Creating a Project with SDL + +- Create a project as a `Win32 Application`. + +- Create a C++ file for your project. + +- Set the C runtime to `Multi-threaded DLL` in the menu: +`Project|Settings|C/C++ tab|Code Generation|Runtime Library `. + +- Add the SDL `include` directory to your list of includes in the menu: +`Project|Settings|C/C++ tab|Preprocessor|Additional include directories ` + +*VC7 Specific: Instead of doing this, I find it easier to add the +include and library directories to the list that VC7 keeps. Do this by +selecting Tools|Options|Projects|VC++ Directories and under the "Show +Directories For:" dropbox select "Include Files", and click the "New +Directory Icon" and add the [SDLROOT]\\include directory (e.g. If you +installed to c:\\SDL\\ add c:\\SDL\\include). Proceed to change the +dropbox selection to "Library Files" and add [SDLROOT]\\lib.* + +The "include directory" I am referring to is the `./include` folder. + +Now we're going to use the files that we had created earlier in the *Build SDL* step. + +Copy the following file into your Project directory: + +- `SDL3.dll` + +Add the following file to your project (It is not necessary to copy it to your project directory): + +- `SDL3.lib` + +To add them to your project, right click on your project, and select +`Add files to project`. + +**Instead of adding the files to your project, it is more desirable to add them to the linker options: Project|Properties|Linker|Command Line +and type the names of the libraries to link with in the "Additional Options:" box. Note: This must be done for each build configuration +(e.g. Release,Debug).** + +### Hello SDL + +Here's a sample SDL snippet to verify everything is setup in your IDE: + +``` + #include + #include // only include this one in the source file with main()! + + int main( int argc, char* argv[] ) + { + const int WIDTH = 640; + const int HEIGHT = 480; + SDL_Window* window = NULL; + SDL_Renderer* renderer = NULL; + + SDL_Init(SDL_INIT_VIDEO); + window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, 0); + renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; + } + ``` + +### That's it! + +I hope that this document has helped you get through the most difficult part of using the SDL: installing it. +Suggestions for improvements should be posted to the [Github Issues](https://github.com/libsdl-org/SDL/issues). + +### Credits + +Thanks to [Paulus Esterhazy](mailto:pesterhazy@gmx.net), for the work on VC++ port. + +This document was originally called "VisualC.txt", and was written by [Sam Lantinga](mailto:slouken@libsdl.org). + +Later, it was converted to HTML and expanded into the document that you see today by [Lion Kimbro](mailto:snowlion@sprynet.com). + +Minor Fixes and Visual C++ 7 Information (In Green) was added by [James Turk](mailto:james@conceptofzero.net) diff --git a/docs/README-vita.md b/docs/README-vita.md index 3dbaf1cd405c2..0a11cf806ba81 100644 --- a/docs/README-vita.md +++ b/docs/README-vita.md @@ -1,33 +1,33 @@ -PS Vita -======= -SDL port for the Sony Playstation Vita and Sony Playstation TV - -Credit to -* xerpi, cpasjuste and rsn8887 for initial (vita2d) port -* vitasdk/dolcesdk devs -* CBPS discord (Namely Graphene and SonicMastr) - -Building --------- -To build for the PSVita, make sure you have vitasdk and cmake installed and run: -``` - cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release - cmake --build build - cmake --install build -``` - - -Notes ------ -* gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON` - These renderers support 720p and 1080i resolutions. These can be specified with: - `SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);` -* Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK. - They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);` - anytime before video subsystem initialization. -* gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON` -* By default SDL emits mouse events for touch events on every touchscreen. - Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead. - Individual touchscreens can be disabled with: - `SDL_setenv("VITA_DISABLE_TOUCH_FRONT", "1", 1);` and `SDL_setenv("VITA_DISABLE_TOUCH_BACK", "1", 1);` -* Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita. +PS Vita +======= +SDL port for the Sony Playstation Vita and Sony Playstation TV + +Credit to +* xerpi, cpasjuste and rsn8887 for initial (vita2d) port +* vitasdk/dolcesdk devs +* CBPS discord (Namely Graphene and SonicMastr) + +Building +-------- +To build for the PSVita, make sure you have vitasdk and cmake installed and run: +``` + cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release + cmake --build build + cmake --install build +``` + + +Notes +----- +* gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON` + These renderers support 720p and 1080i resolutions. These can be specified with: + `SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);` +* Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK. + They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);` + anytime before video subsystem initialization. +* gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON` +* By default SDL emits mouse events for touch events on every touchscreen. + Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead. + Individual touchscreens can be disabled with: + `SDL_setenv("VITA_DISABLE_TOUCH_FRONT", "1", 1);` and `SDL_setenv("VITA_DISABLE_TOUCH_BACK", "1", 1);` +* Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita. diff --git a/docs/README-wayland.md b/docs/README-wayland.md index 2bab54f244eb5..a376b48ad01c8 100644 --- a/docs/README-wayland.md +++ b/docs/README-wayland.md @@ -1,45 +1,45 @@ -Wayland -======= -Wayland is a replacement for the X11 window system protocol and architecture and is favored over X11 by default in SDL3 -for communicating with desktop compositors. It works well for the majority of applications, however, applications may -encounter limitations or behavior that is different from other windowing systems. - -## Common issues: - -### Window decorations are missing, or the decorations look strange - -- On some desktops (i.e. GNOME), Wayland applications use a library - called [libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) to provide window decorations. If this library is - not installed, the decorations will be missing. This library uses plugins to generate different decoration styles, and - if a plugin to generate native-looking decorations is not installed (i.e. the GTK plugin), the decorations will not - appear to be 'native'. - -### Windows do not appear immediately after creation - -- Wayland requires that the application initially present a buffer before the window becomes visible. Additionally, - applications _must_ have an event loop and processes messages on a regular basis, or the application can appear - unresponsive to both the user and desktop compositor. - -### ```SDL_SetWindowPosition()``` doesn't work on non-popup windows - -- Wayland does not allow toplevel windows to position themselves programmatically. - -### Retrieving the global mouse cursor position when the cursor is outside a window doesn't work - -- Wayland only provides applications with the cursor position within the borders of the application windows. Querying - the global position when an application window does not have mouse focus returns 0,0 as the actual cursor position is - unknown. In most cases, applications don't actually need the global cursor position and should use the window-relative - coordinates as provided by the mouse movement event or from ```SDL_GetMouseState()``` instead. - -### Warping the global mouse cursor position via ```SDL_WarpMouseGlobal()``` doesn't work - -- For security reasons, Wayland does not allow warping the global mouse cursor position. - -### The application icon can't be set via ```SDL_SetWindowIcon()``` - -- Wayland doesn't support programmatically setting the application icon. To provide a custom icon for your application, - you must create an associated desktop entry file, aka a `.desktop` file, that points to the icon image. Please see the - [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/) for more information - on the format of this file. Note that if your application manually sets the application ID via the `SDL_APP_ID` hint - string, the desktop entry file name should match the application ID. For example, if your application ID is set - to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`. +Wayland +======= +Wayland is a replacement for the X11 window system protocol and architecture and is favored over X11 by default in SDL3 +for communicating with desktop compositors. It works well for the majority of applications, however, applications may +encounter limitations or behavior that is different from other windowing systems. + +## Common issues: + +### Window decorations are missing, or the decorations look strange + +- On some desktops (i.e. GNOME), Wayland applications use a library + called [libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) to provide window decorations. If this library is + not installed, the decorations will be missing. This library uses plugins to generate different decoration styles, and + if a plugin to generate native-looking decorations is not installed (i.e. the GTK plugin), the decorations will not + appear to be 'native'. + +### Windows do not appear immediately after creation + +- Wayland requires that the application initially present a buffer before the window becomes visible. Additionally, + applications _must_ have an event loop and processes messages on a regular basis, or the application can appear + unresponsive to both the user and desktop compositor. + +### ```SDL_SetWindowPosition()``` doesn't work on non-popup windows + +- Wayland does not allow toplevel windows to position themselves programmatically. + +### Retrieving the global mouse cursor position when the cursor is outside a window doesn't work + +- Wayland only provides applications with the cursor position within the borders of the application windows. Querying + the global position when an application window does not have mouse focus returns 0,0 as the actual cursor position is + unknown. In most cases, applications don't actually need the global cursor position and should use the window-relative + coordinates as provided by the mouse movement event or from ```SDL_GetMouseState()``` instead. + +### Warping the global mouse cursor position via ```SDL_WarpMouseGlobal()``` doesn't work + +- For security reasons, Wayland does not allow warping the global mouse cursor position. + +### The application icon can't be set via ```SDL_SetWindowIcon()``` + +- Wayland doesn't support programmatically setting the application icon. To provide a custom icon for your application, + you must create an associated desktop entry file, aka a `.desktop` file, that points to the icon image. Please see the + [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/) for more information + on the format of this file. Note that if your application manually sets the application ID via the `SDL_APP_ID` hint + string, the desktop entry file name should match the application ID. For example, if your application ID is set + to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`. diff --git a/docs/README-windows.md b/docs/README-windows.md index 1e6d59c44cae5..daf80647fc121 100644 --- a/docs/README-windows.md +++ b/docs/README-windows.md @@ -1,66 +1,66 @@ -# Windows - -## LLVM and Intel C++ compiler support - -SDL will build with the Visual Studio project files with LLVM-based compilers, such as the Intel oneAPI C++ -compiler, but you'll have to manually add the "-msse3" command line option -to at least the SDL_audiocvt.c source file, and possibly others. This may -not be necessary if you build SDL with CMake instead of the included Visual -Studio solution. - -Details are here: https://github.com/libsdl-org/SDL/issues/5186 - - -## OpenGL ES 2.x support - -SDL has support for OpenGL ES 2.x under Windows via two alternative -implementations. - -The most straightforward method consists in running your app in a system with -a graphic card paired with a relatively recent (as of November of 2013) driver -which supports the WGL_EXT_create_context_es2_profile extension. Vendors known -to ship said extension on Windows currently include nVidia and Intel. - -The other method involves using the -[ANGLE library](https://code.google.com/p/angleproject/). If an OpenGL ES 2.x -context is requested and no WGL_EXT_create_context_es2_profile extension is -found, SDL will try to load the libEGL.dll library provided by ANGLE. - -To obtain the ANGLE binaries, you can either compile from source from -https://chromium.googlesource.com/angle/angle or copy the relevant binaries -from a recent Chrome/Chromium install for Windows. The files you need are: - -- libEGL.dll -- libGLESv2.dll -- d3dcompiler_46.dll (supports Windows Vista or later, better shader - compiler) *or* d3dcompiler_43.dll (supports Windows XP or later) - -If you compile ANGLE from source, you can configure it so it does not need the -d3dcompiler_* DLL at all (for details on this, see their documentation). -However, by default SDL will try to preload the d3dcompiler_46.dll to -comply with ANGLE's requirements. If you wish SDL to preload -d3dcompiler_43.dll (to support Windows XP) or to skip this step at all, you -can use the SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more -details). - -Known Bugs: - -- SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears - that there's a bug in the library which prevents the window contents from - refreshing if this is set to anything other than the default value. - -## Vulkan Surface Support - -Support for creating Vulkan surfaces is configured on by default. To disable -it change the value of `SDL_VIDEO_VULKAN` to 0 in `SDL_config_windows.h`. You -must install the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) in order to -use Vulkan graphics in your application. - -## Transparent Window Support - -SDL uses the Desktop Window Manager (DWM) to create transparent windows. DWM is -always enabled from Windows 8 and above. Windows 7 only enables DWM with Aero Glass -theme. - -However, it cannot be guaranteed to work on all hardware configurations (an example -is hybrid GPU systems, such as NVIDIA Optimus laptops). +# Windows + +## LLVM and Intel C++ compiler support + +SDL will build with the Visual Studio project files with LLVM-based compilers, such as the Intel oneAPI C++ +compiler, but you'll have to manually add the "-msse3" command line option +to at least the SDL_audiocvt.c source file, and possibly others. This may +not be necessary if you build SDL with CMake instead of the included Visual +Studio solution. + +Details are here: https://github.com/libsdl-org/SDL/issues/5186 + + +## OpenGL ES 2.x support + +SDL has support for OpenGL ES 2.x under Windows via two alternative +implementations. + +The most straightforward method consists in running your app in a system with +a graphic card paired with a relatively recent (as of November of 2013) driver +which supports the WGL_EXT_create_context_es2_profile extension. Vendors known +to ship said extension on Windows currently include nVidia and Intel. + +The other method involves using the +[ANGLE library](https://code.google.com/p/angleproject/). If an OpenGL ES 2.x +context is requested and no WGL_EXT_create_context_es2_profile extension is +found, SDL will try to load the libEGL.dll library provided by ANGLE. + +To obtain the ANGLE binaries, you can either compile from source from +https://chromium.googlesource.com/angle/angle or copy the relevant binaries +from a recent Chrome/Chromium install for Windows. The files you need are: + +- libEGL.dll +- libGLESv2.dll +- d3dcompiler_46.dll (supports Windows Vista or later, better shader + compiler) *or* d3dcompiler_43.dll (supports Windows XP or later) + +If you compile ANGLE from source, you can configure it so it does not need the +d3dcompiler_* DLL at all (for details on this, see their documentation). +However, by default SDL will try to preload the d3dcompiler_46.dll to +comply with ANGLE's requirements. If you wish SDL to preload +d3dcompiler_43.dll (to support Windows XP) or to skip this step at all, you +can use the SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more +details). + +Known Bugs: + +- SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears + that there's a bug in the library which prevents the window contents from + refreshing if this is set to anything other than the default value. + +## Vulkan Surface Support + +Support for creating Vulkan surfaces is configured on by default. To disable +it change the value of `SDL_VIDEO_VULKAN` to 0 in `SDL_config_windows.h`. You +must install the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) in order to +use Vulkan graphics in your application. + +## Transparent Window Support + +SDL uses the Desktop Window Manager (DWM) to create transparent windows. DWM is +always enabled from Windows 8 and above. Windows 7 only enables DWM with Aero Glass +theme. + +However, it cannot be guaranteed to work on all hardware configurations (an example +is hybrid GPU systems, such as NVIDIA Optimus laptops). diff --git a/docs/README-winrt.md b/docs/README-winrt.md index 61922640981a2..a41b21eb6f39a 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -1,523 +1,523 @@ -WinRT -===== - -This port allows SDL applications to run on Microsoft's platforms that require -use of "Windows Runtime", aka. "WinRT", APIs. Microsoft may, in some cases, -refer to them as either "Windows Store", or for Windows 10, "UWP" apps. - -In the past, SDL has supported Windows RT 8.x, Windows Phone, etc, but in -modern times this port is focused on UWP apps, which run on Windows 10, -and modern Xbox consoles. - - -Requirements ------------- - -* Microsoft Visual C++ (aka Visual Studio) 2019. - - Free, "Community" or "Express" editions may be used, so long as they - include support for either "Windows Store" or "Windows Phone" apps. - "Express" versions marked as supporting "Windows Desktop" development - typically do not include support for creating WinRT apps, to note. - (The "Community" editions of Visual C++ do, however, support both - desktop/Win32 and WinRT development). -* A valid Microsoft account - This requirement is not imposed by SDL, but - rather by Microsoft's Visual C++ toolchain. This is required to launch or - debug apps. - - -Status ------- - -Here is a rough list of what works, and what doesn't: - -* What works: - * compilation via Visual C++ 2019. - * compile-time platform detection for SDL programs. The C/C++ #define, - `__WINRT__`, will be set to 1 (by SDL) when compiling for WinRT. - * GPU-accelerated 2D rendering, via SDL_Renderer. - * OpenGL ES 2, via the ANGLE library (included separately from SDL) - * software rendering, via either SDL_Surface (optionally in conjunction with - SDL_GetWindowSurface() and SDL_UpdateWindowSurface()) or via the - SDL_Renderer APIs - * threads - * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(), - SDL_GetPerformanceFrequency(), etc.) - * file I/O via SDL_RWops - * mouse input (unsupported on Windows Phone) - * audio, via SDL's WASAPI backend (if you want to record, your app must - have "Microphone" capabilities enabled in its manifest, and the user must - not have blocked access. Otherwise, capture devices will fail to work, - presenting as a device disconnect shortly after opening it.) - * .DLL file loading. Libraries *MUST* be packaged inside applications. Loading - anything outside of the app is not supported. - * system path retrieval via SDL's filesystem APIs - * game controllers. Support is provided via the SDL_Joystick and - SDL_Gamepad APIs, and is backed by Microsoft's XInput API. Please - note, however, that Windows limits game-controller support in UWP apps to, - "Xbox compatible controllers" (many controllers that work in Win32 apps, - do not work in UWP, due to restrictions in UWP itself.) - * multi-touch input - * app events. SDL_APP_WILLENTER* and SDL_APP_DIDENTER* events get sent out as - appropriate. - * window events - * using Direct3D 11.x APIs outside of SDL. Non-XAML / Direct3D-only apps can - choose to render content directly via Direct3D, using SDL to manage the - internal WinRT window, as well as input and audio. (Use - the window properties to get the WinRT 'CoreWindow', and pass it into - IDXGIFactory2::CreateSwapChainForCoreWindow() as appropriate.) - -* What partially works: - * keyboard input. Most of WinRT's documented virtual keys are supported, as - well as many keys with documented hardware scancodes. Converting - SDL_Scancodes to or from SDL_Keycodes may not work, due to missing APIs - (MapVirtualKey()) in Microsoft's Windows Store / UWP APIs. - * SDL_main. WinRT uses a different signature for each app's main() function - and requires it to be implemented in C++, so SDL_main.h must be #include'd - in a C++ source file, that also must be compiled with /ZW. - -* What doesn't work: - * compilation with anything other than Visual C++ - * programmatically-created custom cursors. These don't appear to be supported - by WinRT. Different OS-provided cursors can, however, be created via - SDL_CreateSystemCursor() (unsupported on Windows Phone) - * SDL_WarpMouseInWindow() or SDL_WarpMouseGlobal(). This are not currently - supported by WinRT itself. - * joysticks and game controllers that either are not supported by - Microsoft's XInput API, or are not supported within UWP apps (many - controllers that work in Win32, do not work in UWP, due to restrictions in - UWP itself). - * turning off VSync when rendering on Windows Phone. Attempts to turn VSync - off on Windows Phone result either in Direct3D not drawing anything, or it - forcing VSync back on. As such, SDL_RENDERER_PRESENTVSYNC will always get - turned-on on Windows Phone. This limitation is not present in non-Phone - WinRT (such as Windows 8.x), where turning off VSync appears to work. - * probably anything else that's not listed as supported - - - -Upgrade Notes -------------- - -#### SDL_GetPrefPath() usage when upgrading WinRT apps from SDL 2.0.3 - -SDL 2.0.4 fixes two bugs found in the WinRT version of SDL_GetPrefPath(). -The fixes may affect older, SDL 2.0.3-based apps' save data. Please note -that these changes only apply to SDL-based WinRT apps, and not to apps for -any other platform. - -1. SDL_GetPrefPath() would return an invalid path, one in which the path's - directory had not been created. Attempts to create files there - (via fopen(), for example), would fail, unless that directory was - explicitly created beforehand. - -2. SDL_GetPrefPath(), for non-WinPhone-based apps, would return a path inside - a WinRT 'Roaming' folder, the contents of which get automatically - synchronized across multiple devices. This process can occur while an - application runs, and can cause existing save-data to be overwritten - at unexpected times, with data from other devices. (Windows Phone apps - written with SDL 2.0.3 did not utilize a Roaming folder, due to API - restrictions in Windows Phone 8.0). - - -SDL_GetPrefPath(), starting with SDL 2.0.4, addresses these by: - -1. making sure that SDL_GetPrefPath() returns a directory in which data - can be written to immediately, without first needing to create directories. - -2. basing SDL_GetPrefPath() off of a different, non-Roaming folder, the - contents of which do not automatically get synchronized across devices - (and which require less work to use safely, in terms of data integrity). - -Apps that wish to get their Roaming folder's path can do so either by using -SDL_WinRTGetFSPathUTF8(), SDL_WinRTGetFSPathUNICODE() (which returns a -UCS-2/wide-char string), or directly through the WinRT class, -Windows.Storage.ApplicationData. - - - -Setup, High-Level Steps ------------------------ - -The steps for setting up a project for an SDL/WinRT app looks like the -following, at a high-level: - -1. create a new Visual C++ project using Microsoft's template for a, - "Direct3D App". -2. remove most of the files from the project. -3. make your app's project directly reference SDL/WinRT's own Visual C++ - project file, via use of Visual C++'s "References" dialog. This will setup - the linker, and will copy SDL's .dll files to your app's final output. -4. adjust your app's build settings, at minimum, telling it where to find SDL's - header files. -5. add files that contains a WinRT-appropriate main function, along with some - data to make sure mouse-cursor-hiding (via SDL_ShowCursor(SDL_DISABLE) calls) - work properly. -6. add SDL-specific app code. -7. build and run your app. - - -Setup, Detailed Steps ---------------------- - -### 1. Create a new project ### - -Create a new project using one of Visual C++'s templates for a plain, non-XAML, -"Direct3D App" (XAML support for SDL/WinRT is not yet ready for use). If you -don't see one of these templates, in Visual C++'s 'New Project' dialog, try -using the textbox titled, 'Search Installed Templates' to look for one. - - -### 2. Remove unneeded files from the project ### - -In the new project, delete any file that has one of the following extensions: - -- .cpp -- .h -- .hlsl - -When you are done, you should be left with a few files, each of which will be a -necessary part of your app's project. These files will consist of: - -- an .appxmanifest file, which contains metadata on your WinRT app. This is - similar to an Info.plist file on iOS, or an AndroidManifest.xml on Android. -- a few .png files, one of which is a splash screen (displayed when your app - launches), others are app icons. -- a .pfx file, used for code signing purposes. - - -### 3. Add references to SDL's project files ### - -SDL/WinRT can be built in multiple variations, spanning across three different -CPU architectures (x86, x64, and ARM) and two different configurations -(Debug and Release). WinRT and Visual C++ do not currently provide a means -for combining multiple variations of one library into a single file. -Furthermore, it does not provide an easy means for copying pre-built .dll files -into your app's final output (via Post-Build steps, for example). It does, -however, provide a system whereby an app can reference the MSVC projects of -libraries such that, when the app is built: - -1. each library gets built for the appropriate CPU architecture(s) and WinRT - platform(s). -2. each library's output, such as .dll files, get copied to the app's build - output. - -To set this up for SDL/WinRT, you'll need to run through the following steps: - -1. open up the Solution Explorer inside Visual C++ (under the "View" menu, then - "Solution Explorer") -2. right click on your app's solution. -3. navigate to "Add", then to "Existing Project..." -4. find SDL/WinRT's Visual C++ project file and open it, in the `VisualC-WinRT` - directory. -5. once the project has been added, right-click on your app's project and - select, "References..." -6. click on the button titled, "Add New Reference..." -7. check the box next to SDL -8. click OK to close the dialog -9. SDL will now show up in the list of references. Click OK to close that - dialog. - -Your project is now linked to SDL's project, insofar that when the app is -built, SDL will be built as well, with its build output getting included with -your app. - - -### 4. Adjust Your App's Build Settings ### - -Some build settings need to be changed in your app's project. This guide will -outline the following: - -- making sure that the compiler knows where to find SDL's header files -- **Optional for C++, but NECESSARY for compiling C code:** telling the - compiler not to use Microsoft's C++ extensions for WinRT development. -- **Optional:** telling the compiler not generate errors due to missing - precompiled header files. - -To change these settings: - -1. right-click on the project -2. choose "Properties" -3. in the drop-down box next to "Configuration", choose, "All Configurations" -4. in the drop-down box next to "Platform", choose, "All Platforms" -5. in the left-hand list, expand the "C/C++" section - **Note:** If you don't see this section, you may have to add a .c or .cpp - Source file to the Project first. -6. select "General" -7. edit the "Additional Include Directories" setting, and add a path to SDL's - "include" directory -8. **Optional: to enable compilation of C code:** change the setting for - "Consume Windows Runtime Extension" from "Yes (/ZW)" to "No". If you're - working with a completely C++ based project, this step can usually be - omitted. -9. **Optional: to disable precompiled headers (which can produce - 'stdafx.h'-related build errors, if setup incorrectly:** in the left-hand - list, select "Precompiled Headers", then change the setting for "Precompiled - Header" from "Use (/Yu)" to "Not Using Precompiled Headers". -10. close the dialog, saving settings, by clicking the "OK" button - - -### 5. Add a WinRT-appropriate main function, and a blank-cursor image, to the app. ### - -A few files should be included directly in your app's MSVC project, specifically: -1. a WinRT-appropriate main function (which is different than main() functions on - other platforms) -2. a Win32-style cursor resource, used by SDL_ShowCursor() to hide the mouse cursor - (if and when the app needs to do so). *If this cursor resource is not - included, mouse-position reporting may fail if and when the cursor is - hidden, due to possible bugs/design-oddities in Windows itself.* - -To include these files for C/C++ projects: - -1. right-click on your project (again, in Visual C++'s Solution Explorer), - navigate to "Add", then choose "Existing Item...". -2. navigate to the directory containing SDL's source code, then into its - subdirectory, 'src/main/winrt/'. Select, then add, the following files: - - `SDL3-WinRTResources.rc` - - `SDL3-WinRTResource_BlankCursor.cur` -3. For the next step you need a C++ source file. - - If your standard main() function is implemented in a **C++** source file, - use that file. - - If your standard main() function is implemented in a **plain C** source file, - create an empty .cpp source file (e.g. `main.cpp`) that only contains the line - `#include ` and use that file instead. -4. Right click on the C++ source file from step 3 (as listed in your project), - then click on "Properties...". -5. in the drop-down box next to "Configuration", choose, "All Configurations" -6. in the drop-down box next to "Platform", choose, "All Platforms" -7. in the left-hand list, click on "C/C++" -8. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)". -9. click the OK button. This will close the dialog. - -**NOTE: C++/CX compilation is currently required in at least one file of your -app's project. This is to make sure that Visual C++'s linker builds a 'Windows -Metadata' file (.winmd) for your app. Not doing so can lead to build errors.** - -For non-C++ projects, you will need to call SDL_RunApp from your language's -main function, and generate SDL3-WinRTResources.res manually by using `rc` via -the Developer Command Prompt and including it as a within the -first block in your Visual Studio project file. - -### 6. Add app code and assets ### - -At this point, you can add in SDL-specific source code. Be sure to include a -C-style main function (ie: `int main(int argc, char *argv[])`). From there you -should be able to create a single `SDL_Window` (WinRT apps can only have one -window, at present), as well as an `SDL_Renderer`. Direct3D will be used to -draw content. Events are received via SDL's usual event functions -(`SDL_PollEvent`, etc.) If you have a set of existing source files and assets, -you can start adding them to the project now. If not, or if you would like to -make sure that you're setup correctly, some short and simple sample code is -provided below. - - -#### 6.A. ... when creating a new app #### - -If you are creating a new app (rather than porting an existing SDL-based app), -or if you would just like a simple app to test SDL/WinRT with before trying to -get existing code working, some working SDL/WinRT code is provided below. To -set this up: - -1. right click on your app's project -2. select Add, then New Item. An "Add New Item" dialog will show up. -3. from the left-hand list, choose "Visual C++" -4. from the middle/main list, choose "C++ File (.cpp)" -5. near the bottom of the dialog, next to "Name:", type in a name for your -source file, such as, "main.cpp". -6. click on the Add button. This will close the dialog, add the new file to -your project, and open the file in Visual C++'s text editor. -7. Copy and paste the following code into the new file, then save it. - -```c -#include -#include - -int main(int argc, char **argv) -{ - SDL_Window *window = NULL; - SDL_Renderer *renderer = NULL; - SDL_Event evt; - SDL_bool keep_going = SDL_TRUE; - - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - return 1; - } else if (SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN, &window, &renderer) != 0) { - return 1; - } - - while (keep_going) { - while (SDL_PollEvent(&evt)) { - if ((evt.type == SDL_EVENT_KEY_DOWN) && (evt.key.keysym.sym == SDLK_ESCAPE)) { - keep_going = SDL_FALSE; - } - } - - SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - } - - SDL_Quit(); - return 0; -} -``` - -#### 6.B. Adding code and assets #### - -If you have existing code and assets that you'd like to add, you should be able -to add them now. The process for adding a set of files is as such. - -1. right click on the app's project -2. select Add, then click on "New Item..." -3. open any source, header, or asset files as appropriate. Support for C and -C++ is available. - -Do note that WinRT only supports a subset of the APIs that are available to -Win32-based apps. Many portions of the Win32 API and the C runtime are not -available. - -A list of unsupported C APIs can be found at - - -General information on using the C runtime in WinRT can be found at - - -A list of supported Win32 APIs for WinRT apps can be found at -. To note, -the list of supported Win32 APIs for Windows Phone 8.0 is different. -That list can be found at - - - -### 7. Build and run your app ### - -Your app project should now be setup, and you should be ready to build your app. -To run it on the local machine, open the Debug menu and choose "Start -Debugging". This will build your app, then run your app full-screen. To switch -out of your app, press the Windows key. Alternatively, you can choose to run -your app in a window. To do this, before building and running your app, find -the drop-down menu in Visual C++'s toolbar that says, "Local Machine". Expand -this by clicking on the arrow on the right side of the list, then click on -Simulator. Once you do that, any time you build and run the app, the app will -launch in window, rather than full-screen. - - -#### 7.A. Running apps on older, ARM-based, "Windows RT" devices #### - -**These instructions do not include Windows Phone, despite Windows Phone -typically running on ARM processors.** They are specifically for devices -that use the "Windows RT" operating system, which was a modified version of -Windows 8.x that ran primarily on ARM-based tablet computers. - -To build and run the app on ARM-based, "Windows RT" devices, you'll need to: - -- install Microsoft's "Remote Debugger" on the device. Visual C++ installs and - debugs ARM-based apps via IP networks. -- change a few options on the development machine, both to make sure it builds - for ARM (rather than x86 or x64), and to make sure it knows how to find the - Windows RT device (on the network). - -Microsoft's Remote Debugger can be found at -. Please note -that separate versions of this debugger exist for different versions of Visual -C++, one each for MSVC 2015, 2013, and 2012. - -To setup Visual C++ to launch your app on an ARM device: - -1. make sure the Remote Debugger is running on your ARM device, and that it's on - the same IP network as your development machine. -2. from Visual C++'s toolbar, find a drop-down menu that says, "Win32". Click - it, then change the value to "ARM". -3. make sure Visual C++ knows the hostname or IP address of the ARM device. To - do this: - 1. open the app project's properties - 2. select "Debugging" - 3. next to "Machine Name", enter the hostname or IP address of the ARM - device - 4. if, and only if, you've turned off authentication in the Remote Debugger, - then change the setting for "Require Authentication" to No - 5. click "OK" -4. build and run the app (from Visual C++). The first time you do this, a - prompt will show up on the ARM device, asking for a Microsoft Account. You - do, unfortunately, need to log in here, and will need to follow the - subsequent registration steps in order to launch the app. After you do so, - if the app didn't already launch, try relaunching it again from within Visual - C++. - - -Troubleshooting ---------------- - -#### Build fails with message, "error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker'" - -Try adding the following to your linker flags. In MSVC, this can be done by -right-clicking on the app project, navigating to Configuration Properties -> -Linker -> Command Line, then adding them to the Additional Options -section. - -* For Release builds / MSVC-Configurations, add: - - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib - -* For Debug builds / MSVC-Configurations, add: - - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib - - -#### Mouse-motion events fail to get sent, or SDL_GetMouseState() fails to return updated values - -This may be caused by a bug in Windows itself, whereby hiding the mouse -cursor can cause mouse-position reporting to fail. - -SDL provides a workaround for this, but it requires that an app links to a -set of Win32-style cursor image-resource files. A copy of suitable resource -files can be found in `src/main/winrt/`. Adding them to an app's Visual C++ -project file should be sufficient to get the app to use them. - - -#### SDL's Visual Studio project file fails to open, with message, "The system can't find the file specified." - -This can be caused for any one of a few reasons, which Visual Studio can -report, but won't always do so in an up-front manner. - -To help determine why this error comes up: - -1. open a copy of Visual Studio without opening a project file. This can be - accomplished via Windows' Start Menu, among other means. -2. show Visual Studio's Output window. This can be done by going to VS' - menu bar, then to View, and then to Output. -3. try opening the SDL project file directly by going to VS' menu bar, then - to File, then to Open, then to Project/Solution. When a File-Open dialog - appears, open the SDL project (such as the one in SDL's source code, in its - directory, VisualC-WinRT/UWP_VS2015/). -4. after attempting to open SDL's Visual Studio project file, additional error - information will be output to the Output window. - -If Visual Studio reports (via its Output window) that the project: - -"could not be loaded because it's missing install components. To fix this launch Visual Studio setup with the following selections: -Microsoft.VisualStudio.ComponentGroup.UWP.VC" - -... then you will need to re-launch Visual Studio's installer, and make sure that -the workflow for "Universal Windows Platform development" is checked, and that its -optional component, "C++ Universal Windows Platform tools" is also checked. While -you are there, if you are planning on targeting UWP / Windows 10, also make sure -that you check the optional component, "Windows 10 SDK (10.0.10240.0)". After -making sure these items are checked as-appropriate, install them. - -Once you install these components, try re-launching Visual Studio, and re-opening -the SDL project file. If you still get the error dialog, try using the Output -window, again, seeing what Visual Studio says about it. - - -#### Game controllers / joysticks aren't working! - -Windows only permits certain game controllers and joysticks to work within -WinRT / UWP apps. Even if a game controller or joystick works in a Win32 -app, that device is not guaranteed to work inside a WinRT / UWP app. - -According to Microsoft, "Xbox compatible controllers" should work inside -UWP apps, potentially with more working in the future. This includes, but -may not be limited to, Microsoft-made Xbox controllers and USB adapters. -(Source: https://social.msdn.microsoft.com/Forums/en-US/9064838b-e8c3-4c18-8a83-19bf0dfe150d/xinput-fails-to-detect-game-controllers?forum=wpdevelop) - - +WinRT +===== + +This port allows SDL applications to run on Microsoft's platforms that require +use of "Windows Runtime", aka. "WinRT", APIs. Microsoft may, in some cases, +refer to them as either "Windows Store", or for Windows 10, "UWP" apps. + +In the past, SDL has supported Windows RT 8.x, Windows Phone, etc, but in +modern times this port is focused on UWP apps, which run on Windows 10, +and modern Xbox consoles. + + +Requirements +------------ + +* Microsoft Visual C++ (aka Visual Studio) 2019. + - Free, "Community" or "Express" editions may be used, so long as they + include support for either "Windows Store" or "Windows Phone" apps. + "Express" versions marked as supporting "Windows Desktop" development + typically do not include support for creating WinRT apps, to note. + (The "Community" editions of Visual C++ do, however, support both + desktop/Win32 and WinRT development). +* A valid Microsoft account - This requirement is not imposed by SDL, but + rather by Microsoft's Visual C++ toolchain. This is required to launch or + debug apps. + + +Status +------ + +Here is a rough list of what works, and what doesn't: + +* What works: + * compilation via Visual C++ 2019. + * compile-time platform detection for SDL programs. The C/C++ #define, + `__WINRT__`, will be set to 1 (by SDL) when compiling for WinRT. + * GPU-accelerated 2D rendering, via SDL_Renderer. + * OpenGL ES 2, via the ANGLE library (included separately from SDL) + * software rendering, via either SDL_Surface (optionally in conjunction with + SDL_GetWindowSurface() and SDL_UpdateWindowSurface()) or via the + SDL_Renderer APIs + * threads + * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(), + SDL_GetPerformanceFrequency(), etc.) + * file I/O via SDL_RWops + * mouse input (unsupported on Windows Phone) + * audio, via SDL's WASAPI backend (if you want to record, your app must + have "Microphone" capabilities enabled in its manifest, and the user must + not have blocked access. Otherwise, capture devices will fail to work, + presenting as a device disconnect shortly after opening it.) + * .DLL file loading. Libraries *MUST* be packaged inside applications. Loading + anything outside of the app is not supported. + * system path retrieval via SDL's filesystem APIs + * game controllers. Support is provided via the SDL_Joystick and + SDL_Gamepad APIs, and is backed by Microsoft's XInput API. Please + note, however, that Windows limits game-controller support in UWP apps to, + "Xbox compatible controllers" (many controllers that work in Win32 apps, + do not work in UWP, due to restrictions in UWP itself.) + * multi-touch input + * app events. SDL_APP_WILLENTER* and SDL_APP_DIDENTER* events get sent out as + appropriate. + * window events + * using Direct3D 11.x APIs outside of SDL. Non-XAML / Direct3D-only apps can + choose to render content directly via Direct3D, using SDL to manage the + internal WinRT window, as well as input and audio. (Use + the window properties to get the WinRT 'CoreWindow', and pass it into + IDXGIFactory2::CreateSwapChainForCoreWindow() as appropriate.) + +* What partially works: + * keyboard input. Most of WinRT's documented virtual keys are supported, as + well as many keys with documented hardware scancodes. Converting + SDL_Scancodes to or from SDL_Keycodes may not work, due to missing APIs + (MapVirtualKey()) in Microsoft's Windows Store / UWP APIs. + * SDL_main. WinRT uses a different signature for each app's main() function + and requires it to be implemented in C++, so SDL_main.h must be #include'd + in a C++ source file, that also must be compiled with /ZW. + +* What doesn't work: + * compilation with anything other than Visual C++ + * programmatically-created custom cursors. These don't appear to be supported + by WinRT. Different OS-provided cursors can, however, be created via + SDL_CreateSystemCursor() (unsupported on Windows Phone) + * SDL_WarpMouseInWindow() or SDL_WarpMouseGlobal(). This are not currently + supported by WinRT itself. + * joysticks and game controllers that either are not supported by + Microsoft's XInput API, or are not supported within UWP apps (many + controllers that work in Win32, do not work in UWP, due to restrictions in + UWP itself). + * turning off VSync when rendering on Windows Phone. Attempts to turn VSync + off on Windows Phone result either in Direct3D not drawing anything, or it + forcing VSync back on. As such, SDL_RENDERER_PRESENTVSYNC will always get + turned-on on Windows Phone. This limitation is not present in non-Phone + WinRT (such as Windows 8.x), where turning off VSync appears to work. + * probably anything else that's not listed as supported + + + +Upgrade Notes +------------- + +#### SDL_GetPrefPath() usage when upgrading WinRT apps from SDL 2.0.3 + +SDL 2.0.4 fixes two bugs found in the WinRT version of SDL_GetPrefPath(). +The fixes may affect older, SDL 2.0.3-based apps' save data. Please note +that these changes only apply to SDL-based WinRT apps, and not to apps for +any other platform. + +1. SDL_GetPrefPath() would return an invalid path, one in which the path's + directory had not been created. Attempts to create files there + (via fopen(), for example), would fail, unless that directory was + explicitly created beforehand. + +2. SDL_GetPrefPath(), for non-WinPhone-based apps, would return a path inside + a WinRT 'Roaming' folder, the contents of which get automatically + synchronized across multiple devices. This process can occur while an + application runs, and can cause existing save-data to be overwritten + at unexpected times, with data from other devices. (Windows Phone apps + written with SDL 2.0.3 did not utilize a Roaming folder, due to API + restrictions in Windows Phone 8.0). + + +SDL_GetPrefPath(), starting with SDL 2.0.4, addresses these by: + +1. making sure that SDL_GetPrefPath() returns a directory in which data + can be written to immediately, without first needing to create directories. + +2. basing SDL_GetPrefPath() off of a different, non-Roaming folder, the + contents of which do not automatically get synchronized across devices + (and which require less work to use safely, in terms of data integrity). + +Apps that wish to get their Roaming folder's path can do so either by using +SDL_WinRTGetFSPathUTF8(), SDL_WinRTGetFSPathUNICODE() (which returns a +UCS-2/wide-char string), or directly through the WinRT class, +Windows.Storage.ApplicationData. + + + +Setup, High-Level Steps +----------------------- + +The steps for setting up a project for an SDL/WinRT app looks like the +following, at a high-level: + +1. create a new Visual C++ project using Microsoft's template for a, + "Direct3D App". +2. remove most of the files from the project. +3. make your app's project directly reference SDL/WinRT's own Visual C++ + project file, via use of Visual C++'s "References" dialog. This will setup + the linker, and will copy SDL's .dll files to your app's final output. +4. adjust your app's build settings, at minimum, telling it where to find SDL's + header files. +5. add files that contains a WinRT-appropriate main function, along with some + data to make sure mouse-cursor-hiding (via SDL_ShowCursor(SDL_DISABLE) calls) + work properly. +6. add SDL-specific app code. +7. build and run your app. + + +Setup, Detailed Steps +--------------------- + +### 1. Create a new project ### + +Create a new project using one of Visual C++'s templates for a plain, non-XAML, +"Direct3D App" (XAML support for SDL/WinRT is not yet ready for use). If you +don't see one of these templates, in Visual C++'s 'New Project' dialog, try +using the textbox titled, 'Search Installed Templates' to look for one. + + +### 2. Remove unneeded files from the project ### + +In the new project, delete any file that has one of the following extensions: + +- .cpp +- .h +- .hlsl + +When you are done, you should be left with a few files, each of which will be a +necessary part of your app's project. These files will consist of: + +- an .appxmanifest file, which contains metadata on your WinRT app. This is + similar to an Info.plist file on iOS, or an AndroidManifest.xml on Android. +- a few .png files, one of which is a splash screen (displayed when your app + launches), others are app icons. +- a .pfx file, used for code signing purposes. + + +### 3. Add references to SDL's project files ### + +SDL/WinRT can be built in multiple variations, spanning across three different +CPU architectures (x86, x64, and ARM) and two different configurations +(Debug and Release). WinRT and Visual C++ do not currently provide a means +for combining multiple variations of one library into a single file. +Furthermore, it does not provide an easy means for copying pre-built .dll files +into your app's final output (via Post-Build steps, for example). It does, +however, provide a system whereby an app can reference the MSVC projects of +libraries such that, when the app is built: + +1. each library gets built for the appropriate CPU architecture(s) and WinRT + platform(s). +2. each library's output, such as .dll files, get copied to the app's build + output. + +To set this up for SDL/WinRT, you'll need to run through the following steps: + +1. open up the Solution Explorer inside Visual C++ (under the "View" menu, then + "Solution Explorer") +2. right click on your app's solution. +3. navigate to "Add", then to "Existing Project..." +4. find SDL/WinRT's Visual C++ project file and open it, in the `VisualC-WinRT` + directory. +5. once the project has been added, right-click on your app's project and + select, "References..." +6. click on the button titled, "Add New Reference..." +7. check the box next to SDL +8. click OK to close the dialog +9. SDL will now show up in the list of references. Click OK to close that + dialog. + +Your project is now linked to SDL's project, insofar that when the app is +built, SDL will be built as well, with its build output getting included with +your app. + + +### 4. Adjust Your App's Build Settings ### + +Some build settings need to be changed in your app's project. This guide will +outline the following: + +- making sure that the compiler knows where to find SDL's header files +- **Optional for C++, but NECESSARY for compiling C code:** telling the + compiler not to use Microsoft's C++ extensions for WinRT development. +- **Optional:** telling the compiler not generate errors due to missing + precompiled header files. + +To change these settings: + +1. right-click on the project +2. choose "Properties" +3. in the drop-down box next to "Configuration", choose, "All Configurations" +4. in the drop-down box next to "Platform", choose, "All Platforms" +5. in the left-hand list, expand the "C/C++" section + **Note:** If you don't see this section, you may have to add a .c or .cpp + Source file to the Project first. +6. select "General" +7. edit the "Additional Include Directories" setting, and add a path to SDL's + "include" directory +8. **Optional: to enable compilation of C code:** change the setting for + "Consume Windows Runtime Extension" from "Yes (/ZW)" to "No". If you're + working with a completely C++ based project, this step can usually be + omitted. +9. **Optional: to disable precompiled headers (which can produce + 'stdafx.h'-related build errors, if setup incorrectly:** in the left-hand + list, select "Precompiled Headers", then change the setting for "Precompiled + Header" from "Use (/Yu)" to "Not Using Precompiled Headers". +10. close the dialog, saving settings, by clicking the "OK" button + + +### 5. Add a WinRT-appropriate main function, and a blank-cursor image, to the app. ### + +A few files should be included directly in your app's MSVC project, specifically: +1. a WinRT-appropriate main function (which is different than main() functions on + other platforms) +2. a Win32-style cursor resource, used by SDL_ShowCursor() to hide the mouse cursor + (if and when the app needs to do so). *If this cursor resource is not + included, mouse-position reporting may fail if and when the cursor is + hidden, due to possible bugs/design-oddities in Windows itself.* + +To include these files for C/C++ projects: + +1. right-click on your project (again, in Visual C++'s Solution Explorer), + navigate to "Add", then choose "Existing Item...". +2. navigate to the directory containing SDL's source code, then into its + subdirectory, 'src/main/winrt/'. Select, then add, the following files: + - `SDL3-WinRTResources.rc` + - `SDL3-WinRTResource_BlankCursor.cur` +3. For the next step you need a C++ source file. + - If your standard main() function is implemented in a **C++** source file, + use that file. + - If your standard main() function is implemented in a **plain C** source file, + create an empty .cpp source file (e.g. `main.cpp`) that only contains the line + `#include ` and use that file instead. +4. Right click on the C++ source file from step 3 (as listed in your project), + then click on "Properties...". +5. in the drop-down box next to "Configuration", choose, "All Configurations" +6. in the drop-down box next to "Platform", choose, "All Platforms" +7. in the left-hand list, click on "C/C++" +8. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)". +9. click the OK button. This will close the dialog. + +**NOTE: C++/CX compilation is currently required in at least one file of your +app's project. This is to make sure that Visual C++'s linker builds a 'Windows +Metadata' file (.winmd) for your app. Not doing so can lead to build errors.** + +For non-C++ projects, you will need to call SDL_RunApp from your language's +main function, and generate SDL3-WinRTResources.res manually by using `rc` via +the Developer Command Prompt and including it as a within the +first block in your Visual Studio project file. + +### 6. Add app code and assets ### + +At this point, you can add in SDL-specific source code. Be sure to include a +C-style main function (ie: `int main(int argc, char *argv[])`). From there you +should be able to create a single `SDL_Window` (WinRT apps can only have one +window, at present), as well as an `SDL_Renderer`. Direct3D will be used to +draw content. Events are received via SDL's usual event functions +(`SDL_PollEvent`, etc.) If you have a set of existing source files and assets, +you can start adding them to the project now. If not, or if you would like to +make sure that you're setup correctly, some short and simple sample code is +provided below. + + +#### 6.A. ... when creating a new app #### + +If you are creating a new app (rather than porting an existing SDL-based app), +or if you would just like a simple app to test SDL/WinRT with before trying to +get existing code working, some working SDL/WinRT code is provided below. To +set this up: + +1. right click on your app's project +2. select Add, then New Item. An "Add New Item" dialog will show up. +3. from the left-hand list, choose "Visual C++" +4. from the middle/main list, choose "C++ File (.cpp)" +5. near the bottom of the dialog, next to "Name:", type in a name for your +source file, such as, "main.cpp". +6. click on the Add button. This will close the dialog, add the new file to +your project, and open the file in Visual C++'s text editor. +7. Copy and paste the following code into the new file, then save it. + +```c +#include +#include + +int main(int argc, char **argv) +{ + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Event evt; + SDL_bool keep_going = SDL_TRUE; + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + return 1; + } else if (SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN, &window, &renderer) != 0) { + return 1; + } + + while (keep_going) { + while (SDL_PollEvent(&evt)) { + if ((evt.type == SDL_EVENT_KEY_DOWN) && (evt.key.keysym.sym == SDLK_ESCAPE)) { + keep_going = SDL_FALSE; + } + } + + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + } + + SDL_Quit(); + return 0; +} +``` + +#### 6.B. Adding code and assets #### + +If you have existing code and assets that you'd like to add, you should be able +to add them now. The process for adding a set of files is as such. + +1. right click on the app's project +2. select Add, then click on "New Item..." +3. open any source, header, or asset files as appropriate. Support for C and +C++ is available. + +Do note that WinRT only supports a subset of the APIs that are available to +Win32-based apps. Many portions of the Win32 API and the C runtime are not +available. + +A list of unsupported C APIs can be found at + + +General information on using the C runtime in WinRT can be found at + + +A list of supported Win32 APIs for WinRT apps can be found at +. To note, +the list of supported Win32 APIs for Windows Phone 8.0 is different. +That list can be found at + + + +### 7. Build and run your app ### + +Your app project should now be setup, and you should be ready to build your app. +To run it on the local machine, open the Debug menu and choose "Start +Debugging". This will build your app, then run your app full-screen. To switch +out of your app, press the Windows key. Alternatively, you can choose to run +your app in a window. To do this, before building and running your app, find +the drop-down menu in Visual C++'s toolbar that says, "Local Machine". Expand +this by clicking on the arrow on the right side of the list, then click on +Simulator. Once you do that, any time you build and run the app, the app will +launch in window, rather than full-screen. + + +#### 7.A. Running apps on older, ARM-based, "Windows RT" devices #### + +**These instructions do not include Windows Phone, despite Windows Phone +typically running on ARM processors.** They are specifically for devices +that use the "Windows RT" operating system, which was a modified version of +Windows 8.x that ran primarily on ARM-based tablet computers. + +To build and run the app on ARM-based, "Windows RT" devices, you'll need to: + +- install Microsoft's "Remote Debugger" on the device. Visual C++ installs and + debugs ARM-based apps via IP networks. +- change a few options on the development machine, both to make sure it builds + for ARM (rather than x86 or x64), and to make sure it knows how to find the + Windows RT device (on the network). + +Microsoft's Remote Debugger can be found at +. Please note +that separate versions of this debugger exist for different versions of Visual +C++, one each for MSVC 2015, 2013, and 2012. + +To setup Visual C++ to launch your app on an ARM device: + +1. make sure the Remote Debugger is running on your ARM device, and that it's on + the same IP network as your development machine. +2. from Visual C++'s toolbar, find a drop-down menu that says, "Win32". Click + it, then change the value to "ARM". +3. make sure Visual C++ knows the hostname or IP address of the ARM device. To + do this: + 1. open the app project's properties + 2. select "Debugging" + 3. next to "Machine Name", enter the hostname or IP address of the ARM + device + 4. if, and only if, you've turned off authentication in the Remote Debugger, + then change the setting for "Require Authentication" to No + 5. click "OK" +4. build and run the app (from Visual C++). The first time you do this, a + prompt will show up on the ARM device, asking for a Microsoft Account. You + do, unfortunately, need to log in here, and will need to follow the + subsequent registration steps in order to launch the app. After you do so, + if the app didn't already launch, try relaunching it again from within Visual + C++. + + +Troubleshooting +--------------- + +#### Build fails with message, "error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker'" + +Try adding the following to your linker flags. In MSVC, this can be done by +right-clicking on the app project, navigating to Configuration Properties -> +Linker -> Command Line, then adding them to the Additional Options +section. + +* For Release builds / MSVC-Configurations, add: + + /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib + +* For Debug builds / MSVC-Configurations, add: + + /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib + + +#### Mouse-motion events fail to get sent, or SDL_GetMouseState() fails to return updated values + +This may be caused by a bug in Windows itself, whereby hiding the mouse +cursor can cause mouse-position reporting to fail. + +SDL provides a workaround for this, but it requires that an app links to a +set of Win32-style cursor image-resource files. A copy of suitable resource +files can be found in `src/main/winrt/`. Adding them to an app's Visual C++ +project file should be sufficient to get the app to use them. + + +#### SDL's Visual Studio project file fails to open, with message, "The system can't find the file specified." + +This can be caused for any one of a few reasons, which Visual Studio can +report, but won't always do so in an up-front manner. + +To help determine why this error comes up: + +1. open a copy of Visual Studio without opening a project file. This can be + accomplished via Windows' Start Menu, among other means. +2. show Visual Studio's Output window. This can be done by going to VS' + menu bar, then to View, and then to Output. +3. try opening the SDL project file directly by going to VS' menu bar, then + to File, then to Open, then to Project/Solution. When a File-Open dialog + appears, open the SDL project (such as the one in SDL's source code, in its + directory, VisualC-WinRT/UWP_VS2015/). +4. after attempting to open SDL's Visual Studio project file, additional error + information will be output to the Output window. + +If Visual Studio reports (via its Output window) that the project: + +"could not be loaded because it's missing install components. To fix this launch Visual Studio setup with the following selections: +Microsoft.VisualStudio.ComponentGroup.UWP.VC" + +... then you will need to re-launch Visual Studio's installer, and make sure that +the workflow for "Universal Windows Platform development" is checked, and that its +optional component, "C++ Universal Windows Platform tools" is also checked. While +you are there, if you are planning on targeting UWP / Windows 10, also make sure +that you check the optional component, "Windows 10 SDK (10.0.10240.0)". After +making sure these items are checked as-appropriate, install them. + +Once you install these components, try re-launching Visual Studio, and re-opening +the SDL project file. If you still get the error dialog, try using the Output +window, again, seeing what Visual Studio says about it. + + +#### Game controllers / joysticks aren't working! + +Windows only permits certain game controllers and joysticks to work within +WinRT / UWP apps. Even if a game controller or joystick works in a Win32 +app, that device is not guaranteed to work inside a WinRT / UWP app. + +According to Microsoft, "Xbox compatible controllers" should work inside +UWP apps, potentially with more working in the future. This includes, but +may not be limited to, Microsoft-made Xbox controllers and USB adapters. +(Source: https://social.msdn.microsoft.com/Forums/en-US/9064838b-e8c3-4c18-8a83-19bf0dfe150d/xinput-fails-to-detect-game-controllers?forum=wpdevelop) + + diff --git a/docs/README.md b/docs/README.md index 661515c855d11..469a8394d25df 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,57 +1,57 @@ -# Simple DirectMedia Layer - -https://www.libsdl.org/ - -Simple DirectMedia Layer is a cross-platform development library designed -to provide low level access to audio, keyboard, mouse, joystick, and graphics -hardware via OpenGL and Direct3D. It is used by video playback software, -emulators, and popular games including Valve's award winning catalog -and many Humble Bundle games. - -SDL officially supports Windows, macOS, Linux, iOS, and Android. -Support for other platforms may be found in the source code. - -SDL is written in C, works natively with C++, and there are bindings -available for several other languages, including C# and Python. - -This library is distributed under the zlib license, which can be found -in the file "LICENSE.txt". - -The best way to learn how to use SDL is to check out the header files in -the "include" subdirectory and the programs in the "test" subdirectory. -The header files and test programs are well commented and always up to date. - -More documentation and FAQs are available online at [the wiki](http://wiki.libsdl.org/) - -- [Android](README-android.md) -- [CMake](README-cmake.md) -- [DynAPI](README-dynapi.md) -- [Emscripten](README-emscripten.md) -- [GDK](README-gdk.md) -- [Git](README-git.md) -- [iOS](README-ios.md) -- [Linux](README-linux.md) -- [macOS](README-macos.md) -- [Supported Platforms](README-platforms.md) -- [Porting information](README-porting.md) -- [PSP](README-psp.md) -- [PS2](README-ps2.md) -- [Raspberry Pi](README-raspberrypi.md) -- [Touch](README-touch.md) -- [Versions](README-versions.md) -- [Windows](README-windows.md) -- [WinRT](README-winrt.md) -- [PSVita](README-vita.md) -- [Nokia N-Gage](README-ngage.md) - -If you need help with the library, or just want to discuss SDL related -issues, you can join the [SDL Discourse](https://discourse.libsdl.org/), -which can be used as a web forum or a mailing list, at your preference. - -If you want to report bugs or contribute patches, please submit them to -[our bug tracker](https://github.com/libsdl-org/SDL/issues) - -Enjoy! - - -Sam Lantinga +# Simple DirectMedia Layer + +https://www.libsdl.org/ + +Simple DirectMedia Layer is a cross-platform development library designed +to provide low level access to audio, keyboard, mouse, joystick, and graphics +hardware via OpenGL and Direct3D. It is used by video playback software, +emulators, and popular games including Valve's award winning catalog +and many Humble Bundle games. + +SDL officially supports Windows, macOS, Linux, iOS, and Android. +Support for other platforms may be found in the source code. + +SDL is written in C, works natively with C++, and there are bindings +available for several other languages, including C# and Python. + +This library is distributed under the zlib license, which can be found +in the file "LICENSE.txt". + +The best way to learn how to use SDL is to check out the header files in +the "include" subdirectory and the programs in the "test" subdirectory. +The header files and test programs are well commented and always up to date. + +More documentation and FAQs are available online at [the wiki](http://wiki.libsdl.org/) + +- [Android](README-android.md) +- [CMake](README-cmake.md) +- [DynAPI](README-dynapi.md) +- [Emscripten](README-emscripten.md) +- [GDK](README-gdk.md) +- [Git](README-git.md) +- [iOS](README-ios.md) +- [Linux](README-linux.md) +- [macOS](README-macos.md) +- [Supported Platforms](README-platforms.md) +- [Porting information](README-porting.md) +- [PSP](README-psp.md) +- [PS2](README-ps2.md) +- [Raspberry Pi](README-raspberrypi.md) +- [Touch](README-touch.md) +- [Versions](README-versions.md) +- [Windows](README-windows.md) +- [WinRT](README-winrt.md) +- [PSVita](README-vita.md) +- [Nokia N-Gage](README-ngage.md) + +If you need help with the library, or just want to discuss SDL related +issues, you can join the [SDL Discourse](https://discourse.libsdl.org/), +which can be used as a web forum or a mailing list, at your preference. + +If you want to report bugs or contribute patches, please submit them to +[our bug tracker](https://github.com/libsdl-org/SDL/issues) + +Enjoy! + + +Sam Lantinga From eef5c536687750123bc3b9ef50b781684895a405 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 12:31:27 -0500 Subject: [PATCH 465/725] docs: Moved CREDITS and INSTALL to markdown format. --- CREDITS.md | 34 ++++++++++++++++++++++++++++ CREDITS.txt | 53 -------------------------------------------- INSTALL.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ INSTALL.txt | 43 ----------------------------------- 4 files changed, 98 insertions(+), 96 deletions(-) create mode 100644 CREDITS.md delete mode 100644 CREDITS.txt create mode 100644 INSTALL.md delete mode 100644 INSTALL.txt diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 0000000000000..370bcec0ffe9c --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,34 @@ +# Simple DirectMedia Layer CREDITS + +Thanks to everyone who made this possible, including: + +- Cliff Matthews, for giving me a reason to start this project. :) -- Executor rocks! *grin* +- Ryan Gordon for helping everybody out and keeping the dream alive. :) +- Gabriel Jacobo for his work on the Android port and generally helping out all around. +- Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches. +- Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code. +- Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve. +- Alfred Reynolds for the game controller API and general (in)sanity +- Jørgen Tjernø¸ for numerous magical macOS fixes. +- Pierre-Loup Griffais for his deep knowledge of OpenGL drivers. +- Julian Winter for the SDL 2.0 website. +- Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides. +- Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010. +- Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010. +- Jim Grandpre for his work on multi-touch and gesture recognition during + the Google Summer of Code 2010. +- Edgar "bobbens" Simo for his force feedback API development during the + Google Summer of Code 2008. +- Aaron Wishnick for his work on audio resampling and pitch shifting during + the Google Summer of Code 2008. +- Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the + Google Summer of Code 2008. +- Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation. +- Everybody at Loki Software, Inc. for their great contributions! + + And a big hand to everyone else who has contributed over the years. + +THANKS! :) + + -- Sam Lantinga + diff --git a/CREDITS.txt b/CREDITS.txt deleted file mode 100644 index 3243318b050ff..0000000000000 --- a/CREDITS.txt +++ /dev/null @@ -1,53 +0,0 @@ - -Simple DirectMedia Layer CREDITS -Thanks to everyone who made this possible, including: - -* Cliff Matthews, for giving me a reason to start this project. :) - -- Executor rocks! *grin* - -* Ryan Gordon for helping everybody out and keeping the dream alive. :) - -* Gabriel Jacobo for his work on the Android port and generally helping out all around. - -* Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches. - -* Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code. - -* Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve. - -* Alfred Reynolds for the game controller API and general (in)sanity - -* Jørgen Tjernø for numerous magical macOS fixes. - -* Pierre-Loup Griffais for his deep knowledge of OpenGL drivers. - -* Julian Winter for the SDL 2.0 website. - -* Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides. - -* Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010. - -* Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010. - -* Jim Grandpre for his work on multi-touch and gesture recognition during - the Google Summer of Code 2010. - -* Edgar "bobbens" Simo for his force feedback API development during the - Google Summer of Code 2008. - -* Aaron Wishnick for his work on audio resampling and pitch shifting during - the Google Summer of Code 2008. - -* Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the - Google Summer of Code 2008. - -* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation. - -* Everybody at Loki Software, Inc. for their great contributions! - - And a big hand to everyone else who has contributed over the years. - -THANKS! :) - - -- Sam Lantinga - diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000000000..f071eab0fc363 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,64 @@ +# To compile and install SDL: + +## Windows with Visual Studio: + +Read ./docs/README-visualc.md + +## Windows building with mingw-w64 for x86: + +Run: `cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build-scripts/cmake-toolchain-mingw64-i686.cmake && cmake --build build && cmake --install build` + +## Windows building with mingw-w64 for x64: + +Run: `cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build-scripts/cmake-toolchain-mingw64-x86_64.cmake && cmake --build build && cmake --install build` + +## macOS with Xcode: + +Read docs/README-macos.md + +## macOS from the command line: + +Run: `cmake -S . -B build && cmake --build build && cmake --install build` + +## Linux and other UNIX systems: + +Run: `cmake -S . -B build && cmake --build build && cmake --install build` + +## Android: + +Read docs/README-android.md + +## iOS: + +Read docs/README-ios.md + +## Using CMake: + +Read docs/README-cmake.md + +# Example code + +Look at the example programs in ./test, and check out the online +documentation at https://wiki.libsdl.org/SDL3/ + +# Discussion + +## Forums/mailing lists + +Join the SDL developer discussions, sign up on + +https://discourse.libsdl.org/ + +and go to the development forum + +https://discourse.libsdl.org/c/sdl-development/6 + +Once you sign up, you can use the forum through the website, or as a mailing +list from your email client. + +## Announcement list + +Sign up for the announcement list through the web interface: + +https://www.libsdl.org/mailing-list.php + diff --git a/INSTALL.txt b/INSTALL.txt deleted file mode 100644 index 9faadeb0fbd93..0000000000000 --- a/INSTALL.txt +++ /dev/null @@ -1,43 +0,0 @@ - -To compile and install SDL: - - 1. Windows with Visual Studio: - * Read ./docs/README-visualc.md - - Windows building with mingw-w64 for x86: - * Run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build-scripts/cmake-toolchain-mingw64-i686.cmake && cmake --build build && cmake --install build - - Windows building with mingw-w64 for x64: - * Run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build-scripts/cmake-toolchain-mingw64-x86_64.cmake && cmake --build build && cmake --install build - - macOS with Xcode: - * Read docs/README-macos.md - - macOS from the command line: - * Run: cmake -S . -B build && cmake --build build && cmake --install build - - Linux and other UNIX systems: - * Run: cmake -S . -B build && cmake --build build && cmake --install build - - Android: - * Read docs/README-android.md - - iOS: - * Read docs/README-ios.md - - Using Cmake: - * Read docs/README-cmake.md - - 2. Look at the example programs in ./test, and check out the online - documentation at https://wiki.libsdl.org/ - - 3. Join the SDL developer discussions, sign up on - https://discourse.libsdl.org/ - and go to the development forum - https://discourse.libsdl.org/c/sdl-development/6 - - 4. Sign up for the announcement list through the web interface: - https://www.libsdl.org/mailing-list.php - -That's it! -Sam Lantinga From dfee3f9e9209081b51f16436cd031f17d05ccee9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 25 Nov 2023 22:41:23 -0500 Subject: [PATCH 466/725] render: Replaced SDL_RenderFlush with SDL_FlushRenderer. This uses the same `SDL_VerbNoun` format as the rest of SDL3, and also adds stronger effort to invalidate cached state in the backend, so cooperation improves with apps that are using lowlevel rendering APIs directly. Fixes #367. --- build-scripts/SDL_migration.cocci | 7 ++++- docs/README-migration.md | 3 ++- include/SDL3/SDL_oldnames.h | 2 ++ include/SDL3/SDL_render.h | 19 +++++++++---- src/dynapi/SDL_dynapi.sym | 2 +- src/dynapi/SDL_dynapi_overrides.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 2 +- src/render/SDL_render.c | 8 ++++-- src/render/SDL_sysrender.h | 1 + src/render/direct3d/SDL_render_d3d.c | 12 +++++++++ src/render/direct3d11/SDL_render_d3d11.c | 14 ++++++++++ src/render/direct3d12/SDL_render_d3d12.c | 11 ++++++++ src/render/metal/SDL_render_metal.m | 6 +++++ src/render/opengl/SDL_render_gl.c | 34 +++++++++++++++++++++--- src/render/opengles2/SDL_render_gles2.c | 24 +++++++++++++++-- src/render/ps2/SDL_render_ps2.c | 6 +++++ src/render/psp/SDL_render_psp.c | 6 +++++ src/render/software/SDL_render_sw.c | 7 +++++ src/render/vitagxm/SDL_render_vita_gxm.c | 8 ++++++ 19 files changed, 156 insertions(+), 18 deletions(-) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index e4ac8a9899735..50e17402d0773 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -2749,4 +2749,9 @@ expression e, n, v; expression w, i, s; @@ - SDL_Vulkan_CreateSurface(w, i, s) -+ SDL_Vulkan_CreateSurface(w, i, NULL, s) \ No newline at end of file ++ SDL_Vulkan_CreateSurface(w, i, NULL, s) +@@ +@@ +- SDL_RenderFlush ++ SDL_FlushRenderer + (...) diff --git a/docs/README-migration.md b/docs/README-migration.md index a7a97015efa91..60de306e73c1b 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -816,7 +816,7 @@ The 2D renderer API always uses batching in SDL3. There is no magic to turn it on and off; it doesn't matter if you select a specific renderer or try to use any hint. This means that all apps that use SDL3's 2D renderer and also want to call directly into the platform's lower-layer graphics API _must_ call -SDL_RenderFlush() before doing so. This will make sure any pending rendering +SDL_FlushRenderer() before doing so. This will make sure any pending rendering work from SDL is done before the app starts directly drawing. SDL_GetRenderDriverInfo() has been removed, since most of the information it reported were @@ -868,6 +868,7 @@ The following functions have been renamed: * SDL_RenderDrawRectsF() => SDL_RenderRects() * SDL_RenderFillRectF() => SDL_RenderFillRect() * SDL_RenderFillRectsF() => SDL_RenderFillRects() +* SDL_RenderFlush() => SDL_FlushRenderer() * SDL_RenderGetClipRect() => SDL_GetRenderClipRect() * SDL_RenderGetIntegerScale() => SDL_GetRenderIntegerScale() * SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalPresentation() diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 39b1a61598cd2..bfe64d4f5d8aa 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -394,6 +394,7 @@ #define SDL_RenderDrawRectsF SDL_RenderRects #define SDL_RenderFillRectF SDL_RenderFillRect #define SDL_RenderFillRectsF SDL_RenderFillRects +#define SDL_RenderFlush SDL_FlushRenderer #define SDL_RenderGetClipRect SDL_GetRenderClipRect #define SDL_RenderGetLogicalSize SDL_GetRenderLogicalPresentation #define SDL_RenderGetMetalCommandEncoder SDL_GetRenderMetalCommandEncoder @@ -838,6 +839,7 @@ #define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_renamed_SDL_RenderRects #define SDL_RenderFillRectF SDL_RenderFillRectF_renamed_SDL_RenderFillRect #define SDL_RenderFillRectsF SDL_RenderFillRectsF_renamed_SDL_RenderFillRects +#define SDL_RenderFlush SDL_RenderFlush_renamed_SDL_FlushRenderer #define SDL_RenderGetClipRect SDL_RenderGetClipRect_renamed_SDL_GetRenderClipRect #define SDL_RenderGetLogicalSize SDL_RenderGetLogicalSize_renamed_SDL_GetRenderLogicalPresentation #define SDL_RenderGetMetalCommandEncoder SDL_RenderGetMetalCommandEncoder_renamed_SDL_GetRenderMetalCommandEncoder diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index caff6f87a672f..d235e40ae41a4 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1552,27 +1552,36 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture *texture); extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); /** - * Force the rendering context to flush any pending commands to the underlying - * rendering API. + * Force the rendering context to flush any pending commands and state. * * You do not need to (and in fact, shouldn't) call this function unless you - * are planning to call into OpenGL/Direct3D/Metal/whatever directly in + * are planning to call into OpenGL/Direct3D/Metal/whatever directly, in * addition to using an SDL_Renderer. * * This is for a very-specific case: if you are using SDL's render API, and * you plan to make OpenGL/D3D/whatever calls in addition to SDL render API - * calls. If this applies, you should call SDL_RenderFlush() between calls to + * calls. If this applies, you should call this function between calls to * SDL's render API and the low-level API you're using in cooperation. * * In all other cases, you can ignore this function. * + * This call makes SDL flush any pending rendering work it was queueing up + * to do later in a single batch, and marks any internal cached state as + * invalid, so it'll prepare all its state again later, from scratch. + * + * This means you do not need to save state in your rendering code to protect + * the SDL renderer. However, there lots of arbitrary pieces of Direct3D + * and OpenGL state that can confuse things; you should use your best + * judgement and be prepared to make changes if specific state needs to be + * protected. + * * \param renderer the rendering context * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer *renderer); +extern DECLSPEC int SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer); /** diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 0cb08454f4315..5194954994a7d 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -107,6 +107,7 @@ SDL3_0.0.0 { SDL_FlashWindow; SDL_FlushEvent; SDL_FlushEvents; + SDL_FlushRenderer; SDL_GDKGetTaskQueue; SDL_GDKSuspendComplete; SDL_GL_BindTexture; @@ -512,7 +513,6 @@ SDL3_0.0.0 { SDL_RenderCoordinatesToWindow; SDL_RenderFillRect; SDL_RenderFillRects; - SDL_RenderFlush; SDL_RenderGeometry; SDL_RenderGeometryRaw; SDL_RenderLine; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index fcd77a293013d..478005db8f2a7 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -131,6 +131,7 @@ #define SDL_FlashWindow SDL_FlashWindow_REAL #define SDL_FlushEvent SDL_FlushEvent_REAL #define SDL_FlushEvents SDL_FlushEvents_REAL +#define SDL_FlushRenderer SDL_FlushRenderer_REAL #define SDL_GDKGetTaskQueue SDL_GDKGetTaskQueue_REAL #define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL #define SDL_GL_BindTexture SDL_GL_BindTexture_REAL @@ -536,7 +537,6 @@ #define SDL_RenderCoordinatesToWindow SDL_RenderCoordinatesToWindow_REAL #define SDL_RenderFillRect SDL_RenderFillRect_REAL #define SDL_RenderFillRects SDL_RenderFillRects_REAL -#define SDL_RenderFlush SDL_RenderFlush_REAL #define SDL_RenderGeometry SDL_RenderGeometry_REAL #define SDL_RenderGeometryRaw SDL_RenderGeometryRaw_REAL #define SDL_RenderLine SDL_RenderLine_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4149b05cd805b..17567ae673fd1 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -193,6 +193,7 @@ SDL_DYNAPI_PROC(void,SDL_FilterEvents,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, SDL_FlashOperation b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),) SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_FlushRenderer,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GL_BindTexture,(SDL_Texture *a, float *b, float *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GL_DeleteContext,(SDL_GLContext a),(a),return) @@ -580,7 +581,6 @@ SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesFromWindow,(SDL_Renderer *a, float b, f SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesToWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_RenderFillRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_RenderFillRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(int,SDL_RenderGeometry,(SDL_Renderer *a, SDL_Texture *b, const SDL_Vertex *c, int d, const int *e, int f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(int,SDL_RenderGeometryRaw,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_Color *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) SDL_DYNAPI_PROC(int,SDL_RenderLine,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index a9cd2105ad26f..464b8f2e3e400 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -265,9 +265,13 @@ static int FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture) return 0; } -int SDL_RenderFlush(SDL_Renderer *renderer) +int SDL_FlushRenderer(SDL_Renderer *renderer) { - return FlushRenderCommands(renderer); + if (FlushRenderCommands(renderer) == -1) { + return -1; + } + renderer->InvalidateCachedState(renderer); + return 0; } void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset) diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 54d2d151484ec..01bf8ec29a931 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -179,6 +179,7 @@ struct SDL_Renderer int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y); + void (*InvalidateCachedState)(SDL_Renderer *renderer); int (*RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); int (*UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 6a882ce0f101e..73a8a71508db6 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1086,6 +1086,17 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) return 0; } +static void D3D_InvalidateCachedState(SDL_Renderer *renderer) +{ + D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; + data->drawstate.viewport_dirty = SDL_TRUE; + data->drawstate.cliprect_enabled_dirty = SDL_TRUE; + data->drawstate.cliprect_dirty = SDL_TRUE; + data->drawstate.blend = SDL_BLENDMODE_INVALID; + data->drawstate.texture = NULL; + data->drawstate.shader = NULL; +} + static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; @@ -1586,6 +1597,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer->QueueDrawPoints = D3D_QueueDrawPoints; renderer->QueueDrawLines = D3D_QueueDrawPoints; /* lines and points queue vertices the same way. */ renderer->QueueGeometry = D3D_QueueGeometry; + renderer->InvalidateCachedState = D3D_InvalidateCachedState; renderer->RunCommandQueue = D3D_RunCommandQueue; renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->RenderPresent = D3D_RenderPresent; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 103eb21715f82..4119275e6f0b0 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -2124,6 +2124,19 @@ static void D3D11_DrawPrimitives(SDL_Renderer *renderer, D3D11_PRIMITIVE_TOPOLOG ID3D11DeviceContext_Draw(rendererData->d3dContext, (UINT)vertexCount, (UINT)vertexStart); } +static void D3D11_InvalidateCachedState(SDL_Renderer *renderer) +{ + D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; + data->currentRenderTargetView = NULL; + data->currentRasterizerState = NULL; + data->currentBlendState = NULL; + data->currentShader = NULL; + data->currentShaderResource = NULL; + data->currentSampler = NULL; + data->cliprectDirty = SDL_TRUE; + data->viewportDirty = SDL_TRUE; +} + static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; @@ -2454,6 +2467,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->QueueDrawPoints = D3D11_QueueDrawPoints; renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */ renderer->QueueGeometry = D3D11_QueueGeometry; + renderer->InvalidateCachedState = D3D11_InvalidateCachedState; renderer->RunCommandQueue = D3D11_RunCommandQueue; renderer->RenderReadPixels = D3D11_RenderReadPixels; renderer->RenderPresent = D3D11_RenderPresent; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index dee07a4898741..195371406e4f0 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -2587,6 +2587,16 @@ static void D3D12_DrawPrimitives(SDL_Renderer *renderer, D3D12_PRIMITIVE_TOPOLOG D3D_CALL(rendererData->commandList, DrawInstanced, (UINT)vertexCount, 1, (UINT)vertexStart, 0); } +static void D3D12_InvalidateCachedState(SDL_Renderer *renderer) +{ + D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata; + data->currentRenderTargetView.ptr = 0; + data->currentShaderResource.ptr = 0; + data->currentSampler.ptr = 0; + data->cliprectDirty = SDL_TRUE; + data->viewportDirty = SDL_TRUE; +} + static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; @@ -3008,6 +3018,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->QueueDrawPoints = D3D12_QueueDrawPoints; renderer->QueueDrawLines = D3D12_QueueDrawPoints; /* lines and points queue vertices the same way. */ renderer->QueueGeometry = D3D12_QueueGeometry; + renderer->InvalidateCachedState = D3D12_InvalidateCachedState; renderer->RunCommandQueue = D3D12_RunCommandQueue; renderer->RenderReadPixels = D3D12_RenderReadPixels; renderer->RenderPresent = D3D12_RenderPresent; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index dc2b6124b6094..983e079398857 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1310,6 +1310,11 @@ static SDL_bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cm return SDL_TRUE; } +static void METAL_InvalidateCachedState(SDL_Renderer *renderer) +{ + // METAL_DrawStateCache only exists during a run of METAL_RunCommandQueue, so there's nothing to invalidate! +} + static int METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { @autoreleasepool { @@ -1905,6 +1910,7 @@ in case we want to use it later (recreating the renderer) renderer->QueueDrawPoints = METAL_QueueDrawPoints; renderer->QueueDrawLines = METAL_QueueDrawLines; renderer->QueueGeometry = METAL_QueueGeometry; + renderer->InvalidateCachedState = METAL_InvalidateCachedState; renderer->RunCommandQueue = METAL_RunCommandQueue; renderer->RenderReadPixels = METAL_RenderReadPixels; renderer->RenderPresent = METAL_RenderPresent; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 04c5d51002680..8a102f649c7d9 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -75,10 +75,13 @@ typedef struct SDL_bool cliprect_dirty; SDL_Rect cliprect; SDL_bool texturing; + SDL_bool texturing_dirty; SDL_bool vertex_array; SDL_bool color_array; SDL_bool texture_array; + SDL_bool color_dirty; Uint32 color; + SDL_bool clear_color_dirty; Uint32 clear_color; } GL_DrawStateCache; @@ -450,7 +453,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr GL_ActivateRenderer(renderer); renderdata->drawstate.texture = NULL; /* we trash this state. */ - renderdata->drawstate.texturing = SDL_FALSE; /* we trash this state. */ + renderdata->drawstate.texturing_dirty = SDL_TRUE; /* we trash this state. */ if (texture->access == SDL_TEXTUREACCESS_TARGET && !renderdata->GL_EXT_framebuffer_object_supported) { @@ -1108,7 +1111,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const data->drawstate.shader = shader; } - if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) { + if (data->drawstate.texturing_dirty || ((cmd->data.draw.texture != NULL) != data->drawstate.texturing)) { if (!cmd->data.draw.texture) { data->glDisable(data->textype); data->drawstate.texturing = SDL_FALSE; @@ -1116,6 +1119,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const data->glEnable(data->textype); data->drawstate.texturing = SDL_TRUE; } + data->drawstate.texturing_dirty = SDL_FALSE; } vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS || cmd->command == SDL_RENDERCMD_DRAW_LINES || cmd->command == SDL_RENDERCMD_GEOMETRY; @@ -1193,6 +1197,25 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) return 0; } +static void GL_InvalidateCachedState(SDL_Renderer *renderer) +{ + GL_DrawStateCache *cache = &((GL_RenderData *)renderer->driverdata)->drawstate; + cache->viewport_dirty = SDL_TRUE; + cache->texture = NULL; + cache->drawablew = 0; + cache->drawableh = 0; + cache->blend = SDL_BLENDMODE_INVALID; + cache->shader = SHADER_INVALID; + cache->cliprect_enabled_dirty = SDL_TRUE; + cache->cliprect_dirty = SDL_TRUE; + cache->texturing_dirty = SDL_TRUE; + cache->vertex_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */ + cache->color_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */ + cache->texture_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */ + cache->color_dirty = SDL_TRUE; + cache->clear_color_dirty = SDL_TRUE; +} + static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { /* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */ @@ -1230,9 +1253,10 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo const Uint8 b = cmd->data.color.b; const Uint8 a = cmd->data.color.a; const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b); - if (color != data->drawstate.color) { + if ((data->drawstate.color_dirty) || (color != data->drawstate.color)) { data->glColor4ub((GLubyte)r, (GLubyte)g, (GLubyte)b, (GLubyte)a); data->drawstate.color = color; + data->drawstate.color_dirty = SDL_FALSE; } break; } @@ -1269,13 +1293,14 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo const Uint8 b = cmd->data.color.b; const Uint8 a = cmd->data.color.a; const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b); - if (color != data->drawstate.clear_color) { + if ((data->drawstate.clear_color_dirty) || (color != data->drawstate.clear_color)) { const GLfloat fr = ((GLfloat)r) * inv255f; const GLfloat fg = ((GLfloat)g) * inv255f; const GLfloat fb = ((GLfloat)b) * inv255f; const GLfloat fa = ((GLfloat)a) * inv255f; data->glClearColor(fr, fg, fb, fa); data->drawstate.clear_color = color; + data->drawstate.clear_color_dirty = SDL_FALSE; } if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) { @@ -1797,6 +1822,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea renderer->QueueDrawPoints = GL_QueueDrawPoints; renderer->QueueDrawLines = GL_QueueDrawLines; renderer->QueueGeometry = GL_QueueGeometry; + renderer->InvalidateCachedState = GL_InvalidateCachedState; renderer->RunCommandQueue = GL_RunCommandQueue; renderer->RenderReadPixels = GL_RenderReadPixels; renderer->RenderPresent = GL_RenderPresent; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 1eb17c6e17ad1..9ff464c591bbc 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -138,7 +138,9 @@ typedef struct SDL_bool cliprect_dirty; SDL_Rect cliprect; SDL_bool texturing; + SDL_bool texturing_dirty; Uint32 clear_color; + SDL_bool clear_color_dirty; int drawablew; int drawableh; GLES2_ProgramCacheEntry *program; @@ -949,7 +951,7 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co data->drawstate.cliprect_dirty = SDL_FALSE; } - if ((texture != NULL) != data->drawstate.texturing) { + if (data->drawstate.texturing_dirty || ((texture != NULL) != data->drawstate.texturing)) { if (!texture) { data->glDisableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD); data->drawstate.texturing = SDL_FALSE; @@ -957,6 +959,7 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co data->glEnableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD); data->drawstate.texturing = SDL_TRUE; } + data->drawstate.texturing_dirty = SDL_FALSE; } if (texture) { @@ -1150,6 +1153,21 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo return ret; } +static void GLES2_InvalidateCachedState(SDL_Renderer *renderer) +{ + GLES2_DrawStateCache *cache = &((GLES2_RenderData *)renderer->driverdata)->drawstate; + cache->viewport_dirty = SDL_TRUE; + cache->texture = NULL; + cache->blend = SDL_BLENDMODE_INVALID; + cache->cliprect_enabled_dirty = SDL_TRUE; + cache->cliprect_dirty = SDL_TRUE; + cache->texturing_dirty = SDL_TRUE; + cache->clear_color_dirty = SDL_TRUE; + cache->drawablew = 0; + cache->drawableh = 0; + cache->program = NULL; +} + static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; @@ -1233,13 +1251,14 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b; const Uint8 a = cmd->data.color.a; const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b); - if (color != data->drawstate.clear_color) { + if (data->drawstate.clear_color_dirty || (color != data->drawstate.clear_color)) { const GLfloat fr = ((GLfloat)r) * inv255f; const GLfloat fg = ((GLfloat)g) * inv255f; const GLfloat fb = ((GLfloat)b) * inv255f; const GLfloat fa = ((GLfloat)a) * inv255f; data->glClearColor(fr, fg, fb, fa); data->drawstate.clear_color = color; + data->drawstate.clear_color_dirty = SDL_FALSE; } if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) { @@ -2196,6 +2215,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c renderer->QueueDrawPoints = GLES2_QueueDrawPoints; renderer->QueueDrawLines = GLES2_QueueDrawLines; renderer->QueueGeometry = GLES2_QueueGeometry; + renderer->InvalidateCachedState = GLES2_InvalidateCachedState; renderer->RunCommandQueue = GLES2_RunCommandQueue; renderer->RenderReadPixels = GLES2_RenderReadPixels; renderer->RenderPresent = GLES2_RenderPresent; diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index 9d02c3e768abb..d21c005b4e097 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -446,6 +446,11 @@ int PS2_RenderPoints(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand * return 0; } +static void PS2_InvalidateCachedState(SDL_Renderer *renderer) +{ + /* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */ +} + static int PS2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { while (cmd) { @@ -656,6 +661,7 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre renderer->QueueDrawPoints = PS2_QueueDrawPoints; renderer->QueueDrawLines = PS2_QueueDrawPoints; renderer->QueueGeometry = PS2_QueueGeometry; + renderer->InvalidateCachedState = PS2_InvalidateCachedState; renderer->RunCommandQueue = PS2_RunCommandQueue; renderer->RenderReadPixels = PS2_RenderReadPixels; renderer->RenderPresent = PS2_RenderPresent; diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 3fe45e2af0bce..c2f8c31030151 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -1021,6 +1021,11 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state) *current = *state; } +static void PSP_InvalidateCachedState(SDL_Renderer *renderer) +{ + /* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */ +} + static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { PSP_RenderData *data = (PSP_RenderData *)renderer->driverdata; @@ -1325,6 +1330,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer->QueueFillRects = PSP_QueueFillRects; renderer->QueueCopy = PSP_QueueCopy; renderer->QueueCopyEx = PSP_QueueCopyEx; + renderer->InvalidateCachedState = PSP_InvalidateCachedState; renderer->RunCommandQueue = PSP_RunCommandQueue; renderer->RenderReadPixels = PSP_RenderReadPixels; renderer->RenderPresent = PSP_RenderPresent; diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 8f10ef7f0f769..5f70345d9bd10 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -658,6 +658,12 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate) } } +static void SW_InvalidateCachedState(SDL_Renderer *renderer) +{ + /* SW_DrawStateCache only lives during SW_RunCommandQueue, so nothing to do here! */ +} + + static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { SDL_Surface *surface = SW_ActivateRenderer(renderer); @@ -1134,6 +1140,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) renderer->QueueCopy = SW_QueueCopy; renderer->QueueCopyEx = SW_QueueCopyEx; renderer->QueueGeometry = SW_QueueGeometry; + renderer->InvalidateCachedState = SW_InvalidateCachedState; renderer->RunCommandQueue = SW_RunCommandQueue; renderer->RenderReadPixels = SW_RenderReadPixels; renderer->RenderPresent = SW_RenderPresent; diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index ec0fe146a507f..43cc0e2d213c2 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -89,6 +89,8 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd); +static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer); + static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, @@ -244,6 +246,7 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints; renderer->QueueDrawLines = VITA_GXM_QueueDrawLines; renderer->QueueGeometry = VITA_GXM_QueueGeometry; + renderer->InvalidateCachedState = VITA_GXM_InvalidateCachedState; renderer->RunCommandQueue = VITA_GXM_RunCommandQueue; renderer->RenderReadPixels = VITA_GXM_RenderReadPixels; renderer->RenderPresent = VITA_GXM_RenderPresent; @@ -929,6 +932,11 @@ static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd) return 0; } +static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer) +{ + /* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */ +} + static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; From dd47da8a5c2eeba75798ab796f66ee2d291da8a3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 11:15:48 -0500 Subject: [PATCH 467/725] gamepad: Replace GetNumMappings/GetMappingByIndex with a single function. Now it returns an array and optional count, to match other SDL3 APIs. --- build-scripts/SDL_migration.cocci | 10 --- docs/README-migration.md | 4 +- include/SDL3/SDL_gamepad.h | 17 ++--- include/SDL3/SDL_oldnames.h | 4 -- src/dynapi/SDL_dynapi.sym | 3 +- src/dynapi/SDL_dynapi_overrides.h | 3 +- src/dynapi/SDL_dynapi_procs.h | 3 +- src/joystick/SDL_gamepad.c | 100 +++++++++++++++++++----------- test/testcontroller.c | 13 ++-- 9 files changed, 78 insertions(+), 79 deletions(-) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 50e17402d0773..fb27a66f644d1 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -1240,21 +1240,11 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; (...) @@ @@ -- SDL_GameControllerMappingForIndex -+ SDL_GetGamepadMappingForIndex - (...) -@@ -@@ - SDL_GameControllerName + SDL_GetGamepadName (...) @@ @@ -- SDL_GameControllerNumMappings -+ SDL_GetNumGamepadMappings - (...) -@@ -@@ - SDL_GameControllerOpen + SDL_OpenGamepad (...) diff --git a/docs/README-migration.md b/docs/README-migration.md index 60de306e73c1b..14d172f76bda7 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -468,9 +468,7 @@ The following functions have been renamed: * SDL_GameControllerIsSensorEnabled() => SDL_GamepadSensorEnabled() * SDL_GameControllerMapping() => SDL_GetGamepadMapping() * SDL_GameControllerMappingForGUID() => SDL_GetGamepadMappingForGUID() -* SDL_GameControllerMappingForIndex() => SDL_GetGamepadMappingForIndex() * SDL_GameControllerName() => SDL_GetGamepadName() -* SDL_GameControllerNumMappings() => SDL_GetNumGamepadMappings() * SDL_GameControllerOpen() => SDL_OpenGamepad() * SDL_GameControllerPath() => SDL_GetGamepadPath() * SDL_GameControllerRumble() => SDL_RumbleGamepad() @@ -490,6 +488,8 @@ The following functions have been removed: * SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName() * SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath() * SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType() +* SDL_GameControllerNumMappings() - replaced with SDL_GetGamepadMappings() +* SDL_GameControllerMappingForIndex() replaced with SDL_GetGamepadMappings() The following symbols have been renamed: * SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index f0bf60e1603f8..6baeaf305af56 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -311,25 +311,16 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file); */ extern DECLSPEC int SDLCALL SDL_ReloadGamepadMappings(void); -/** - * Get the number of mappings installed. - * - * \returns the number of mappings. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC int SDLCALL SDL_GetNumGamepadMappings(void); - /** * Get the mapping at a particular index. * - * \param mapping_index mapping index - * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if - * the index is out of range. + * \param count On return, set to the number of mappings returned. Can be NULL. + * \returns an array of the mapping strings, NULL-terminated. Must be freed with SDL_free(). + * Returns NULL on error. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForIndex(int mapping_index); +extern DECLSPEC char ** SDLCALL SDL_GetGamepadMappings(int *count); /** * Get the gamepad mapping string for a given GUID. diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index bfe64d4f5d8aa..5e5042d9e4dc4 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -235,9 +235,7 @@ #define SDL_GameControllerIsSensorEnabled SDL_GamepadSensorEnabled #define SDL_GameControllerMapping SDL_GetGamepadMapping #define SDL_GameControllerMappingForGUID SDL_GetGamepadMappingForGUID -#define SDL_GameControllerMappingForIndex SDL_GetGamepadMappingForIndex #define SDL_GameControllerName SDL_GetGamepadName -#define SDL_GameControllerNumMappings SDL_GetNumGamepadMappings #define SDL_GameControllerOpen SDL_OpenGamepad #define SDL_GameControllerPath SDL_GetGamepadPath #define SDL_GameControllerRumble SDL_RumbleGamepad @@ -680,9 +678,7 @@ #define SDL_GameControllerMapping SDL_GameControllerMapping_renamed_SDL_GetGamepadMapping #define SDL_GameControllerMappingForDeviceIndex SDL_GameControllerMappingForDeviceIndex_renamed_SDL_GetGamepadMappingForDeviceIndex #define SDL_GameControllerMappingForGUID SDL_GameControllerMappingForGUID_renamed_SDL_GetGamepadMappingForGUID -#define SDL_GameControllerMappingForIndex SDL_GameControllerMappingForIndex_renamed_SDL_GetGamepadMappingForIndex #define SDL_GameControllerName SDL_GameControllerName_renamed_SDL_GetGamepadName -#define SDL_GameControllerNumMappings SDL_GameControllerNumMappings_renamed_SDL_GetNumGamepadMappings #define SDL_GameControllerOpen SDL_GameControllerOpen_renamed_SDL_OpenGamepad #define SDL_GameControllerPath SDL_GameControllerPath_renamed_SDL_GetGamepadPath #define SDL_GameControllerRumble SDL_GameControllerRumble_renamed_SDL_RumbleGamepad diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 5194954994a7d..4e8c1cf8721d4 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -189,7 +189,6 @@ SDL3_0.0.0 { SDL_GetGamepadJoystick; SDL_GetGamepadMapping; SDL_GetGamepadMappingForGUID; - SDL_GetGamepadMappingForIndex; SDL_GetGamepadName; SDL_GetGamepadPath; SDL_GetGamepadPlayerIndex; @@ -250,7 +249,6 @@ SDL3_0.0.0 { SDL_GetMouseState; SDL_GetNaturalDisplayOrientation; SDL_GetNumAllocations; - SDL_GetNumGamepadMappings; SDL_GetNumGamepadTouchpadFingers; SDL_GetNumGamepadTouchpads; SDL_GetNumJoystickAxes; @@ -963,6 +961,7 @@ SDL3_0.0.0 { SDL_GetBooleanProperty; SDL_CreateTextureWithProperties; SDL_CreateRendererWithProperties; + SDL_GetGamepadMappings; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 478005db8f2a7..8676e44138ca4 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -213,7 +213,6 @@ #define SDL_GetGamepadJoystick SDL_GetGamepadJoystick_REAL #define SDL_GetGamepadMapping SDL_GetGamepadMapping_REAL #define SDL_GetGamepadMappingForGUID SDL_GetGamepadMappingForGUID_REAL -#define SDL_GetGamepadMappingForIndex SDL_GetGamepadMappingForIndex_REAL #define SDL_GetGamepadName SDL_GetGamepadName_REAL #define SDL_GetGamepadPath SDL_GetGamepadPath_REAL #define SDL_GetGamepadPlayerIndex SDL_GetGamepadPlayerIndex_REAL @@ -274,7 +273,6 @@ #define SDL_GetMouseState SDL_GetMouseState_REAL #define SDL_GetNaturalDisplayOrientation SDL_GetNaturalDisplayOrientation_REAL #define SDL_GetNumAllocations SDL_GetNumAllocations_REAL -#define SDL_GetNumGamepadMappings SDL_GetNumGamepadMappings_REAL #define SDL_GetNumGamepadTouchpadFingers SDL_GetNumGamepadTouchpadFingers_REAL #define SDL_GetNumGamepadTouchpads SDL_GetNumGamepadTouchpads_REAL #define SDL_GetNumJoystickAxes SDL_GetNumJoystickAxes_REAL @@ -988,3 +986,4 @@ #define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL #define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL #define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL +#define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 17567ae673fd1..5cce83c8abaf2 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -272,7 +272,6 @@ SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceVendor,(SDL_JoystickID a),(a),retur SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetGamepadJoystick,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetGamepadMapping,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForGUID,(SDL_JoystickGUID a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForIndex,(int a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadName,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPath,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetGamepadPlayerIndex,(SDL_Gamepad *a),(a),return) @@ -333,7 +332,6 @@ SDL_DYNAPI_PROC(SDL_Window*,SDL_GetMouseFocus,(void),(),return) SDL_DYNAPI_PROC(Uint32,SDL_GetMouseState,(float *a, float *b),(a,b),return) SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetNaturalDisplayOrientation,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumAllocations,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetNumGamepadMappings,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumGamepadTouchpadFingers,(SDL_Gamepad *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetNumGamepadTouchpads,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickAxes,(SDL_Joystick *a),(a),return) @@ -1013,3 +1011,4 @@ SDL_DYNAPI_PROC(int,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, S SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index ec1120db71907..8347857e2644a 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -2002,29 +2002,6 @@ int SDL_AddGamepadMapping(const char *mapping) return retval; } -/* - * Get the number of mappings installed - */ -int SDL_GetNumGamepadMappings(void) -{ - int num_mappings = 0; - - SDL_LockJoysticks(); - { - GamepadMapping_t *mapping; - - for (mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { - if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { - continue; - } - ++num_mappings; - } - } - SDL_UnlockJoysticks(); - - return num_mappings; -} - /* * Create a mapping string for a mapping */ @@ -2081,33 +2058,82 @@ static char *CreateMappingString(GamepadMapping_t *mapping, SDL_JoystickGUID gui return pMappingString; } -/* - * Get the mapping at a particular index. - */ -char *SDL_GetGamepadMappingForIndex(int mapping_index) +char **SDL_GetGamepadMappings(int *count) { - char *retval = NULL; + int num_mappings = 0; + char **retval = NULL; + char **mappings = NULL; + + if (count) { + *count = 0; + } SDL_LockJoysticks(); - { - GamepadMapping_t *mapping; - for (mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { + for (GamepadMapping_t *mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + num_mappings++; + } + + size_t final_allocation = sizeof (char *); // for the NULL terminator element. + SDL_bool failed = SDL_FALSE; + mappings = (char **) SDL_calloc(num_mappings + 1, sizeof (char *)); + if (!mappings) { + failed = SDL_TRUE; + SDL_OutOfMemory(); + } else { + size_t i = 0; + for (GamepadMapping_t *mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { continue; } - if (mapping_index == 0) { - retval = CreateMappingString(mapping, mapping->guid); - break; + + char *mappingstr = CreateMappingString(mapping, mapping->guid); + if (!mappingstr) { + failed = SDL_TRUE; + break; // error string is already set. } - --mapping_index; + + SDL_assert(i < num_mappings); + mappings[i++] = mappingstr; + + final_allocation += SDL_strlen(mappingstr) + 1 + sizeof (char *); } } + SDL_UnlockJoysticks(); - if (!retval) { - SDL_SetError("Mapping not available"); + if (!failed) { + retval = (char **) SDL_malloc(final_allocation); + if (!retval) { + SDL_OutOfMemory(); + } else { + final_allocation -= (sizeof (char *) * num_mappings + 1); + char *strptr = (char *) (retval + (num_mappings + 1)); + for (int i = 0; i < num_mappings; i++) { + retval[i] = strptr; + const size_t slen = SDL_strlcpy(strptr, mappings[i], final_allocation) + 1; + SDL_assert(final_allocation >= slen); + final_allocation -= slen; + strptr += slen; + } + retval[num_mappings] = NULL; + + if (count) { + *count = num_mappings; + } + } + } + + if (mappings) { + for (int i = 0; i < num_mappings; i++) { + SDL_free(mappings[i]); + } + SDL_free(mappings); } + return retval; } diff --git a/test/testcontroller.c b/test/testcontroller.c index e7d7260bc6e08..f6d406e01fcb8 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1871,12 +1871,12 @@ static void loop(void *arg) int main(int argc, char *argv[]) { + SDL_bool show_mappings = SDL_FALSE; int i; float content_scale; int screen_width, screen_height; SDL_Rect area; int gamepad_index = -1; - SDL_bool show_mappings = SDL_FALSE; SDLTest_CommonState *state; /* Initialize test framework */ @@ -1937,16 +1937,15 @@ int main(int argc, char *argv[]) SDL_AddGamepadMappingsFromFile("gamecontrollerdb.txt"); if (show_mappings) { + int count = 0; + char **mappings = SDL_GetGamepadMappings(&count); int map_i; SDL_Log("Supported mappings:\n"); - for (map_i = 0; map_i < SDL_GetNumGamepadMappings(); ++map_i) { - char *mapping = SDL_GetGamepadMappingForIndex(map_i); - if (mapping) { - SDL_Log("\t%s\n", mapping); - SDL_free(mapping); - } + for (map_i = 0; map_i < count; ++map_i) { + SDL_Log("\t%s\n", mappings[map_i]); } SDL_Log("\n"); + SDL_free(mappings); } /* Create a window to display gamepad state */ From daa38dc79312955fa6cffcc1bc7cc90113e9a006 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 13:08:52 -0500 Subject: [PATCH 468/725] touch: Replace GetNumTouchDevices/GetTouchDevice with a single function. Now it returns an array and optional count, to match other SDL3 APIs. SDL_GetTouchName() was replaced with a function that takes an instance ID instead of an index, too. --- docs/README-migration.md | 7 +++++ docs/README-touch.md | 9 +++--- include/SDL3/SDL_touch.h | 36 ++++++++-------------- src/dynapi/SDL_dynapi.sym | 5 ++- src/dynapi/SDL_dynapi_overrides.h | 5 ++- src/dynapi/SDL_dynapi_procs.h | 5 ++- src/events/SDL_touch.c | 44 ++++++++++++++++----------- src/events/SDL_touch_c.h | 3 ++ src/video/windows/SDL_windowsevents.c | 2 +- 9 files changed, 61 insertions(+), 55 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 14d172f76bda7..f19c6159bc870 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1240,6 +1240,13 @@ If you were using this macro for other things besides SDL ticks values, you can SDL_GetNumTouchFingers() returns a negative error code if there was an error. +SDL_GetTouchName is replaced with SDL_GetTouchDeviceName(), which takes an SDL_TouchID instead of an index. + +The following functions have been removed: +* SDL_GetNumTouchDevices() - replaced with SDL_GetTouchDevices() +* SDL_GetTouchDevice() - replaced with SDL_GetTouchDevices() + + ## SDL_version.h SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0. diff --git a/docs/README-touch.md b/docs/README-touch.md index 569feb6063048..979252797e76e 100644 --- a/docs/README-touch.md +++ b/docs/README-touch.md @@ -47,11 +47,12 @@ These structures should _never_ be modified. The following functions are included from SDL_touch.h -To get a SDL_TouchID call SDL_GetTouchDevice(int index). -This returns a SDL_TouchID. -IMPORTANT: If the touch has been removed, or there is no touch with the given index, SDL_GetTouchDevice() will return 0. Be sure to check for this! +Devices are tracked by instance ID, of type SDL_TouchID. -The number of touch devices can be queried with SDL_GetNumTouchDevices(). +To get a list of available device SDL_TouchID values, call SDL_GetTouchDevices(). +This returns an array of device IDs, terminated by a zero ID. Optionally, you can +get a count of IDs by passing a non-NULL int* to SDL_GetTouchDevices() if you'd +rather not iterate the whole array to get this number. A SDL_TouchID may be used to get pointers to SDL_Finger. diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index fc96305d95e2d..9f3d216016d6a 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -65,46 +65,36 @@ typedef struct SDL_Finger /** - * Get the number of registered touch devices. + * Get a list of registered touch devices. * * On some platforms SDL first sees the touch device if it was actually used. - * Therefore SDL_GetNumTouchDevices() may return 0 although devices are + * Therefore the returned list might be empty, although devices are * available. After using all devices at least once the number will be * correct. * * This was fixed for Android in SDL 2.0.1. * - * \returns the number of registered touch devices. + * \param count a pointer filled in with the number of devices returned + * \returns a 0 terminated array of touch device IDs which should be + * freed with SDL_free(), or NULL on error; call SDL_GetError() for + * more details. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetTouchDevice */ -extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); +extern DECLSPEC SDL_TouchID *SDLCALL SDL_GetTouchDevices(int *count); /** - * Get the touch ID with the given index. - * - * \param index the touch device index - * \returns the touch ID with the given index on success or 0 if the index is - * invalid; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. + * Get the touch device name as reported from the driver. * - * \sa SDL_GetNumTouchDevices - */ -extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); - -/** - * Get the touch device name as reported from the driver or NULL if the index - * is invalid. + * You do not own the returned string, do not modify or free it. * - * \param index the touch device index - * \returns touch device name + * \param touchID the touch device instance ID. + * \returns touch device name, or NULL on error; call SDL_GetError() for + * more details. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char* SDLCALL SDL_GetTouchName(int index); +extern DECLSPEC const char* SDLCALL SDL_GetTouchDeviceName(SDL_TouchID touchID); /** * Get the type of the given touch device. diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 4e8c1cf8721d4..8d1bd4811ae38 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -255,7 +255,6 @@ SDL3_0.0.0 { SDL_GetNumJoystickButtons; SDL_GetNumJoystickHats; SDL_GetNumRenderDrivers; - SDL_GetNumTouchDevices; SDL_GetNumTouchFingers; SDL_GetNumVideoDrivers; SDL_GetOriginalMemoryFunctions; @@ -328,10 +327,8 @@ SDL3_0.0.0 { SDL_GetThreadName; SDL_GetTicks; SDL_GetTicksNS; - SDL_GetTouchDevice; SDL_GetTouchDeviceType; SDL_GetTouchFinger; - SDL_GetTouchName; SDL_GetVersion; SDL_GetVideoDriver; SDL_GetWindowBordersSize; @@ -962,6 +959,8 @@ SDL3_0.0.0 { SDL_CreateTextureWithProperties; SDL_CreateRendererWithProperties; SDL_GetGamepadMappings; + SDL_GetTouchDevices; + SDL_GetTouchDeviceName; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8676e44138ca4..3be07fa255298 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -279,7 +279,6 @@ #define SDL_GetNumJoystickButtons SDL_GetNumJoystickButtons_REAL #define SDL_GetNumJoystickHats SDL_GetNumJoystickHats_REAL #define SDL_GetNumRenderDrivers SDL_GetNumRenderDrivers_REAL -#define SDL_GetNumTouchDevices SDL_GetNumTouchDevices_REAL #define SDL_GetNumTouchFingers SDL_GetNumTouchFingers_REAL #define SDL_GetNumVideoDrivers SDL_GetNumVideoDrivers_REAL #define SDL_GetOriginalMemoryFunctions SDL_GetOriginalMemoryFunctions_REAL @@ -352,10 +351,8 @@ #define SDL_GetThreadName SDL_GetThreadName_REAL #define SDL_GetTicks SDL_GetTicks_REAL #define SDL_GetTicksNS SDL_GetTicksNS_REAL -#define SDL_GetTouchDevice SDL_GetTouchDevice_REAL #define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL #define SDL_GetTouchFinger SDL_GetTouchFinger_REAL -#define SDL_GetTouchName SDL_GetTouchName_REAL #define SDL_GetVersion SDL_GetVersion_REAL #define SDL_GetVideoDriver SDL_GetVideoDriver_REAL #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL @@ -987,3 +984,5 @@ #define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL #define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL #define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL +#define SDL_GetTouchDevices SDL_GetTouchDevices_REAL +#define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 5cce83c8abaf2..0ae19f03064ca 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -338,7 +338,6 @@ SDL_DYNAPI_PROC(int,SDL_GetNumJoystickAxes,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickButtons,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickHats,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumRenderDrivers,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetNumTouchDevices,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumTouchFingers,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumVideoDrivers,(void),(),return) SDL_DYNAPI_PROC(void,SDL_GetOriginalMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),) @@ -411,10 +410,8 @@ SDL_DYNAPI_PROC(SDL_threadID,SDL_GetThreadID,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetThreadName,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetTicks,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetTicksNS,(void),(),return) -SDL_DYNAPI_PROC(SDL_TouchID,SDL_GetTouchDevice,(int a),(a),return) SDL_DYNAPI_PROC(SDL_TouchDeviceType,SDL_GetTouchDeviceType,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(SDL_Finger*,SDL_GetTouchFinger,(SDL_TouchID a, int b),(a,b),return) -SDL_DYNAPI_PROC(const char*,SDL_GetTouchName,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetVersion,(SDL_version *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetVideoDriver,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) @@ -1012,3 +1009,5 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return) +SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 9671f49b46bf5..08e570909fd8a 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -44,27 +44,32 @@ int SDL_InitTouch(void) return 0; } -int SDL_GetNumTouchDevices(void) +SDL_bool SDL_TouchDevicesAvailable(void) { - return SDL_num_touch; + return SDL_num_touch > 0; } -SDL_TouchID SDL_GetTouchDevice(int index) +SDL_TouchID *SDL_GetTouchDevices(int *count) { - if (index < 0 || index >= SDL_num_touch) { - SDL_SetError("Unknown touch device index %d", index); - return 0; + if (count) { + *count = 0; } - return SDL_touchDevices[index]->id; -} -const char *SDL_GetTouchName(int index) -{ - if (index < 0 || index >= SDL_num_touch) { - SDL_SetError("Unknown touch device"); - return NULL; + const int total = SDL_num_touch; + SDL_TouchID *retval = (SDL_TouchID *) SDL_malloc(sizeof (SDL_TouchID) * (total + 1)); + if (!retval) { + SDL_OutOfMemory(); + } else { + for (int i = 0; i < total; i++) { + retval[i] = SDL_touchDevices[i]->id; + } + retval[total] = 0; + if (count) { + *count = SDL_num_touch; + } } - return SDL_touchDevices[index]->name; + + return retval; } static int SDL_GetTouchIndex(SDL_TouchID id) @@ -96,13 +101,16 @@ SDL_Touch *SDL_GetTouch(SDL_TouchID id) return SDL_touchDevices[index]; } +const char *SDL_GetTouchDeviceName(SDL_TouchID id) +{ + SDL_Touch *touch = SDL_GetTouch(id); + return touch ? touch->name : NULL; +} + SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id) { SDL_Touch *touch = SDL_GetTouch(id); - if (touch) { - return touch->type; - } - return SDL_TOUCH_DEVICE_INVALID; + return touch ? touch->type : SDL_TOUCH_DEVICE_INVALID; } static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid) diff --git a/src/events/SDL_touch_c.h b/src/events/SDL_touch_c.h index c768de8a3d240..34d7e290b618a 100644 --- a/src/events/SDL_touch_c.h +++ b/src/events/SDL_touch_c.h @@ -36,6 +36,9 @@ typedef struct SDL_Touch /* Initialize the touch subsystem */ extern int SDL_InitTouch(void); +/* Returns SDL_TRUE if _any_ connected touch devices are known to SDL */ +extern SDL_bool SDL_TouchDevicesAvailable(void); + /* Add a touch, returning the index of the touch, or -1 if there was an error. */ extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *name); diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 8624b92dc9d50..620ab332bd1be 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -668,7 +668,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (inp.header.dwType == RIM_TYPEMOUSE) { SDL_MouseID mouseID; RAWMOUSE *rawmouse; - if (SDL_GetNumTouchDevices() > 0 && + if (SDL_TouchDevicesAvailable() && (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x82) == 0x82)) { break; } From d1b831e2329dc79505396b1eef20fef87225afdd Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 15:56:26 -0500 Subject: [PATCH 469/725] include: Clarified documentation for two functions. --- include/SDL3/SDL_gamepad.h | 5 ++++- include/SDL3/SDL_touch.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 6baeaf305af56..bc1d9c47b654e 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -314,7 +314,10 @@ extern DECLSPEC int SDLCALL SDL_ReloadGamepadMappings(void); /** * Get the mapping at a particular index. * - * \param count On return, set to the number of mappings returned. Can be NULL. + * You must free the returned pointer with SDL_free() when you are done with + * it, but you do _not_ free each string in the array. + * + * \param count a pointer filled in with the number of mappings returned, can be NULL. * \returns an array of the mapping strings, NULL-terminated. Must be freed with SDL_free(). * Returns NULL on error. * diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index 9f3d216016d6a..26558c7dbfc56 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -74,7 +74,7 @@ typedef struct SDL_Finger * * This was fixed for Android in SDL 2.0.1. * - * \param count a pointer filled in with the number of devices returned + * \param count a pointer filled in with the number of devices returned, can be NULL. * \returns a 0 terminated array of touch device IDs which should be * freed with SDL_free(), or NULL on error; call SDL_GetError() for * more details. From 70b65d4170bbff6a8c2ffc9b5834ec85384f6fc0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Nov 2023 21:38:41 -0500 Subject: [PATCH 470/725] cocoa: Resync modifier keypressed on NSEventTypeFlagsChanged event. Fixes #7507. --- src/video/cocoa/SDL_cocoakeyboard.m | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m index 9334c7ab2df5e..957c7ac5201d9 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.m +++ b/src/video/cocoa/SDL_cocoakeyboard.m @@ -435,9 +435,19 @@ void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event) case NSEventTypeKeyUp: SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_RELEASED, code); break; - case NSEventTypeFlagsChanged: - HandleModifiers(_this, code, (unsigned int)[event modifierFlags]); + case NSEventTypeFlagsChanged: { + // see if the new modifierFlags mean any existing keys should be pressed/released... + const unsigned int modflags = (unsigned int)[event modifierFlags]; + HandleModifiers(_this, SDL_SCANCODE_LSHIFT, modflags); + HandleModifiers(_this, SDL_SCANCODE_LCTRL, modflags); + HandleModifiers(_this, SDL_SCANCODE_LALT, modflags); + HandleModifiers(_this, SDL_SCANCODE_LGUI, modflags); + HandleModifiers(_this, SDL_SCANCODE_RSHIFT, modflags); + HandleModifiers(_this, SDL_SCANCODE_RCTRL, modflags); + HandleModifiers(_this, SDL_SCANCODE_RALT, modflags); + HandleModifiers(_this, SDL_SCANCODE_RGUI, modflags); break; + } default: /* just to avoid compiler warnings */ break; } From 447b508a77b8601d23ca48cf189fe4436ab33572 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 30 Nov 2023 00:14:27 -0500 Subject: [PATCH 471/725] error: SDL's allocators now call SDL_OutOfMemory on error. This means the allocator's caller doesn't need to use SDL_OutOfMemory directly if the allocation fails. This applies to the usual allocators: SDL_malloc, SDL_calloc, SDL_realloc (all of these regardless of if the app supplied a custom allocator or we're using system malloc() or an internal copy of dlmalloc under the hood), SDL_aligned_alloc, SDL_small_alloc, SDL_strdup, SDL_asprintf, SDL_wcsdup... probably others. If it returns something you can pass to SDL_free, it should work. The caller might still need to use SDL_OutOfMemory if something that wasn't SDL allocated the memory: operator new in C++ code, Objective-C's alloc message, win32 GlobalAlloc, etc. Fixes #8642. --- src/SDL_hashtable.c | 3 -- src/SDL_hints.c | 6 +-- src/SDL_list.c | 2 +- src/SDL_properties.c | 18 +++----- src/audio/SDL_audio.c | 16 +++---- src/audio/SDL_audiocvt.c | 8 +--- src/audio/SDL_audioqueue.c | 8 ++-- src/audio/SDL_wave.c | 30 ++++++------- src/audio/aaudio/SDL_aaudio.c | 4 +- src/audio/alsa/SDL_alsa_audio.c | 4 +- src/audio/android/SDL_androidaudio.c | 2 +- src/audio/coreaudio/SDL_coreaudio.m | 4 +- src/audio/directsound/SDL_directsound.c | 2 +- src/audio/disk/SDL_diskaudio.c | 4 +- src/audio/dsp/SDL_dspaudio.c | 4 +- src/audio/dummy/SDL_dummyaudio.c | 4 +- src/audio/emscripten/SDL_emscriptenaudio.c | 4 +- src/audio/jack/SDL_jackaudio.c | 6 +-- src/audio/n3ds/SDL_n3dsaudio.c | 4 +- src/audio/netbsd/SDL_netbsdaudio.c | 4 +- src/audio/openslES/SDL_openslES.c | 2 +- src/audio/pipewire/SDL_pipewire.c | 3 +- src/audio/ps2/SDL_ps2audio.c | 2 +- src/audio/psp/SDL_pspaudio.c | 2 +- src/audio/pulseaudio/SDL_pulseaudio.c | 4 +- src/audio/qnx/SDL_qsa_audio.c | 4 +- src/audio/sndio/SDL_sndioaudio.c | 6 +-- src/audio/vita/SDL_vitaaudio.c | 5 +-- src/audio/wasapi/SDL_wasapi.c | 4 +- src/core/linux/SDL_evdev.c | 12 +++--- src/core/linux/SDL_udev.c | 4 +- src/core/windows/SDL_immdevice.c | 2 - src/events/SDL_events.c | 3 -- src/events/SDL_mouse.c | 5 +-- src/events/SDL_touch.c | 12 +++--- src/file/SDL_rwops.c | 9 +--- src/file/n3ds/SDL_rwopsromfs.c | 1 - src/filesystem/android/SDL_sysfilesystem.c | 1 - src/filesystem/cocoa/SDL_sysfilesystem.m | 17 ++------ src/filesystem/emscripten/SDL_sysfilesystem.c | 10 +---- src/filesystem/gdk/SDL_sysfilesystem.cpp | 1 - src/filesystem/haiku/SDL_sysfilesystem.cc | 21 +++------ src/filesystem/n3ds/SDL_sysfilesystem.c | 1 - src/filesystem/riscos/SDL_sysfilesystem.c | 3 -- src/filesystem/unix/SDL_sysfilesystem.c | 15 +------ src/filesystem/vita/SDL_sysfilesystem.c | 1 - src/filesystem/windows/SDL_sysfilesystem.c | 3 -- src/filesystem/winrt/SDL_sysfilesystem.cpp | 3 -- src/haptic/SDL_haptic.c | 2 - src/haptic/android/SDL_syshaptic.c | 1 - src/haptic/darwin/SDL_syshaptic.c | 43 +++++++------------ src/haptic/linux/SDL_syshaptic.c | 9 ++-- src/haptic/windows/SDL_dinputhaptic.c | 42 ++++++++---------- src/haptic/windows/SDL_windowshaptic.c | 5 +-- src/haptic/windows/SDL_xinputhaptic.c | 13 +++--- src/joystick/SDL_gamepad.c | 27 ++---------- src/joystick/SDL_joystick.c | 5 --- src/joystick/apple/SDL_mfijoystick.m | 2 - src/joystick/bsd/SDL_bsdjoystick.c | 3 +- src/joystick/darwin/SDL_iokitjoystick.c | 3 +- src/joystick/haiku/SDL_haikujoystick.cc | 14 +++--- src/joystick/hidapi/SDL_hidapi_gamecube.c | 1 - src/joystick/hidapi/SDL_hidapi_luna.c | 1 - src/joystick/hidapi/SDL_hidapi_ps3.c | 2 - src/joystick/hidapi/SDL_hidapi_ps4.c | 1 - src/joystick/hidapi/SDL_hidapi_ps5.c | 1 - src/joystick/hidapi/SDL_hidapi_rumble.c | 2 +- src/joystick/hidapi/SDL_hidapi_shield.c | 1 - src/joystick/hidapi/SDL_hidapi_stadia.c | 1 - src/joystick/hidapi/SDL_hidapi_steam.c | 1 - src/joystick/hidapi/SDL_hidapi_switch.c | 1 - src/joystick/hidapi/SDL_hidapi_wii.c | 1 - src/joystick/hidapi/SDL_hidapi_xbox360.c | 1 - src/joystick/hidapi/SDL_hidapi_xbox360w.c | 1 - src/joystick/hidapi/SDL_hidapi_xboxone.c | 1 - src/joystick/hidapi/SDL_hidapijoystick.c | 2 +- src/joystick/linux/SDL_sysjoystick.c | 6 +-- src/joystick/virtual/SDL_virtualjoystick.c | 8 ++-- src/joystick/windows/SDL_dinputjoystick.c | 2 +- src/joystick/windows/SDL_rawinputjoystick.c | 14 +++--- .../windows/SDL_windows_gaming_input.c | 3 +- src/joystick/windows/SDL_windowsjoystick.c | 6 +-- src/locale/SDL_locale.c | 1 - src/locale/unix/SDL_syslocale.c | 2 +- src/locale/windows/SDL_syslocale.c | 2 +- src/misc/windows/SDL_sysurl.c | 2 +- src/misc/winrt/SDL_sysurl.cpp | 2 +- src/render/SDL_render.c | 19 ++++---- src/render/SDL_yuv_sw.c | 3 -- src/render/direct3d/SDL_render_d3d.c | 6 +-- src/render/direct3d11/SDL_render_d3d11.c | 6 +-- src/render/direct3d12/SDL_render_d3d12.c | 6 +-- src/render/metal/SDL_render_metal.m | 5 +-- src/render/opengl/SDL_render_gl.c | 8 ++-- src/render/opengles2/SDL_render_gles2.c | 11 ++--- src/render/ps2/SDL_render_ps2.c | 6 +-- src/render/psp/SDL_render_psp.c | 12 +++--- src/render/software/SDL_render_sw.c | 2 - src/render/vitagxm/SDL_render_vita_gxm.c | 6 +-- src/sensor/SDL_sensor.c | 3 -- src/sensor/android/SDL_androidsensor.c | 2 +- src/sensor/coremotion/SDL_coremotionsensor.m | 4 +- src/sensor/vita/SDL_vitasensor.c | 4 +- src/sensor/windows/SDL_windowssensor.c | 4 +- src/stdlib/SDL_malloc.c | 9 ++++ src/test/SDL_test_common.c | 1 - src/thread/SDL_thread.c | 9 +--- src/thread/generic/SDL_syscond.c | 2 - src/thread/generic/SDL_sysmutex.c | 2 - src/thread/generic/SDL_sysrwlock.c | 1 - src/thread/generic/SDL_syssem.c | 1 - src/thread/n3ds/SDL_syscond.c | 2 - src/thread/n3ds/SDL_sysmutex.c | 2 - src/thread/n3ds/SDL_syssem.c | 1 - src/thread/ps2/SDL_syssem.c | 2 - src/thread/psp/SDL_syscond.c | 2 - src/thread/psp/SDL_sysmutex.c | 2 - src/thread/psp/SDL_syssem.c | 2 - src/thread/pthread/SDL_sysmutex.c | 2 - src/thread/pthread/SDL_sysrwlock.c | 2 - src/thread/pthread/SDL_syssem.c | 2 - src/thread/vita/SDL_syscond.c | 2 - src/thread/vita/SDL_sysmutex.c | 2 - src/thread/vita/SDL_syssem.c | 2 - src/thread/windows/SDL_syscond_cv.c | 15 ++----- src/thread/windows/SDL_sysmutex.c | 13 ++---- src/thread/windows/SDL_sysrwlock_srw.c | 5 +-- src/thread/windows/SDL_syssem.c | 9 +--- src/timer/SDL_timer.c | 3 -- src/video/SDL_RLEaccel.c | 4 +- src/video/SDL_clipboard.c | 4 +- src/video/SDL_egl.c | 2 +- src/video/SDL_pixels.c | 6 --- src/video/SDL_surface.c | 4 -- src/video/SDL_video.c | 11 +---- src/video/SDL_vulkan_utils.c | 6 --- src/video/SDL_yuv.c | 14 +++--- src/video/android/SDL_androidmouse.c | 3 -- src/video/android/SDL_androidvideo.c | 2 - src/video/android/SDL_androidwindow.c | 2 +- src/video/cocoa/SDL_cocoaclipboard.m | 2 - src/video/cocoa/SDL_cocoamouse.m | 2 +- src/video/cocoa/SDL_cocoavideo.m | 1 - src/video/cocoa/SDL_cocoawindow.m | 1 - src/video/dummy/SDL_nullvideo.c | 1 - src/video/emscripten/SDL_emscriptenmouse.c | 7 +-- src/video/emscripten/SDL_emscriptenvideo.c | 3 +- src/video/gdk/SDL_gdktextinput.cpp | 10 +---- src/video/haiku/SDL_bvideo.cc | 2 - src/video/kmsdrm/SDL_kmsdrmmouse.c | 5 +-- src/video/kmsdrm/SDL_kmsdrmvideo.c | 11 ++--- src/video/n3ds/SDL_n3dsframebuffer.c | 2 +- src/video/n3ds/SDL_n3dsvideo.c | 5 +-- src/video/ngage/SDL_ngagevideo.cpp | 2 - src/video/ngage/SDL_ngagewindow.cpp | 2 +- src/video/offscreen/SDL_offscreenvideo.c | 1 - src/video/offscreen/SDL_offscreenwindow.c | 2 +- src/video/ps2/SDL_ps2video.c | 1 - src/video/psp/SDL_pspvideo.c | 5 +-- src/video/raspberry/SDL_rpimouse.c | 2 - src/video/raspberry/SDL_rpivideo.c | 4 +- src/video/riscos/SDL_riscosframebuffer.c | 2 +- src/video/riscos/SDL_riscosmodes.c | 6 +-- src/video/riscos/SDL_riscosmouse.c | 6 +-- src/video/riscos/SDL_riscosvideo.c | 2 - src/video/riscos/SDL_riscoswindow.c | 2 +- src/video/uikit/SDL_uikitvideo.m | 12 +++--- src/video/vita/SDL_vitavideo.c | 5 +-- src/video/vivante/SDL_vivantevideo.c | 6 +-- src/video/wayland/SDL_waylanddatamanager.c | 12 +++--- src/video/wayland/SDL_waylandevents.c | 18 ++------ src/video/wayland/SDL_waylandmessagebox.c | 2 +- src/video/wayland/SDL_waylandmouse.c | 15 +------ src/video/wayland/SDL_waylandvideo.c | 2 - src/video/wayland/SDL_waylandwindow.c | 2 +- src/video/windows/SDL_windowsclipboard.c | 2 - src/video/windows/SDL_windowsframebuffer.c | 2 +- src/video/windows/SDL_windowsmessagebox.c | 1 - src/video/windows/SDL_windowsmouse.c | 10 +---- src/video/windows/SDL_windowsopengl.c | 2 +- src/video/windows/SDL_windowsvideo.c | 1 - src/video/windows/SDL_windowswindow.c | 4 +- src/video/winrt/SDL_winrtmouse.cpp | 2 - src/video/winrt/SDL_winrtvideo.cpp | 3 -- src/video/x11/SDL_x11clipboard.c | 4 +- src/video/x11/SDL_x11framebuffer.c | 2 +- src/video/x11/SDL_x11messagebox.c | 4 +- src/video/x11/SDL_x11modes.c | 8 ++-- src/video/x11/SDL_x11mouse.c | 16 +------ src/video/x11/SDL_x11opengl.c | 2 +- src/video/x11/SDL_x11video.c | 2 - src/video/x11/SDL_x11window.c | 9 ++-- src/video/x11/SDL_x11xinput2.c | 1 - test/testffmpeg.c | 3 -- test/testshape.c | 2 +- test/testutils.c | 18 ++------ test/testvulkan.c | 6 --- 197 files changed, 313 insertions(+), 742 deletions(-) diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 0b898059853fb..b6a8b0d49cd34 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -54,14 +54,12 @@ SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const S table = (SDL_HashTable *) SDL_calloc(1, sizeof (SDL_HashTable)); if (!table) { - SDL_OutOfMemory(); return NULL; } table->table = (SDL_HashItem **) SDL_calloc(num_buckets, sizeof (SDL_HashItem *)); if (!table->table) { SDL_free(table); - SDL_OutOfMemory(); return NULL; } @@ -92,7 +90,6 @@ SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const vo // !!! FIXME: grow and rehash table if it gets too saturated. item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem)); if (!item) { - SDL_OutOfMemory(); return SDL_FALSE; } diff --git a/src/SDL_hints.c b/src/SDL_hints.c index 3e792c6d50e19..e45823a4ebb1c 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -226,7 +226,7 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); if (!entry) { - return SDL_OutOfMemory(); + return -1; } entry->callback = callback; entry->userdata = userdata; @@ -241,13 +241,13 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); if (!hint) { SDL_free(entry); - return SDL_OutOfMemory(); + return -1; } hint->name = SDL_strdup(name); if (!hint->name) { SDL_free(entry); SDL_free(hint); - return SDL_OutOfMemory(); + return -1; } hint->value = NULL; hint->priority = SDL_HINT_DEFAULT; diff --git a/src/SDL_list.c b/src/SDL_list.c index 64c39245e62a4..b6ea10d105c0d 100644 --- a/src/SDL_list.c +++ b/src/SDL_list.c @@ -28,7 +28,7 @@ int SDL_ListAdd(SDL_ListNode **head, void *ent) SDL_ListNode *node = SDL_malloc(sizeof(*node)); if (!node) { - return SDL_OutOfMemory(); + return -1; } node->entry = ent; diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 92c260fc14609..b883a4d37dcd1 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -271,7 +271,7 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_POINTER; property->value.pointer_value = value; @@ -290,7 +290,7 @@ int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_POINTER; property->value.pointer_value = value; @@ -308,13 +308,13 @@ int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char * property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_STRING; property->value.string_value = SDL_strdup(value); if (!property->value.string_value) { SDL_free(property); - return SDL_OutOfMemory(); + return -1; } return SDL_PrivateSetProperty(props, name, property); } @@ -323,7 +323,7 @@ int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_NUMBER; property->value.number_value = value; @@ -334,7 +334,7 @@ int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value) { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_FLOAT; property->value.float_value = value; @@ -345,7 +345,7 @@ int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool va { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return SDL_OutOfMemory(); + return -1; } property->type = SDL_PROPERTY_TYPE_BOOLEAN; property->value.boolean_value = value ? SDL_TRUE : SDL_FALSE; @@ -478,8 +478,6 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons SDL_asprintf(&property->string_storage, "%" SDL_PRIs64 "", property->value.number_value); if (property->string_storage) { value = property->string_storage; - } else { - SDL_OutOfMemory(); } } break; @@ -490,8 +488,6 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons SDL_asprintf(&property->string_storage, "%f", property->value.float_value); if (property->string_storage) { value = property->string_storage; - } else { - SDL_OutOfMemory(); } } break; diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 168a909fa78b4..b47c840b6b54f 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -512,14 +512,12 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc SDL_AudioDevice *device = (SDL_AudioDevice *)SDL_calloc(1, sizeof(SDL_AudioDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } device->name = SDL_strdup(name); if (!device->name) { SDL_free(device); - SDL_OutOfMemory(); return NULL; } @@ -840,7 +838,7 @@ int SDL_InitAudio(const char *driver_name) if (!driver_name_copy) { SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); - return SDL_OutOfMemory(); + return -1; } while (driver_attempt && *driver_attempt != 0 && !initialized) { @@ -1272,7 +1270,6 @@ static SDL_AudioDeviceID *GetAudioDevices(int *reqcount, SDL_bool iscapture) retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); if (!retval) { num_devices = 0; - SDL_OutOfMemory(); } else { int devs_seen = 0; const void *key; @@ -1360,9 +1357,6 @@ char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); if (device) { retval = SDL_strdup(device->name); - if (!retval) { - SDL_OutOfMemory(); - } } ReleaseAudioDevice(device); @@ -1574,14 +1568,14 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); if (!device->work_buffer) { ClosePhysicalAudioDevice(device); - return SDL_OutOfMemory(); + return -1; } if (device->spec.format != SDL_AUDIO_F32) { device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); if (!device->mix_buffer) { ClosePhysicalAudioDevice(device); - return SDL_OutOfMemory(); + return -1; } } @@ -1630,7 +1624,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp // uhoh, this device is undead, and just waiting to be cleaned up. Refuse explicit opens. SDL_SetError("Device was already lost and can't accept new opens"); } else if ((logdev = (SDL_LogicalAudioDevice *) SDL_calloc(1, sizeof (SDL_LogicalAudioDevice))) == NULL) { - SDL_OutOfMemory(); + /* SDL_calloc already called SDL_OutOfMemory */ } else if (OpenPhysicalAudioDevice(device, spec) == -1) { // if this is the first thing using this physical device, open at the OS level if necessary... SDL_free(logdev); } else { @@ -1704,7 +1698,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac if (callback && !device->postmix_buffer) { device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); if (!device->postmix_buffer) { - retval = SDL_OutOfMemory(); + retval = -1; } } diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index a101410095704..27f69f7020c7d 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -389,7 +389,7 @@ static int UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSp if (stream->history_buffer_allocation < history_buffer_allocation) { history_buffer = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), history_buffer_allocation); if (!history_buffer) { - return SDL_OutOfMemory(); + return -1; } SDL_aligned_free(stream->history_buffer); stream->history_buffer = history_buffer; @@ -409,7 +409,6 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_ SDL_AudioStream *retval = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream)); if (!retval) { - SDL_OutOfMemory(); return NULL; } @@ -722,7 +721,6 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne Uint8 *ptr = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), newlen); if (!ptr) { - SDL_OutOfMemory(); return NULL; // previous work buffer is still valid! } @@ -1234,9 +1232,7 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data dstlen = SDL_GetAudioStreamAvailable(stream); if (dstlen >= 0) { dst = (Uint8 *)SDL_malloc(dstlen); - if (!dst) { - SDL_OutOfMemory(); - } else { + if (dst) { retval = (SDL_GetAudioStreamData(stream, dst, dstlen) >= 0) ? 0 : -1; } } diff --git a/src/audio/SDL_audioqueue.c b/src/audio/SDL_audioqueue.c index 763809fdca896..085e8aaee02db 100644 --- a/src/audio/SDL_audioqueue.c +++ b/src/audio/SDL_audioqueue.c @@ -150,7 +150,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) chunk = CreateAudioTrackChunk(track); if (!chunk) { - return SDL_OutOfMemory(); + return -1; } SDL_assert((track->head == NULL) && (track->tail == NULL) && (track->queued_bytes == 0)); @@ -189,7 +189,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) DestroyAudioChunks(next); - return SDL_OutOfMemory(); + return -1; } track->tail = chunk; @@ -256,7 +256,6 @@ static SDL_AudioTrack *CreateChunkedAudioTrack(const SDL_AudioSpec *spec, size_t SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)SDL_calloc(1, sizeof(*track)); if (!track) { - SDL_OutOfMemory(); return NULL; } @@ -276,7 +275,6 @@ SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size) SDL_AudioQueue *queue = (SDL_AudioQueue *)SDL_calloc(1, sizeof(*queue)); if (!queue) { - SDL_OutOfMemory(); return NULL; } @@ -398,7 +396,7 @@ int SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, cons SDL_AudioTrack *new_track = CreateChunkedAudioTrack(spec, queue->chunk_size); if (!new_track) { - return SDL_OutOfMemory(); + return -1; } if (track) { diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 76785cf914474..cb3732305d578 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -440,7 +440,7 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4); file->decoderdata = coeffdata; /* Freed in cleanup. */ if (!coeffdata) { - return SDL_OutOfMemory(); + return -1; } coeffdata->coeff = &coeffdata->aligndummy; coeffdata->coeffcount = (Uint16)coeffcount; @@ -674,7 +674,7 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) /* The output size in bytes. May get modified if data is truncated. */ outputsize = (size_t)state.framestotal; if (SafeMult(&outputsize, state.framesize)) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) { return SDL_SetError("WAVE file too big"); } @@ -683,7 +683,7 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_calloc(1, outputsize); if (!state.output.data) { - return SDL_OutOfMemory(); + return -1; } state.cstate = cstate; @@ -1065,7 +1065,7 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len /* The output size in bytes. May get modified if data is truncated. */ outputsize = (size_t)state.framestotal; if (SafeMult(&outputsize, state.framesize)) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) { return SDL_SetError("WAVE file too big"); } @@ -1074,13 +1074,13 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_malloc(outputsize); if (!state.output.data) { - return SDL_OutOfMemory(); + return -1; } cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8)); if (!cstate) { SDL_free(state.output.data); - return SDL_OutOfMemory(); + return -1; } state.cstate = cstate; @@ -1221,12 +1221,12 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) sample_count = (size_t)file->sampleframes; if (SafeMult(&sample_count, format->channels)) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } expanded_len = sample_count; if (SafeMult(&expanded_len, sizeof(Sint16))) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) { return SDL_SetError("WAVE file too big"); } @@ -1234,7 +1234,7 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); if (!src) { - return SDL_OutOfMemory(); + return -1; } chunk->data = NULL; chunk->size = 0; @@ -1352,12 +1352,12 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 * sample_count = (size_t)file->sampleframes; if (SafeMult(&sample_count, format->channels)) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } expanded_len = sample_count; if (SafeMult(&expanded_len, sizeof(Sint32))) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) { return SDL_SetError("WAVE file too big"); } @@ -1365,7 +1365,7 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 * /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); if (!ptr) { - return SDL_OutOfMemory(); + return -1; } /* This pointer is now invalid. */ @@ -1421,7 +1421,7 @@ static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) outputsize = (size_t)file->sampleframes; if (SafeMult(&outputsize, format->blockalign)) { - return SDL_OutOfMemory(); + return SDL_SetError("WAVE file too big"); } else if (outputsize > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) { return SDL_SetError("WAVE file too big"); } @@ -1545,7 +1545,7 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len if (length > 0) { chunk->data = (Uint8 *)SDL_malloc(length); if (!chunk->data) { - return SDL_OutOfMemory(); + return -1; } if (SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET) != chunk->position) { @@ -1611,7 +1611,7 @@ static int WaveReadFormat(WaveFile *file) } fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size); if (!fmtsrc) { - return SDL_OutOfMemory(); + return -1; } if (!SDL_ReadU16LE(fmtsrc, &format->formattag) || diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 668ffac05ec3e..d46f671b67fd0 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -355,7 +355,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device) hidden->mixbuf_bytes = (hidden->num_buffers * device->buffer_size); hidden->mixbuf = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), hidden->mixbuf_bytes); if (!hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } hidden->processed_bytes = 0; hidden->callback_bytes = 0; @@ -398,7 +398,7 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } return BuildAAudioStream(device); diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index e7505b88d9533..98953a96ae3ba 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -537,7 +537,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Open the audio device @@ -683,7 +683,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) if (!iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index b2147f336828f..55be7dddd8d02 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -43,7 +43,7 @@ static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } const SDL_bool iscapture = device->iscapture; diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 0690de3e20686..2133b992c9cc7 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -769,7 +769,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) device->hidden->numAudioBuffers = numAudioBuffers; device->hidden->audioBuffer = SDL_calloc(numAudioBuffers, sizeof(AudioQueueBufferRef)); if (device->hidden->audioBuffer == NULL) { - return SDL_OutOfMemory(); + return -1; } #if DEBUG_COREAUDIO @@ -833,7 +833,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { - return SDL_OutOfMemory(); + return -1; } #ifndef MACOSX_COREAUDIO diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index f9ae9787166d3..305f3d4615345 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -492,7 +492,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Open the audio device diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index bdcb8b3be954e..8a523318770ff 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -113,7 +113,7 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } if (envr) { @@ -132,7 +132,7 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) if (!iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 9a2c918bef467..a9c3c22d2fd3d 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -71,7 +71,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. @@ -192,7 +192,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index 9b2068a488222..91775d3722a0e 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -40,13 +40,13 @@ static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *) SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } } diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 64b195221bc7e..6c8fc60a4226b 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -178,7 +178,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // limit to native freq @@ -189,7 +189,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) if (!device->iscapture) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 78a3dac30e086..8c79a7eeea53a 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -297,7 +297,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); @@ -343,7 +343,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) device->hidden->iobuffer = (float *)SDL_calloc(1, device->buffer_size); if (!device->hidden->iobuffer) { SDL_free(audio_ports); - return SDL_OutOfMemory(); + return -1; } } @@ -351,7 +351,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) device->hidden->sdlports = (jack_port_t **)SDL_calloc(channels, sizeof(jack_port_t *)); if (!device->hidden->sdlports) { SDL_free(audio_ports); - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < channels; i++) { diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index a515d07d048f3..7692d7853ee47 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -84,7 +84,7 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Initialise the DSP service @@ -135,7 +135,7 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index c5f97eb10c014..ac2606302633d 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -216,7 +216,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. @@ -294,7 +294,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->mixlen = device->buffer_size; device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index 22bec9dd6f8de..4253ebcadfcf7 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -600,7 +600,7 @@ static int OPENSLES_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } if (device->iscapture) { diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index bd4ee2ed00cb4..00e46942288f1 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -689,7 +689,6 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p node->userdata = io = SDL_calloc(1, sizeof(struct io_node) + desc_buffer_len + path_buffer_len); if (!io) { node_object_destroy(node); - SDL_OutOfMemory(); return; } @@ -1105,7 +1104,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) priv = SDL_calloc(1, sizeof(struct SDL_PrivateAudioData)); device->hidden = priv; if (!priv) { - return SDL_OutOfMemory(); + return -1; } // Size of a single audio frame in bytes diff --git a/src/audio/ps2/SDL_ps2audio.c b/src/audio/ps2/SDL_ps2audio.c index fd64d86e1b5dc..0971031c5117e 100644 --- a/src/audio/ps2/SDL_ps2audio.c +++ b/src/audio/ps2/SDL_ps2audio.c @@ -31,7 +31,7 @@ static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // These are the native supported audio PS2 configs diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index 057b4b14f6bf2..f2b771661cc81 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -42,7 +42,7 @@ static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // device only natively supports S16LSB diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index b4fd97e5c59f2..bf86b49caf21f 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -615,7 +615,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // Try for a closest match on audio format @@ -664,7 +664,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) if (!iscapture) { h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!h->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(h->mixbuf, device->silence_value, device->buffer_size); } diff --git a/src/audio/qnx/SDL_qsa_audio.c b/src/audio/qnx/SDL_qsa_audio.c index 27e21d721f7ee..0e2d37cf4a6d3 100644 --- a/src/audio/qnx/SDL_qsa_audio.c +++ b/src/audio/qnx/SDL_qsa_audio.c @@ -206,7 +206,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof (struct SDL_PrivateAudioData))); if (device->hidden == NULL) { - return SDL_OutOfMemory(); + return -1; } // Initialize channel transfer parameters to default @@ -275,7 +275,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) device->hidden->pcm_buf = (Uint8 *) SDL_malloc(device->buffer_size); if (device->hidden->pcm_buf == NULL) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->pcm_buf, device->silence_value, device->buffer_size); diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 970e2e9078ff4..59205889e5343 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -228,7 +228,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } // !!! FIXME: we really should standardize this on a specific SDL hint. @@ -243,7 +243,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->pfd = SDL_malloc(sizeof(struct pollfd) * SNDIO_sio_nfds(device->hidden->dev)); if (!device->hidden->pfd) { - return SDL_OutOfMemory(); + return -1; } struct sio_par par; @@ -308,7 +308,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index 7e7c6060820a2..865752c2b7ee8 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -62,11 +62,10 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) const SDL_AudioFormat *closefmts; device->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc(sizeof(*device->hidden)); + SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(device->hidden, 0, sizeof(*device->hidden)); closefmts = SDL_ClosestAudioFormats(device->spec.format); while ((test_format = *(closefmts++)) != 0) { diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 938811a4a4720..294f6420b1a93 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -104,7 +104,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in ManagementThreadPendingTask *pending = SDL_calloc(1, sizeof(ManagementThreadPendingTask)); if (!pending) { - return SDL_OutOfMemory(); + return -1; } pending->fn = task; @@ -700,7 +700,7 @@ static int WASAPI_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return SDL_OutOfMemory(); + return -1; } else if (ActivateWasapiDevice(device) < 0) { return -1; // already set error. } diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index 829c7d864a001..c12fcf0bb702d 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -170,7 +170,7 @@ int SDL_EVDEV_Init(void) if (!_this) { _this = (SDL_EVDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); if (!_this) { - return SDL_OutOfMemory(); + return -1; } #ifdef SDL_USE_LIBUDEV @@ -644,7 +644,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data)); if (!item->touchscreen_data) { - return SDL_OutOfMemory(); + return -1; } ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); @@ -656,7 +656,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) item->touchscreen_data->name = SDL_strdup(name); if (!item->touchscreen_data->name) { SDL_free(item->touchscreen_data); - return SDL_OutOfMemory(); + return -1; } ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info); @@ -712,7 +712,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) if (!item->touchscreen_data->slots) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < item->touchscreen_data->max_slots; i++) { @@ -883,7 +883,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) item = (SDL_evdevlist_item *)SDL_calloc(1, sizeof(SDL_evdevlist_item)); if (!item) { - return SDL_OutOfMemory(); + return -1; } item->fd = open(dev_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); @@ -896,7 +896,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) if (!item->path) { close(item->fd); SDL_free(item); - return SDL_OutOfMemory(); + return -1; } item->udev_class = udev_class; diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 903f272086693..72a527e036af8 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -112,7 +112,7 @@ int SDL_UDEV_Init(void) if (!_this) { _this = (SDL_UDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); if (!_this) { - return SDL_OutOfMemory(); + return -1; } retval = SDL_UDEV_LoadLibrary(); @@ -518,7 +518,7 @@ int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) SDL_UDEV_CallbackList *item; item = (SDL_UDEV_CallbackList *)SDL_calloc(1, sizeof(SDL_UDEV_CallbackList)); if (!item) { - return SDL_OutOfMemory(); + return -1; } item->callback = cb; diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 629f4a181c02e..fe2de5728f7d0 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -149,12 +149,10 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * // handle is freed by SDL_IMMDevice_FreeDeviceHandle! SDL_IMMDevice_HandleData *handle = SDL_malloc(sizeof(SDL_IMMDevice_HandleData)); if (!handle) { - SDL_OutOfMemory(); return NULL; } handle->immdevice_id = SDL_wcsdup(devid); if (!handle->immdevice_id) { - SDL_OutOfMemory(); SDL_free(handle); return NULL; } diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 5879629ba0189..040e5bdc8bfc0 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -105,7 +105,6 @@ void *SDL_AllocateEventMemory(size_t size) { void *memory = SDL_malloc(size); if (!memory) { - SDL_OutOfMemory(); return NULL; } @@ -126,7 +125,6 @@ void *SDL_AllocateEventMemory(size_t size) } else { SDL_free(memory); memory = NULL; - SDL_OutOfMemory(); } } SDL_UnlockMutex(SDL_event_memory_lock); @@ -1295,7 +1293,6 @@ int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) watcher->removed = SDL_FALSE; ++SDL_event_watchers_count; } else { - SDL_OutOfMemory(); result = -1; } } diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 6487ca181847c..eb9a863f60ea4 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -489,7 +489,7 @@ int SDL_SetMouseSystemScale(int num_values, const float *values) v = (float *)SDL_realloc(mouse->system_scale_values, num_values * sizeof(*values)); if (!v) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(v, values, num_values * sizeof(*values)); @@ -1300,9 +1300,6 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) cursor = mouse->CreateCursor(surface, hot_x, hot_y); } else { cursor = SDL_calloc(1, sizeof(*cursor)); - if (!cursor) { - SDL_OutOfMemory(); - } } if (cursor) { cursor->next = mouse->cursors; diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 08e570909fd8a..2a38293fe0094 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -57,9 +57,7 @@ SDL_TouchID *SDL_GetTouchDevices(int *count) const int total = SDL_num_touch; SDL_TouchID *retval = (SDL_TouchID *) SDL_malloc(sizeof (SDL_TouchID) * (total + 1)); - if (!retval) { - SDL_OutOfMemory(); - } else { + if (retval) { for (int i = 0; i < total; i++) { retval[i] = SDL_touchDevices[i]->id; } @@ -169,7 +167,7 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name touchDevices = (SDL_Touch **)SDL_realloc(SDL_touchDevices, (SDL_num_touch + 1) * sizeof(*touchDevices)); if (!touchDevices) { - return SDL_OutOfMemory(); + return -1; } SDL_touchDevices = touchDevices; @@ -177,7 +175,7 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name SDL_touchDevices[index] = (SDL_Touch *)SDL_malloc(sizeof(*SDL_touchDevices[index])); if (!SDL_touchDevices[index]) { - return SDL_OutOfMemory(); + return -1; } /* Added touch to list */ @@ -202,12 +200,12 @@ static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float SDL_Finger **new_fingers; new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers + 1) * sizeof(*touch->fingers)); if (!new_fingers) { - return SDL_OutOfMemory(); + return -1; } touch->fingers = new_fingers; touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger)); if (!touch->fingers[touch->max_fingers]) { - return SDL_OutOfMemory(); + return -1; } touch->max_fingers++; } diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index a671c76f29607..38aad554fb085 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -92,7 +92,7 @@ static int SDLCALL windows_file_open(SDL_RWops *context, const char *filename, c context->hidden.windowsio.buffer.data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); if (!context->hidden.windowsio.buffer.data) { - return SDL_OutOfMemory(); + return -1; } #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) && !defined(__WINRT__) /* Do not open a dialog box if failure */ @@ -609,9 +609,7 @@ SDL_RWops *SDL_CreateRW(void) SDL_RWops *context; context = (SDL_RWops *)SDL_calloc(1, sizeof(*context)); - if (!context) { - SDL_OutOfMemory(); - } else { + if (context) { context->type = SDL_RWOPS_UNKNOWN; } return context; @@ -643,12 +641,10 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc) loading_chunks = SDL_TRUE; } if (size >= SDL_SIZE_MAX) { - SDL_OutOfMemory(); goto done; } data = (char *)SDL_malloc((size_t)(size + 1)); if (!data) { - SDL_OutOfMemory(); goto done; } @@ -665,7 +661,6 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc) if (!newdata) { SDL_free(data); data = NULL; - SDL_OutOfMemory(); goto done; } data = newdata; diff --git a/src/file/n3ds/SDL_rwopsromfs.c b/src/file/n3ds/SDL_rwopsromfs.c index a1bde54948023..92d9a8141fb0a 100644 --- a/src/file/n3ds/SDL_rwopsromfs.c +++ b/src/file/n3ds/SDL_rwopsromfs.c @@ -78,7 +78,6 @@ FILE *TryOpenInRomfs(const char *file, const char *mode) char *prefixed_filepath = NULL; if (SDL_asprintf(&prefixed_filepath, "romfs:/%s", file) < 0) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/android/SDL_sysfilesystem.c b/src/filesystem/android/SDL_sysfilesystem.c index a287b005ec30d..0fc466ffb329b 100644 --- a/src/filesystem/android/SDL_sysfilesystem.c +++ b/src/filesystem/android/SDL_sysfilesystem.c @@ -41,7 +41,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) size_t pathlen = SDL_strlen(path) + 2; char *fullpath = (char *)SDL_malloc(pathlen); if (!fullpath) { - SDL_OutOfMemory(); return NULL; } SDL_snprintf(fullpath, pathlen, "%s/", path); diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index 0a78a2d9aa0c6..eb5ee9b859371 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -52,9 +52,7 @@ if (base) { const size_t len = SDL_strlen(base) + 2; retval = (char *)SDL_malloc(len); - if (retval == NULL) { - SDL_OutOfMemory(); - } else { + if (retval != NULL) { SDL_snprintf(retval, len, "%s/", base); } } @@ -105,9 +103,7 @@ if (base) { const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; retval = (char *)SDL_malloc(len); - if (retval == NULL) { - SDL_OutOfMemory(); - } else { + if (retval != NULL) { char *ptr; if (*org) { SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app); @@ -152,13 +148,7 @@ SDL_SetError("No $HOME environment variable available"); } - retval = SDL_strdup(base); - - if (!retval) { - SDL_OutOfMemory(); - } - - return retval; + return SDL_strdup(base); case SDL_FOLDER_DESKTOP: dir = NSDesktopDirectory; @@ -221,7 +211,6 @@ retval = SDL_strdup(base); if (retval == NULL) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c index 5c87840b3d3ba..b22ee4ce5115d 100644 --- a/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -53,7 +53,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); if (!retval) { - SDL_OutOfMemory(); return NULL; } @@ -86,7 +85,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *SDL_GetUserFolder(SDL_Folder folder) { const char *home = NULL; - char *retval; if (folder != SDL_FOLDER_HOME) { SDL_SetError("Emscripten only supports the home folder"); @@ -99,13 +97,7 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - retval = SDL_strdup(home); - - if (!retval) { - SDL_OutOfMemory(); - } - - return retval; + return SDL_strdup(home); } #endif /* SDL_FILESYSTEM_EMSCRIPTEN */ diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp index 3bbfca311b80e..6794a31fea28d 100644 --- a/src/filesystem/gdk/SDL_sysfilesystem.cpp +++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp @@ -46,7 +46,6 @@ SDL_GetBasePath(void) void *ptr = SDL_realloc(path, buflen * sizeof(CHAR)); if (!ptr) { SDL_free(path); - SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index 9a5f2575cf4d0..d28baacef19b4 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -52,7 +52,6 @@ char *SDL_GetBasePath(void) const size_t len = SDL_strlen(str); char *retval = (char *) SDL_malloc(len + 2); if (!retval) { - SDL_OutOfMemory(); return NULL; } @@ -83,9 +82,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; char *retval = (char *) SDL_malloc(len); - if (!retval) { - SDL_OutOfMemory(); - } else { + if (retval) { if (*org) { SDL_snprintf(retval, len, "%s%s%s/%s/", home, append, org, app); } else { @@ -110,25 +107,17 @@ char *SDL_GetUserFolder(SDL_Folder folder) switch (folder) { case SDL_FOLDER_HOME: - retval = SDL_strdup(home); - - if (!retval) { - SDL_OutOfMemory(); - } - - return retval; + return SDL_strdup(home); /* TODO: Is Haiku's desktop folder always ~/Desktop/ ? */ case SDL_FOLDER_DESKTOP: retval = (char *) SDL_malloc(SDL_strlen(home) + 10); - if (!retval) { - SDL_OutOfMemory(); + if (retval) { + SDL_strlcpy(retval, home, SDL_strlen(home) + 10); + SDL_strlcat(retval, "/Desktop/", SDL_strlen(home) + 10); } - SDL_strlcpy(retval, home, SDL_strlen(home) + 10); - SDL_strlcat(retval, "/Desktop/", SDL_strlen(home) + 10); - return retval; case SDL_FOLDER_DOCUMENTS: diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c index 00ac71fc85726..a4bea05c62409 100644 --- a/src/filesystem/n3ds/SDL_sysfilesystem.c +++ b/src/filesystem/n3ds/SDL_sysfilesystem.c @@ -70,7 +70,6 @@ static char *MakePrefPath(const char *app) { char *pref_path; if (SDL_asprintf(&pref_path, "sdmc:/3ds/%s/", app) < 0) { - SDL_OutOfMemory(); return NULL; } return pref_path; diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c index 842d62e38fc6c..83b676de2b85d 100644 --- a/src/filesystem/riscos/SDL_sysfilesystem.c +++ b/src/filesystem/riscos/SDL_sysfilesystem.c @@ -42,7 +42,6 @@ static char *SDL_unixify_std(const char *ro_path, char *buffer, size_t buf_len, buffer = SDL_malloc(buf_len); if (!buffer) { - SDL_OutOfMemory(); return NULL; } } @@ -89,7 +88,6 @@ static char *canonicalisePath(const char *path, const char *pathVar) regs.r[5] = 1 - regs.r[5]; buf = SDL_malloc(regs.r[5]); if (!buf) { - SDL_OutOfMemory(); return NULL; } regs.r[2] = (int)buf; @@ -174,7 +172,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) len = SDL_strlen(canon) + SDL_strlen(org) + SDL_strlen(app) + 4; dir = (char *)SDL_malloc(len); if (!dir) { - SDL_OutOfMemory(); SDL_free(canon); return NULL; } diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index 491f0f0d8d36f..d288e9d757e6d 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -48,7 +48,6 @@ static char *readSymLink(const char *path) while (1) { char *ptr = (char *)SDL_realloc(retval, (size_t)len); if (!ptr) { - SDL_OutOfMemory(); break; } @@ -85,7 +84,6 @@ static char *search_path_for_binary(const char *bin) envr = SDL_strdup(envr); if (!envr) { - SDL_OutOfMemory(); return NULL; } @@ -131,7 +129,6 @@ char *SDL_GetBasePath(void) if (sysctl(mib, SDL_arraysize(mib), fullpath, &buflen, NULL, 0) != -1) { retval = SDL_strdup(fullpath); if (!retval) { - SDL_OutOfMemory(); return NULL; } } @@ -145,14 +142,12 @@ char *SDL_GetBasePath(void) char *exe, *pwddst; char *realpathbuf = (char *)SDL_malloc(PATH_MAX + 1); if (!realpathbuf) { - SDL_OutOfMemory(); return NULL; } cmdline = SDL_malloc(len); if (!cmdline) { SDL_free(realpathbuf); - SDL_OutOfMemory(); return NULL; } @@ -228,7 +223,6 @@ char *SDL_GetBasePath(void) if ((path) && (path[0] == '/')) { /* must be absolute path... */ retval = SDL_strdup(path); if (!retval) { - SDL_OutOfMemory(); return NULL; } } @@ -302,7 +296,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); if (!retval) { - SDL_OutOfMemory(); return NULL; } @@ -541,13 +534,7 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - retval = SDL_strdup(param); - - if (!retval) { - SDL_OutOfMemory(); - } - - return retval; + return SDL_strdup(param); case SDL_FOLDER_DESKTOP: param = "DESKTOP"; diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c index e06664908737a..83b84254406aa 100644 --- a/src/filesystem/vita/SDL_sysfilesystem.c +++ b/src/filesystem/vita/SDL_sysfilesystem.c @@ -61,7 +61,6 @@ char *SDL_GetPrefPath(const char *org, const char *app) len += SDL_strlen(org) + SDL_strlen(app) + 3; retval = (char *)SDL_malloc(len); if (!retval) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c index d31193af202c1..160d330879861 100644 --- a/src/filesystem/windows/SDL_sysfilesystem.c +++ b/src/filesystem/windows/SDL_sysfilesystem.c @@ -53,7 +53,6 @@ char *SDL_GetBasePath(void) void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR)); if (!ptr) { SDL_free(path); - SDL_OutOfMemory(); return NULL; } @@ -123,14 +122,12 @@ char *SDL_GetPrefPath(const char *org, const char *app) worg = WIN_UTF8ToStringW(org); if (!worg) { - SDL_OutOfMemory(); return NULL; } wapp = WIN_UTF8ToStringW(app); if (!wapp) { SDL_free(worg); - SDL_OutOfMemory(); return NULL; } diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index d442d26033c73..6cefbc049c48f 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -131,7 +131,6 @@ SDL_GetBasePath(void) destPathLen = SDL_strlen(srcPath) + 2; destPath = (char *)SDL_malloc(destPathLen); if (!destPath) { - SDL_OutOfMemory(); return NULL; } @@ -178,14 +177,12 @@ SDL_GetPrefPath(const char *org, const char *app) worg = WIN_UTF8ToString(org); if (!worg) { - SDL_OutOfMemory(); return NULL; } wapp = WIN_UTF8ToString(app); if (!wapp) { SDL_free(worg); - SDL_OutOfMemory(); return NULL; } diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index ad70f274a1c7a..60dd37d34c087 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -125,7 +125,6 @@ SDL_Haptic *SDL_HapticOpen(int device_index) /* Create the haptic device */ haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); if (!haptic) { - SDL_OutOfMemory(); return NULL; } @@ -297,7 +296,6 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) /* Create the haptic device */ haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); if (!haptic) { - SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; } diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index b3d9b21eb42e8..8a68cf7956765 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -107,7 +107,6 @@ static SDL_hapticlist_item *OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item * haptic->nplaying = haptic->neffects; haptic->effects = (struct haptic_effect *)SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); if (!haptic->effects) { - SDL_OutOfMemory(); return NULL; } SDL_memset(haptic->effects, 0, sizeof(struct haptic_effect) * haptic->neffects); diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index c0583640ab3d2..44a85b3835170 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -473,13 +473,10 @@ static int SDL_SYS_HapticOpenFromService(SDL_Haptic *haptic, io_service_t servic int ret2; /* Allocate the hwdata */ - haptic->hwdata = (struct haptic_hwdata *) - SDL_malloc(sizeof(*haptic->hwdata)); + haptic->hwdata = (struct haptic_hwdata *) SDL_calloc(1, sizeof(*haptic->hwdata)); if (!haptic->hwdata) { - SDL_OutOfMemory(); goto creat_err; } - SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); /* Open the device */ ret = FFCreateDevice(service, &haptic->hwdata->device); @@ -513,7 +510,6 @@ static int SDL_SYS_HapticOpenFromService(SDL_Haptic *haptic, io_service_t servic haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); if (!haptic->effects) { - SDL_OutOfMemory(); goto open_err; } /* Clear the memory */ @@ -700,7 +696,7 @@ static int SDL_SYS_SetDirection(FFEFFECT *effect, SDL_HapticDirection *dir, int /* Has axes. */ rglDir = SDL_malloc(sizeof(LONG) * naxes); if (!rglDir) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(rglDir, 0, sizeof(LONG) * naxes); effect->rglDirection = rglDir; @@ -771,11 +767,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe dest->dwFlags = FFEFF_OBJECTOFFSETS; /* Seems obligatory. */ /* Envelope. */ - envelope = SDL_malloc(sizeof(FFENVELOPE)); + envelope = SDL_calloc(1, sizeof(FFENVELOPE)); if (!envelope) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(envelope, 0, sizeof(FFENVELOPE)); dest->lpEnvelope = envelope; envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */ @@ -788,7 +783,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe if (dest->cAxes > 0) { axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); if (!axes) { - return SDL_OutOfMemory(); + return -1; } axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */ if (dest->cAxes > 1) { @@ -804,11 +799,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe switch (src->type) { case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; - constant = SDL_malloc(sizeof(FFCONSTANTFORCE)); + constant = SDL_calloc(1, sizeof(FFCONSTANTFORCE)); if (!constant) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(constant, 0, sizeof(FFCONSTANTFORCE)); /* Specifics */ constant->lMagnitude = CONVERT(hap_constant->level); @@ -846,11 +840,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; - periodic = SDL_malloc(sizeof(FFPERIODIC)); + periodic = SDL_calloc(1, sizeof(FFPERIODIC)); if (!periodic) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(periodic, 0, sizeof(FFPERIODIC)); /* Specifics */ periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude)); @@ -891,11 +884,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_FRICTION: hap_condition = &src->condition; if (dest->cAxes > 0) { - condition = SDL_malloc(sizeof(FFCONDITION) * dest->cAxes); + condition = SDL_calloc(dest->cAxes, sizeof(FFCONDITION)); if (!condition) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(condition, 0, sizeof(FFCONDITION)); /* Specifics */ for (i = 0; i < dest->cAxes; i++) { @@ -934,11 +926,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_RAMP: hap_ramp = &src->ramp; - ramp = SDL_malloc(sizeof(FFRAMPFORCE)); + ramp = SDL_calloc(1, sizeof(FFRAMPFORCE)); if (!ramp) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(ramp, 0, sizeof(FFRAMPFORCE)); /* Specifics */ ramp->lStart = CONVERT(hap_ramp->start); @@ -972,11 +963,10 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe case SDL_HAPTIC_CUSTOM: hap_custom = &src->custom; - custom = SDL_malloc(sizeof(FFCUSTOMFORCE)); + custom = SDL_calloc(1, sizeof(FFCUSTOMFORCE)); if (!custom) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(custom, 0, sizeof(FFCUSTOMFORCE)); /* Specifics */ custom->cChannels = hap_custom->channels; @@ -1107,9 +1097,8 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* Alloc the effect. */ effect->hweffect = (struct haptic_hweffect *) - SDL_malloc(sizeof(struct haptic_hweffect)); + SDL_calloc(1, sizeof(struct haptic_hweffect)); if (!effect->hweffect) { - SDL_OutOfMemory(); goto err_hweffect; } diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 00e60411b742b..0649ce37c9eae 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -375,12 +375,10 @@ static int SDL_SYS_HapticOpenFromFD(SDL_Haptic *haptic, int fd) { /* Allocate the hwdata */ haptic->hwdata = (struct haptic_hwdata *) - SDL_malloc(sizeof(*haptic->hwdata)); + SDL_calloc(1, sizeof(*haptic->hwdata)); if (!haptic->hwdata) { - SDL_OutOfMemory(); goto open_err; } - SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); /* Set the data. */ haptic->hwdata->fd = fd; @@ -397,7 +395,6 @@ static int SDL_SYS_HapticOpenFromFD(SDL_Haptic *haptic, int fd) haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); if (!haptic->effects) { - SDL_OutOfMemory(); goto open_err; } /* Clear the memory */ @@ -903,9 +900,9 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* Allocate the hardware effect */ effect->hweffect = (struct haptic_hweffect *) - SDL_malloc(sizeof(struct haptic_hweffect)); + SDL_calloc(1, sizeof(struct haptic_hweffect)); if (!effect->hweffect) { - return SDL_OutOfMemory(); + return -1; } /* Prepare the ff_effect */ diff --git a/src/haptic/windows/SDL_dinputhaptic.c b/src/haptic/windows/SDL_dinputhaptic.c index a1225dd6704f0..45214ddcdeba9 100644 --- a/src/haptic/windows/SDL_dinputhaptic.c +++ b/src/haptic/windows/SDL_dinputhaptic.c @@ -167,7 +167,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance) item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); if (!item) { - return SDL_OutOfMemory(); + return -1; } item->name = WIN_StringToUTF8(pdidInstance->tszProductName); @@ -286,11 +286,10 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI DIPROPDWORD dipdw; /* Allocate the hwdata */ - haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata)); + haptic->hwdata = (struct haptic_hwdata *)SDL_calloc(1, sizeof(*haptic->hwdata)); if (!haptic->hwdata) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); /* We'll use the device8 from now on. */ haptic->hwdata->device = device8; @@ -402,7 +401,6 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); if (!haptic->effects) { - SDL_OutOfMemory(); goto acquire_err; } /* Clear the memory */ @@ -541,7 +539,7 @@ static int SDL_SYS_SetDirection(DIEFFECT *effect, SDL_HapticDirection *dir, int /* Has axes. */ rglDir = SDL_malloc(sizeof(LONG) * naxes); if (!rglDir) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(rglDir, 0, sizeof(LONG) * naxes); effect->rglDirection = rglDir; @@ -613,11 +611,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, dest->dwFlags = DIEFF_OBJECTOFFSETS; /* Seems obligatory. */ /* Envelope. */ - envelope = SDL_malloc(sizeof(DIENVELOPE)); + envelope = SDL_calloc(1, sizeof(DIENVELOPE)); if (!envelope) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(envelope, 0, sizeof(DIENVELOPE)); dest->lpEnvelope = envelope; envelope->dwSize = sizeof(DIENVELOPE); /* Always should be this. */ @@ -630,7 +627,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, if (dest->cAxes > 0) { axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); if (!axes) { - return SDL_OutOfMemory(); + return -1; } axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */ if (dest->cAxes > 1) { @@ -646,11 +643,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, switch (src->type) { case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; - constant = SDL_malloc(sizeof(DICONSTANTFORCE)); + constant = SDL_calloc(1, sizeof(DICONSTANTFORCE)); if (!constant) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(constant, 0, sizeof(DICONSTANTFORCE)); /* Specifics */ constant->lMagnitude = CONVERT(hap_constant->level); @@ -688,11 +684,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; - periodic = SDL_malloc(sizeof(DIPERIODIC)); + periodic = SDL_calloc(1, sizeof(DIPERIODIC)); if (!periodic) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(periodic, 0, sizeof(DIPERIODIC)); /* Specifics */ periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude)); @@ -732,11 +727,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_INERTIA: case SDL_HAPTIC_FRICTION: hap_condition = &src->condition; - condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes); + condition = SDL_calloc(dest->cAxes, sizeof(DICONDITION)); if (!condition) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(condition, 0, sizeof(DICONDITION)); /* Specifics */ for (i = 0; i < (int)dest->cAxes; i++) { @@ -773,11 +767,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_RAMP: hap_ramp = &src->ramp; - ramp = SDL_malloc(sizeof(DIRAMPFORCE)); + ramp = SDL_calloc(1, sizeof(DIRAMPFORCE)); if (!ramp) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(ramp, 0, sizeof(DIRAMPFORCE)); /* Specifics */ ramp->lStart = CONVERT(hap_ramp->start); @@ -811,11 +804,10 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_CUSTOM: hap_custom = &src->custom; - custom = SDL_malloc(sizeof(DICUSTOMFORCE)); + custom = SDL_calloc(1, sizeof(DICUSTOMFORCE)); if (!custom) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(custom, 0, sizeof(DICUSTOMFORCE)); /* Specifics */ custom->cChannels = hap_custom->channels; diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c index 771ba012bcd29..fae8542b4b3ba 100644 --- a/src/haptic/windows/SDL_windowshaptic.c +++ b/src/haptic/windows/SDL_windowshaptic.c @@ -291,13 +291,10 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, int result; /* Alloc the effect. */ - effect->hweffect = (struct haptic_hweffect *) - SDL_malloc(sizeof(struct haptic_hweffect)); + effect->hweffect = (struct haptic_hweffect *) SDL_calloc(1, sizeof(struct haptic_hweffect)); if (!effect->hweffect) { - SDL_OutOfMemory(); return -1; } - SDL_zerop(effect->hweffect); if (haptic->hwdata->bXInputHaptic) { result = SDL_XINPUT_HapticNewEffect(haptic, effect, base); diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index 961f294079a27..b84c2eadd00fc 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -78,13 +78,11 @@ int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) return -1; /* no force feedback on this device. */ } - item = (SDL_hapticlist_item *)SDL_malloc(sizeof(SDL_hapticlist_item)); + item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); if (!item) { - return SDL_OutOfMemory(); + return -1; } - SDL_zerop(item); - /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */ { char buf[64]; @@ -174,19 +172,18 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us haptic->effects = (struct haptic_effect *) SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); if (!haptic->effects) { - return SDL_OutOfMemory(); + return -1; } /* Clear the memory */ SDL_memset(haptic->effects, 0, sizeof(struct haptic_effect) * haptic->neffects); - haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata)); + haptic->hwdata = (struct haptic_hwdata *)SDL_calloc(1, sizeof(*haptic->hwdata)); if (!haptic->hwdata) { SDL_free(haptic->effects); haptic->effects = NULL; - return SDL_OutOfMemory(); + return -1; } - SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); haptic->hwdata->bXInputHaptic = 1; haptic->hwdata->userid = userid; diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 8347857e2644a..d7fc41028cfdd 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1434,7 +1434,6 @@ static char *SDL_PrivateGetGamepadGUIDFromMappingString(const char *pMapping) if (pFirstComma) { char *pchGUID = SDL_malloc(pFirstComma - pMapping + 1); if (!pchGUID) { - SDL_OutOfMemory(); return NULL; } SDL_memcpy(pchGUID, pMapping, pFirstComma - pMapping); @@ -1483,7 +1482,6 @@ static char *SDL_PrivateGetGamepadNameFromMappingString(const char *pMapping) pchName = SDL_malloc(pSecondComma - pFirstComma); if (!pchName) { - SDL_OutOfMemory(); return NULL; } SDL_memcpy(pchName, pFirstComma + 1, pSecondComma - pFirstComma); @@ -1620,7 +1618,6 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co PopMappingChangeTracking(); SDL_free(pchName); SDL_free(pchMapping); - SDL_OutOfMemory(); return NULL; } /* Clear the CRC, we've already added it to the mapping */ @@ -2032,7 +2029,6 @@ static char *CreateMappingString(GamepadMapping_t *mapping, SDL_JoystickGUID gui pMappingString = SDL_malloc(needed); if (!pMappingString) { - SDL_OutOfMemory(); return NULL; } @@ -2082,7 +2078,6 @@ char **SDL_GetGamepadMappings(int *count) mappings = (char **) SDL_calloc(num_mappings + 1, sizeof (char *)); if (!mappings) { failed = SDL_TRUE; - SDL_OutOfMemory(); } else { size_t i = 0; for (GamepadMapping_t *mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { @@ -2107,9 +2102,7 @@ char **SDL_GetGamepadMappings(int *count) if (!failed) { retval = (char **) SDL_malloc(final_allocation); - if (!retval) { - SDL_OutOfMemory(); - } else { + if (retval) { final_allocation -= (sizeof (char *) * num_mappings + 1); char *strptr = (char *) (retval + (num_mappings + 1)); for (int i = 0; i < num_mappings; i++) { @@ -2431,19 +2424,10 @@ char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id) { GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); if (mapping) { - SDL_JoystickGUID guid; char pchGUID[33]; - size_t needed; - guid = SDL_GetJoystickInstanceGUID(instance_id); + const SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); SDL_GetJoystickGUIDString(guid, pchGUID, sizeof(pchGUID)); - /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ - needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; - retval = (char *)SDL_malloc(needed); - if (retval) { - (void)SDL_snprintf(retval, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); - } else { - SDL_OutOfMemory(); - } + SDL_asprintf(&retval, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); } } SDL_UnlockJoysticks(); @@ -2595,7 +2579,6 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) /* Create and initialize the gamepad */ gamepad = (SDL_Gamepad *)SDL_calloc(1, sizeof(*gamepad)); if (!gamepad) { - SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; } @@ -2611,7 +2594,6 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) if (gamepad->joystick->naxes) { gamepad->last_match_axis = (SDL_GamepadBinding **)SDL_calloc(gamepad->joystick->naxes, sizeof(*gamepad->last_match_axis)); if (!gamepad->last_match_axis) { - SDL_OutOfMemory(); SDL_CloseJoystick(gamepad->joystick); SDL_free(gamepad); SDL_UnlockJoysticks(); @@ -2621,7 +2603,6 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) if (gamepad->joystick->nhats) { gamepad->last_hat_mask = (Uint8 *)SDL_calloc(gamepad->joystick->nhats, sizeof(*gamepad->last_hat_mask)); if (!gamepad->last_hat_mask) { - SDL_OutOfMemory(); SDL_CloseJoystick(gamepad->joystick); SDL_free(gamepad->last_match_axis); SDL_free(gamepad); @@ -3442,8 +3423,6 @@ SDL_GamepadBinding **SDL_GetGamepadBindings(SDL_Gamepad *gamepad, int *count) if (count) { *count = gamepad->num_bindings; } - } else { - SDL_OutOfMemory(); } } SDL_UnlockJoysticks(); diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index f26c3db20ea55..cc0ca88d3a754 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -270,7 +270,6 @@ static SDL_bool SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID if (player_index >= SDL_joystick_player_count) { SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1) * sizeof(*SDL_joystick_players)); if (!new_players) { - SDL_OutOfMemory(); return SDL_FALSE; } @@ -403,8 +402,6 @@ SDL_JoystickID *SDL_GetJoysticks(int *count) if (count) { *count = 0; } - - SDL_OutOfMemory(); } } SDL_UnlockJoysticks(); @@ -755,7 +752,6 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) /* Create and initialize the joystick */ joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1); if (!joystick) { - SDL_OutOfMemory(); SDL_UnlockJoysticks(); return NULL; } @@ -798,7 +794,6 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) joystick->buttons = (Uint8 *)SDL_calloc(joystick->nbuttons, sizeof(Uint8)); } if (((joystick->naxes > 0) && !joystick->axes) || ((joystick->nhats > 0) && !joystick->hats) || ((joystick->nbuttons > 0) && !joystick->buttons)) { - SDL_OutOfMemory(); SDL_CloseJoystick(joystick); SDL_UnlockJoysticks(); return NULL; diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 1b54bf46a2145..b8e6da62cef90 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1165,7 +1165,6 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) int button_count = 0; if (buttons == NULL) { - SDL_OutOfMemory(); return; } @@ -1222,7 +1221,6 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) int button_count = 0; if (buttons == NULL) { - SDL_OutOfMemory(); return; } diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 4522289076153..fc97c5d49f5b3 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -270,7 +270,6 @@ CreateHwData(const char *path) SDL_calloc(1, sizeof(struct joystick_hwdata)); if (!hw) { close(fd); - SDL_OutOfMemory(); return NULL; } hw->fd = fd; @@ -794,7 +793,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind) r->size); #endif if (!r->buf) { - return SDL_OutOfMemory(); + return -1; } } else { r->buf = NULL; diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 50cb2e107b3b1..b6bc97fd7a6c8 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -529,7 +529,6 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender device = (recDevice *)SDL_calloc(1, sizeof(recDevice)); if (!device) { - SDL_OutOfMemory(); return; } @@ -834,7 +833,7 @@ static int DARWIN_JoystickInitRumble(recDevice *device, Sint16 magnitude) /* Create the effect */ device->ffeffect = CreateRumbleEffectData(magnitude); if (!device->ffeffect) { - return SDL_OutOfMemory(); + return -1; } result = FFDeviceCreateEffect(device->ffdevice, kFFEffectType_Sine_ID, diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 5c07affb2f0d0..cfdca6a045d08 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -129,12 +129,10 @@ extern "C" /* Create the joystick data structure */ joystick->instance_id = device_index; - joystick->hwdata = (struct joystick_hwdata *) - SDL_malloc(sizeof(*joystick->hwdata)); + joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); if (joystick->hwdata == NULL) { - return SDL_OutOfMemory(); + return -1; } - SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); stick = new BJoystick; joystick->hwdata->stick = stick; @@ -152,13 +150,11 @@ extern "C" joystick->naxes = stick->CountAxes(); joystick->nhats = stick->CountHats(); - joystick->hwdata->new_axes = (int16 *) - SDL_malloc(joystick->naxes * sizeof(int16)); - joystick->hwdata->new_hats = (uint8 *) - SDL_malloc(joystick->nhats * sizeof(uint8)); + joystick->hwdata->new_axes = (int16 *) SDL_calloc(joystick->naxes, sizeof(int16)); + joystick->hwdata->new_hats = (uint8 *) SDL_calloc(joystick->nhats, sizeof(uint8)); if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) { HAIKU_JoystickClose(joystick); - return SDL_OutOfMemory(); + return -1; } /* We're done! */ diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 9b8f97c179bb6..8ca952cf237f0 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -115,7 +115,6 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } device->context = ctx; diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 57f2a11a69a77..4e02b5f1a2a44 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -73,7 +73,6 @@ static SDL_bool HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } device->context = ctx; diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index eb49d8018e254..7ff706eb07bdf 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -135,7 +135,6 @@ static SDL_bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; @@ -605,7 +604,6 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index a5e9cb0a33c96..3dc2372137482 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -277,7 +277,6 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 4e71f95c61b9c..b27f7029ca178 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -376,7 +376,6 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index b29088cd1baf3..8a246861f26d0 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -216,7 +216,7 @@ int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const request = (SDL_HIDAPI_RumbleRequest *)SDL_calloc(1, sizeof(*request)); if (!request) { SDL_HIDAPI_UnlockRumble(); - return SDL_OutOfMemory(); + return -1; } request->device = device; SDL_memcpy(request->data, data, size); diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 5821c2d6f0bad..71ee72c767b87 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -115,7 +115,6 @@ static SDL_bool HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } device->context = ctx; diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index b5959cbb56437..e4883862cc80f 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -70,7 +70,6 @@ static SDL_bool HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } device->context = ctx; diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 5fc99fbef5e75..aa6f18fff2dae 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -974,7 +974,6 @@ static SDL_bool HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } device->context = ctx; diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index db52c6f23dce5..5a4b109df4246 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -1246,7 +1246,6 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 4a529de76d63e..423835e623c39 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -719,7 +719,6 @@ static SDL_bool HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index bd9565303c4a5..3a7b3accc19db 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -140,7 +140,6 @@ static SDL_bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 954e16c09b6c5..a58c729e94cfe 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -132,7 +132,6 @@ static SDL_bool HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index d21881548c2df..5cf5deda8ee1a 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -360,7 +360,6 @@ static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device) ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { - SDL_OutOfMemory(); return SDL_FALSE; } ctx->device = device; diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index be3eb2e92d414..037651eca4689 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1435,7 +1435,7 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata)); if (!hwdata) { - return SDL_OutOfMemory(); + return -1; } hwdata->device = device; diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 8a3dc2e164335..9b8a85f26678f 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -1381,7 +1381,7 @@ static int PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item, if (fd_sensor >= 0) { close(fd_sensor); } - return SDL_OutOfMemory(); + return -1; } /* Set the joystick to non-blocking read mode */ @@ -1471,7 +1471,7 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); if (!joystick->hwdata) { - return SDL_OutOfMemory(); + return -1; } item_sensor = GetSensor(item); @@ -2147,7 +2147,6 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap a fake SDL_Joystick object to do so. */ joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1); if (!joystick) { - SDL_OutOfMemory(); return SDL_FALSE; } joystick->magic = &SDL_joystick_magic; @@ -2157,7 +2156,6 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap SDL_calloc(1, sizeof(*joystick->hwdata)); if (!joystick->hwdata) { SDL_free(joystick); - SDL_OutOfMemory(); return SDL_FALSE; } diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index b6dbb5c41b30d..23519e53b827a 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -125,7 +125,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); if (!hwdata) { VIRTUAL_FreeHWData(hwdata); - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(&hwdata->desc, desc, sizeof(*desc)); @@ -210,7 +210,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata->axes = SDL_calloc(hwdata->desc.naxes, sizeof(Sint16)); if (!hwdata->axes) { VIRTUAL_FreeHWData(hwdata); - return SDL_OutOfMemory(); + return -1; } /* Trigger axes are at minimum value at rest */ @@ -225,14 +225,14 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata->buttons = SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8)); if (!hwdata->buttons) { VIRTUAL_FreeHWData(hwdata); - return SDL_OutOfMemory(); + return -1; } } if (hwdata->desc.nhats > 0) { hwdata->hats = SDL_calloc(hwdata->desc.nhats, sizeof(Uint8)); if (!hwdata->hats) { VIRTUAL_FreeHWData(hwdata); - return SDL_OutOfMemory(); + return -1; } } diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index 56f844f22ef34..f19bba85256db 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -878,7 +878,7 @@ static int SDL_DINPUT_JoystickInitRumble(SDL_Joystick *joystick, Sint16 magnitud /* Create the effect */ joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude); if (!joystick->hwdata->ffeffect) { - return SDL_OutOfMemory(); + return -1; } result = IDirectInputDevice8_CreateEffect(joystick->hwdata->InputDevice, &GUID_Sine, diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 3fd7b7fcf2788..3302e873eb19b 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -618,12 +618,12 @@ static int RAWINPUT_UpdateWindowsGamingInput() WindowsGamingInputGamepadState **new_per_gamepad; gamepad_state = SDL_calloc(1, sizeof(*gamepad_state)); if (!gamepad_state) { - return SDL_OutOfMemory(); + return -1; } new_per_gamepad = SDL_realloc(wgi_state.per_gamepad, sizeof(wgi_state.per_gamepad[0]) * (wgi_state.per_gamepad_count + 1)); if (!new_per_gamepad) { SDL_free(gamepad_state); - return SDL_OutOfMemory(); + return -1; } wgi_state.per_gamepad = new_per_gamepad; wgi_state.per_gamepad_count++; @@ -1227,7 +1227,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ctx = (RAWINPUT_DeviceContext *)SDL_calloc(1, sizeof(RAWINPUT_DeviceContext)); if (!ctx) { - return SDL_OutOfMemory(); + return -1; } joystick->hwdata = ctx; @@ -1259,7 +1259,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ctx->data = (HIDP_DATA *)SDL_malloc(ctx->max_data_length * sizeof(*ctx->data)); if (!ctx->data) { RAWINPUT_JoystickClose(joystick); - return SDL_OutOfMemory(); + return -1; } if (SDL_HidP_GetCaps(ctx->preparsed_data, &caps) != HIDP_STATUS_SUCCESS) { @@ -1304,7 +1304,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ctx->button_indices = (USHORT *)SDL_malloc(joystick->nbuttons * sizeof(*ctx->button_indices)); if (!ctx->button_indices) { RAWINPUT_JoystickClose(joystick); - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < caps.NumberInputButtonCaps; ++i) { @@ -1357,7 +1357,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ctx->axis_indices = (USHORT *)SDL_malloc(joystick->naxes * sizeof(*ctx->axis_indices)); if (!ctx->axis_indices) { RAWINPUT_JoystickClose(joystick); - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < caps.NumberInputValueCaps; ++i) { @@ -1390,7 +1390,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) ctx->hat_indices = (USHORT *)SDL_malloc(joystick->nhats * sizeof(*ctx->hat_indices)); if (!ctx->hat_indices) { RAWINPUT_JoystickClose(joystick); - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < caps.NumberInputValueCaps; ++i) { diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 5f4ddab209f83..f0ee81d22f37a 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -128,7 +128,6 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count); if (!raw_devices) { - SDL_OutOfMemory(); return SDL_FALSE; } @@ -720,7 +719,7 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index) hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata)); if (!hwdata) { - return SDL_OutOfMemory(); + return -1; } joystick->hwdata = hwdata; diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index bb95a53aca52e..3ce542493f38a 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -670,12 +670,10 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index) /* allocate memory for system specific hardware data */ joystick->instance_id = device->nInstanceID; - joystick->hwdata = - (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata)); + joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata)); if (!joystick->hwdata) { - return SDL_OutOfMemory(); + return -1; } - SDL_zerop(joystick->hwdata); joystick->hwdata->guid = device->guid; if (device->bXInputDevice) { diff --git a/src/locale/SDL_locale.c b/src/locale/SDL_locale.c index 363d0dd86377d..aef5d6ffc9093 100644 --- a/src/locale/SDL_locale.c +++ b/src/locale/SDL_locale.c @@ -48,7 +48,6 @@ static SDL_Locale *build_locales_from_csv_string(char *csv) loc = retval = (SDL_Locale *)SDL_calloc(1, alloclen); if (!retval) { - SDL_OutOfMemory(); return NULL; /* oh well */ } ptr = (char *)(retval + num_locales); diff --git a/src/locale/unix/SDL_syslocale.c b/src/locale/unix/SDL_syslocale.c index bf10e3b196be7..f420cdf6d9f16 100644 --- a/src/locale/unix/SDL_syslocale.c +++ b/src/locale/unix/SDL_syslocale.c @@ -72,7 +72,7 @@ int SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) SDL_assert(buflen > 0); tmp = SDL_small_alloc(char, buflen, &isstack); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } *tmp = '\0'; diff --git a/src/locale/windows/SDL_syslocale.c b/src/locale/windows/SDL_syslocale.c index 977ed0461e4ff..e26f129dcd5d2 100644 --- a/src/locale/windows/SDL_syslocale.c +++ b/src/locale/windows/SDL_syslocale.c @@ -66,7 +66,7 @@ static int SDL_SYS_GetPreferredLocales_vista(char *buf, size_t buflen) wbuf = SDL_small_alloc(WCHAR, wbuflen, &isstack); if (!wbuf) { - return SDL_OutOfMemory(); + return -1; } if (!pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numlangs, wbuf, &wbuflen)) { diff --git a/src/misc/windows/SDL_sysurl.c b/src/misc/windows/SDL_sysurl.c index bb89d55f6632b..38bf896f708b4 100644 --- a/src/misc/windows/SDL_sysurl.c +++ b/src/misc/windows/SDL_sysurl.c @@ -47,7 +47,7 @@ int SDL_SYS_OpenURL(const char *url) wurl = WIN_UTF8ToStringW(url); if (!wurl) { WIN_CoUninitialize(); - return SDL_OutOfMemory(); + return -1; } /* Success returns value greater than 32. Less is an error. */ diff --git a/src/misc/winrt/SDL_sysurl.cpp b/src/misc/winrt/SDL_sysurl.cpp index e117a4e1481e8..23bf289d4cc1f 100644 --- a/src/misc/winrt/SDL_sysurl.cpp +++ b/src/misc/winrt/SDL_sysurl.cpp @@ -27,7 +27,7 @@ int SDL_SYS_OpenURL(const char *url) { WCHAR *wurl = WIN_UTF8ToStringW(url); if (!wurl) { - return SDL_OutOfMemory(); + return -1; } auto strurl = ref new Platform::String(wurl); SDL_free(wurl); diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 464b8f2e3e400..f302440ffdede 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -293,7 +293,6 @@ void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, ptr = SDL_realloc(renderer->vertex_data, newsize); if (!ptr) { - SDL_OutOfMemory(); return NULL; } renderer->vertex_data = ptr; @@ -321,7 +320,6 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) } else { retval = SDL_calloc(1, sizeof(*retval)); if (!retval) { - SDL_OutOfMemory(); return NULL; } } @@ -1158,7 +1156,6 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert } texture = (SDL_Texture *)SDL_calloc(1, sizeof(*texture)); if (!texture) { - SDL_OutOfMemory(); return NULL; } texture->magic = &SDL_texture_magic; @@ -1566,7 +1563,7 @@ static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect, if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, rect->w, rect->h, temp_pixels, temp_pitch); @@ -1606,7 +1603,7 @@ static int SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect, if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_ConvertPixels(rect->w, rect->h, texture->format, pixels, pitch, @@ -1699,7 +1696,7 @@ static int SDL_UpdateTextureYUVPlanar(SDL_Texture *texture, const SDL_Rect *rect if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, rect->w, rect->h, temp_pixels, temp_pitch); @@ -1749,7 +1746,7 @@ static int SDL_UpdateTextureNVPlanar(SDL_Texture *texture, const SDL_Rect *rect, if (alloclen > 0) { void *temp_pixels = SDL_malloc(alloclen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format, rect->w, rect->h, temp_pixels, temp_pitch); @@ -2694,7 +2691,7 @@ static int RenderPointsWithRects(SDL_Renderer *renderer, const SDL_FPoint *fpoin frects = SDL_small_alloc(SDL_FRect, count, &isstack); if (!frects) { - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < count; ++i) { @@ -2814,7 +2811,7 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i points = SDL_small_alloc(SDL_FPoint, numpixels, &isstack); if (!points) { - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < numpixels; ++i) { points[i].x = (float)x; @@ -2857,7 +2854,7 @@ static int RenderLinesWithRectsF(SDL_Renderer *renderer, frects = SDL_small_alloc(SDL_FRect, count - 1, &isstack); if (!frects) { - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < count - 1; ++i) { @@ -3160,7 +3157,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun frects = SDL_small_alloc(SDL_FRect, count, &isstack); if (!frects) { - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < count; ++i) { frects[i].x = rects[i].x * renderer->view->scale.x; diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index 9c123dd0422f7..9a4cc3ac2a3b7 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -47,7 +47,6 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) swdata = (SDL_SW_YUVTexture *)SDL_calloc(1, sizeof(*swdata)); if (!swdata) { - SDL_OutOfMemory(); return NULL; } @@ -59,13 +58,11 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) size_t dst_size; if (SDL_CalculateYUVSize(format, w, h, &dst_size, NULL) < 0) { SDL_SW_DestroyYUVTexture(swdata); - SDL_OutOfMemory(); return NULL; } swdata->pixels = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), dst_size); if (!swdata->pixels) { SDL_SW_DestroyYUVTexture(swdata); - SDL_OutOfMemory(); return NULL; } } diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 73a8a71508db6..744055bcb3d58 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -525,7 +525,7 @@ static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P texturedata = (D3D_TextureData *)SDL_calloc(1, sizeof(*texturedata)); if (!texturedata) { - return SDL_OutOfMemory(); + return -1; } texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR; @@ -661,7 +661,7 @@ static int D3D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, texturedata->pitch = texture->w; texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2); if (!texturedata->pixels) { - return SDL_OutOfMemory(); + return -1; } } *pixels = @@ -1562,7 +1562,6 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; @@ -1570,7 +1569,6 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 4119275e6f0b0..9dfeb928b7eb7 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -399,7 +399,6 @@ static ID3D11BlendState *D3D11_CreateBlendState(SDL_Renderer *renderer, SDL_Blen blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes)); if (!blendModes) { SAFE_RELEASE(blendState); - SDL_OutOfMemory(); return NULL; } blendModes[data->blendModesCount].blendMode = blendMode; @@ -1095,7 +1094,6 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL textureData = (D3D11_TextureData *)SDL_calloc(1, sizeof(*textureData)); if (!textureData) { - SDL_OutOfMemory(); return -1; } textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; @@ -1554,7 +1552,7 @@ static int D3D11_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, textureData->pitch = texture->w; textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2); if (!textureData->pixels) { - return SDL_OutOfMemory(); + return -1; } } textureData->locked_rect = *rect; @@ -2436,7 +2434,6 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; @@ -2444,7 +2441,6 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 195371406e4f0..91fdffbdec47d 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -644,7 +644,6 @@ static D3D12_PipelineState *D3D12_CreatePipelineState(SDL_Renderer *renderer, pipelineStates = (D3D12_PipelineState *)SDL_realloc(data->pipelineStates, (data->pipelineStateCount + 1) * sizeof(*pipelineStates)); if (!pipelineStates) { SAFE_RELEASE(pipelineState); - SDL_OutOfMemory(); return NULL; } @@ -1460,7 +1459,6 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL textureData = (D3D12_TextureData *)SDL_calloc(1, sizeof(*textureData)); if (!textureData) { - SDL_OutOfMemory(); return -1; } textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR; @@ -1910,7 +1908,7 @@ static int D3D12_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, textureData->pitch = texture->w; textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2); if (!textureData->pixels) { - return SDL_OutOfMemory(); + return -1; } } textureData->lockedRect = *rect; @@ -2987,7 +2985,6 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } renderer->magic = &SDL_renderer_magic; @@ -2995,7 +2992,6 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 983e079398857..4686fbd888ab1 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -339,7 +339,6 @@ static MTLBlendFactor GetBlendFactor(SDL_BlendFactor factor) return (__bridge id)pipeline.pipe; } else { CFBridgingRelease(pipeline.pipe); - SDL_OutOfMemory(); return NULL; } } @@ -401,7 +400,6 @@ void MakeShaderPipelines(METAL_RenderData *data, METAL_ShaderPipelines *pipeline allpipelines = SDL_realloc(allpipelines, (count + 1) * sizeof(METAL_ShaderPipelines)); if (allpipelines == NULL) { - SDL_OutOfMemory(); return NULL; } @@ -1507,7 +1505,7 @@ static int METAL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, temp_pitch = rect->w * 4UL; temp_pixels = SDL_malloc(temp_pitch * rect->h); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } [mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0]; @@ -1747,7 +1745,6 @@ static SDL_MetalView GetWindowView(SDL_Window *window) renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 8a102f649c7d9..96ca76bd62a00 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -468,7 +468,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr data = (GL_TextureData *)SDL_calloc(1, sizeof(*data)); if (!data) { - return SDL_OutOfMemory(); + return -1; } if (texture->access == SDL_TEXTUREACCESS_STREAMING) { @@ -488,7 +488,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr data->pixels = SDL_calloc(1, size); if (!data->pixels) { SDL_free(data); - return SDL_OutOfMemory(); + return -1; } } @@ -1483,7 +1483,7 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); temp_pixels = SDL_malloc((size_t)rect->h * temp_pitch); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_GetCurrentRenderOutputSize(renderer, &w, &h); @@ -1794,14 +1794,12 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); goto error; } data = (GL_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); goto error; } diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 9ff464c591bbc..1ea3afde8308c 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -421,7 +421,6 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin /* Create a program cache entry */ entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry)); if (!entry) { - SDL_OutOfMemory(); return NULL; } entry->vertex_shader = vertex; @@ -1466,7 +1465,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL /* Allocate a texture struct */ data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData)); if (!data) { - return SDL_OutOfMemory(); + return -1; } data->texture = 0; #ifdef GL_TEXTURE_EXTERNAL_OES @@ -1501,7 +1500,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL data->pixel_data = SDL_calloc(1, size); if (!data->pixel_data) { SDL_free(data); - return SDL_OutOfMemory(); + return -1; } } @@ -1623,7 +1622,7 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff if ((size_t)pitch != src_pitch) { blob = (Uint8 *)SDL_malloc(src_pitch * height); if (!blob) { - return SDL_OutOfMemory(); + return -1; } src = blob; for (y = 0; y < height; ++y) { @@ -1946,7 +1945,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, temp_pixels = SDL_malloc(buflen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_GetCurrentRenderOutputSize(renderer, &w, &h); @@ -2109,14 +2108,12 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c /* Create the renderer struct */ renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); if (!renderer) { - SDL_OutOfMemory(); goto error; } data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); goto error; } renderer->info = GLES2_RenderDriver.info; diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index d21c005b4e097..b715a8586e785 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -111,7 +111,7 @@ static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P GSTEXTURE *ps2_tex = (GSTEXTURE *)SDL_calloc(1, sizeof(GSTEXTURE)); if (!ps2_tex) { - return SDL_OutOfMemory(); + return -1; } ps2_tex->Width = texture->w; @@ -121,7 +121,7 @@ static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P if (!ps2_tex->Mem) { SDL_free(ps2_tex); - return SDL_OutOfMemory(); + return -1; } texture->driverdata = ps2_tex; @@ -595,14 +595,12 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { PS2_DestroyRenderer(renderer); - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index c2f8c31030151..df70837204d64 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -286,7 +286,7 @@ static int TextureSwizzle(PSP_TextureData *psp_texture, void *dst) } if (!data) { - return SDL_OutOfMemory(); + return -1; } for (j = 0; j < height; j++, blockaddress += 16) { @@ -348,7 +348,7 @@ static int TextureUnswizzle(PSP_TextureData *psp_texture, void *dst) } if (!data) { - return SDL_OutOfMemory(); + return -1; } ydst = (unsigned char *)data; @@ -392,7 +392,7 @@ static int TextureSpillToSram(PSP_RenderData *data, PSP_TextureData *psp_texture // Texture was swizzled in vram, just copy to system memory void *sdata = SDL_malloc(psp_texture->size); if (!sdata) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(sdata, psp_texture->data, psp_texture->size); @@ -484,7 +484,7 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P PSP_TextureData *psp_texture = (PSP_TextureData *)SDL_calloc(1, sizeof(*psp_texture)); if (!psp_texture) { - return SDL_OutOfMemory(); + return -1; } psp_texture->swizzled = SDL_FALSE; @@ -527,7 +527,7 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P if (!psp_texture->data) { SDL_free(psp_texture); - return SDL_OutOfMemory(); + return -1; } texture->driverdata = psp_texture; @@ -1304,14 +1304,12 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { PSP_DestroyRenderer(renderer); - SDL_OutOfMemory(); return NULL; } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 5f70345d9bd10..efa30f312c3de 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -1111,14 +1111,12 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } data = (SW_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SW_DestroyRenderer(renderer); - SDL_OutOfMemory(); return NULL; } data->surface = surface; diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 43cc0e2d213c2..ade52281e92a8 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -218,14 +218,12 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer)); if (!renderer) { - SDL_OutOfMemory(); return NULL; } data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData)); if (!data) { SDL_free(renderer); - SDL_OutOfMemory(); return NULL; } @@ -298,7 +296,7 @@ static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData)); if (!vita_texture) { - return SDL_OutOfMemory(); + return -1; } vita_texture->tex = create_gxm_texture( @@ -1111,7 +1109,7 @@ static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rec temp_pixels = SDL_malloc(buflen); if (!temp_pixels) { - return SDL_OutOfMemory(); + return -1; } SDL_GetCurrentRenderOutputSize(renderer, &w, &h); diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 88cda800c54d0..b706261d236d0 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -208,8 +208,6 @@ SDL_SensorID *SDL_GetSensors(int *count) if (count) { *count = 0; } - - SDL_OutOfMemory(); } } SDL_UnlockSensors(); @@ -330,7 +328,6 @@ SDL_Sensor *SDL_OpenSensor(SDL_SensorID instance_id) /* Create and initialize the sensor */ sensor = (SDL_Sensor *)SDL_calloc(sizeof(*sensor), 1); if (!sensor) { - SDL_OutOfMemory(); SDL_UnlockSensors(); return NULL; } diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index db137d5e2fe41..b2154b1634f26 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -147,7 +147,7 @@ static int SDL_ANDROID_SensorInit(void) if (sensors_count > 0) { SDL_sensors = (SDL_AndroidSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors)); if (!SDL_sensors) { - return SDL_OutOfMemory(); + return -1; } for (i = 0; i < sensors_count; ++i) { diff --git a/src/sensor/coremotion/SDL_coremotionsensor.m b/src/sensor/coremotion/SDL_coremotionsensor.m index 87021ca20759a..7fdc28a5d2fed 100644 --- a/src/sensor/coremotion/SDL_coremotionsensor.m +++ b/src/sensor/coremotion/SDL_coremotionsensor.m @@ -57,7 +57,7 @@ static int SDL_COREMOTION_SensorInit(void) if (sensors_count > 0) { SDL_sensors = (SDL_CoreMotionSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors)); if (!SDL_sensors) { - return SDL_OutOfMemory(); + return -1; } i = 0; @@ -118,7 +118,7 @@ static int SDL_COREMOTION_SensorOpen(SDL_Sensor *sensor, int device_index) hwdata = (struct sensor_hwdata *)SDL_calloc(1, sizeof(*hwdata)); if (hwdata == NULL) { - return SDL_OutOfMemory(); + return -1; } sensor->hwdata = hwdata; diff --git a/src/sensor/vita/SDL_vitasensor.c b/src/sensor/vita/SDL_vitasensor.c index 9495a5e2db297..04323228c1b09 100644 --- a/src/sensor/vita/SDL_vitasensor.c +++ b/src/sensor/vita/SDL_vitasensor.c @@ -52,7 +52,7 @@ static int SDL_VITA_SensorInit(void) SDL_sensors = (SDL_VitaSensor *)SDL_calloc(SDL_sensors_count, sizeof(*SDL_sensors)); if (!SDL_sensors) { - return SDL_OutOfMemory(); + return -1; } SDL_sensors[0].type = SDL_SENSOR_ACCEL; @@ -119,7 +119,7 @@ static int SDL_VITA_SensorOpen(SDL_Sensor *sensor, int device_index) hwdata = (struct sensor_hwdata *)SDL_calloc(1, sizeof(*hwdata)); if (!hwdata) { - return SDL_OutOfMemory(); + return -1; } sensor->hwdata = hwdata; diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index a3bad4f51b6ca..cbd98875c2d66 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -296,7 +296,7 @@ static int ConnectSensor(ISensor *sensor) SysFreeString(bstr_name); } if (!name) { - return SDL_OutOfMemory(); + return -1; } SDL_LockSensors(); @@ -304,7 +304,7 @@ static int ConnectSensor(ISensor *sensor) if (!new_sensors) { SDL_UnlockSensors(); SDL_free(name); - return SDL_OutOfMemory(); + return -1; } ISensor_AddRef(sensor); diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c index c9ffd8e77dbd6..cfa9036c8e082 100644 --- a/src/stdlib/SDL_malloc.c +++ b/src/stdlib/SDL_malloc.c @@ -5287,7 +5287,10 @@ void *SDL_malloc(size_t size) mem = s_mem.malloc_func(size); if (mem) { SDL_AtomicIncRef(&s_mem.num_allocations); + } else { + SDL_OutOfMemory(); } + return mem; } @@ -5303,7 +5306,10 @@ void *SDL_calloc(size_t nmemb, size_t size) mem = s_mem.calloc_func(nmemb, size); if (mem) { SDL_AtomicIncRef(&s_mem.num_allocations); + } else { + SDL_OutOfMemory(); } + return mem; } @@ -5318,7 +5324,10 @@ void *SDL_realloc(void *ptr, size_t size) mem = s_mem.realloc_func(ptr, size); if (mem && !ptr) { SDL_AtomicIncRef(&s_mem.num_allocations); + } else if (!mem) { + SDL_OutOfMemory(); } + return mem; } diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index efc7e6bef234a..966c0c016d336 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -103,7 +103,6 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags) state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state)); if (!state) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 49f24d47e1d7d..84ec9a9ed7534 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -60,7 +60,7 @@ int SDL_SetTLS(SDL_TLSID id, const void *value, void(SDLCALL *destructor)(void * newlimit = (id + TLS_ALLOC_CHUNKSIZE); new_storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage) + (newlimit - 1) * sizeof(storage->array[0])); if (!new_storage) { - return SDL_OutOfMemory(); + return -1; } storage = new_storage; storage->limit = newlimit; @@ -186,10 +186,7 @@ int SDL_Generic_SetTLSData(SDL_TLSData *data) } SDL_UnlockMutex(SDL_generic_TLS_mutex); - if (!entry) { - return SDL_OutOfMemory(); - } - return 0; + return entry ? 0 : -1; } /* Non-thread-safe global error variable */ @@ -331,7 +328,6 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *), /* Allocate memory for the thread info structure */ thread = (SDL_Thread *)SDL_calloc(1, sizeof(*thread)); if (!thread) { - SDL_OutOfMemory(); return NULL; } thread->status = -1; @@ -341,7 +337,6 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *), if (name) { thread->name = SDL_strdup(name); if (!thread->name) { - SDL_OutOfMemory(); SDL_free(thread); return NULL; } diff --git a/src/thread/generic/SDL_syscond.c b/src/thread/generic/SDL_syscond.c index e6b1a5d6bd7af..6a8b06aa8a062 100644 --- a/src/thread/generic/SDL_syscond.c +++ b/src/thread/generic/SDL_syscond.c @@ -64,8 +64,6 @@ SDL_Condition *SDL_CreateCondition_generic(void) SDL_DestroyCondition_generic((SDL_Condition *)cond); cond = NULL; } - } else { - SDL_OutOfMemory(); } return (SDL_Condition *)cond; } diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index 95f4cecd1f0f1..1f21ca506f0ff 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -45,8 +45,6 @@ SDL_Mutex *SDL_CreateMutex(void) SDL_free(mutex); mutex = NULL; } - } else { - SDL_OutOfMemory(); } #endif // !SDL_THREADS_DISABLED diff --git a/src/thread/generic/SDL_sysrwlock.c b/src/thread/generic/SDL_sysrwlock.c index a38b81d6ac76f..73c15e961e5a4 100644 --- a/src/thread/generic/SDL_sysrwlock.c +++ b/src/thread/generic/SDL_sysrwlock.c @@ -59,7 +59,6 @@ SDL_RWLock *SDL_CreateRWLock_generic(void) SDL_RWLock *rwlock = (SDL_RWLock *) SDL_calloc(1, sizeof (*rwlock)); if (!rwlock) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/thread/generic/SDL_syssem.c b/src/thread/generic/SDL_syssem.c index bf945695fdf96..e2e0f9ca91974 100644 --- a/src/thread/generic/SDL_syssem.c +++ b/src/thread/generic/SDL_syssem.c @@ -67,7 +67,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); if (!sem) { - SDL_OutOfMemory(); return NULL; } sem->count = initial_value; diff --git a/src/thread/n3ds/SDL_syscond.c b/src/thread/n3ds/SDL_syscond.c index 5595010fb6ad2..aae480b232e66 100644 --- a/src/thread/n3ds/SDL_syscond.c +++ b/src/thread/n3ds/SDL_syscond.c @@ -37,8 +37,6 @@ SDL_Condition *SDL_CreateCondition(void) SDL_Condition *cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition)); if (cond) { CondVar_Init(&cond->cond_variable); - } else { - SDL_OutOfMemory(); } return cond; } diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 57d189db5631f..61455517800c5 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -31,8 +31,6 @@ SDL_Mutex *SDL_CreateMutex(void) SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex)); if (mutex) { RecursiveLock_Init(&mutex->lock); - } else { - SDL_OutOfMemory(); } return mutex; } diff --git a/src/thread/n3ds/SDL_syssem.c b/src/thread/n3ds/SDL_syssem.c index f41d69c348894..31bca0dd213f9 100644 --- a/src/thread/n3ds/SDL_syssem.c +++ b/src/thread/n3ds/SDL_syssem.c @@ -44,7 +44,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem)); if (!sem) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index 04e0b2d831cf7..ceb191181ee77 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -59,8 +59,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_free(sem); sem = NULL; } - } else { - SDL_OutOfMemory(); } return sem; diff --git a/src/thread/psp/SDL_syscond.c b/src/thread/psp/SDL_syscond.c index 0dc6f177d3075..bfe4f42bac527 100644 --- a/src/thread/psp/SDL_syscond.c +++ b/src/thread/psp/SDL_syscond.c @@ -52,8 +52,6 @@ SDL_Condition *SDL_CreateCondition(void) SDL_DestroyCondition(cond); cond = NULL; } - } else { - SDL_OutOfMemory(); } return cond; } diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 82e63e6febaed..7fb94ee7596b1 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -52,8 +52,6 @@ SDL_Mutex *SDL_CreateMutex(void) mutex = NULL; SDL_SetError("Error trying to create mutex: %lx", res); } - } else { - SDL_OutOfMemory(); } return mutex; } diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index c6b1a3c571282..098a15bb3afc5 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -49,8 +49,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_free(sem); sem = NULL; } - } else { - SDL_OutOfMemory(); } return sem; diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index 30f796cd7fbc8..9ffbd53c5eafe 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -46,8 +46,6 @@ SDL_Mutex *SDL_CreateMutex(void) SDL_free(mutex); mutex = NULL; } - } else { - SDL_OutOfMemory(); } return mutex; } diff --git a/src/thread/pthread/SDL_sysrwlock.c b/src/thread/pthread/SDL_sysrwlock.c index 485264e85e432..6d70ac8eadaf1 100644 --- a/src/thread/pthread/SDL_sysrwlock.c +++ b/src/thread/pthread/SDL_sysrwlock.c @@ -41,8 +41,6 @@ SDL_RWLock *SDL_CreateRWLock(void) SDL_free(rwlock); rwlock = NULL; } - } else { - SDL_OutOfMemory(); } return rwlock; } diff --git a/src/thread/pthread/SDL_syssem.c b/src/thread/pthread/SDL_syssem.c index d2ecb57d9ebeb..0593e4b2aa5a7 100644 --- a/src/thread/pthread/SDL_syssem.c +++ b/src/thread/pthread/SDL_syssem.c @@ -48,8 +48,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_free(sem); sem = NULL; } - } else { - SDL_OutOfMemory(); } return sem; } diff --git a/src/thread/vita/SDL_syscond.c b/src/thread/vita/SDL_syscond.c index 2218f755eae21..fc8e1c9e36d5c 100644 --- a/src/thread/vita/SDL_syscond.c +++ b/src/thread/vita/SDL_syscond.c @@ -52,8 +52,6 @@ SDL_Condition *SDL_CreateCondition(void) SDL_DestroyCondition(cond); cond = NULL; } - } else { - SDL_OutOfMemory(); } return cond; } diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index e63e77fa59f96..38f31ab05b1f9 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -48,8 +48,6 @@ SDL_Mutex *SDL_CreateMutex(void) mutex = NULL; SDL_SetError("Error trying to create mutex: %x", res); } - } else { - SDL_OutOfMemory(); } return mutex; } diff --git a/src/thread/vita/SDL_syssem.c b/src/thread/vita/SDL_syssem.c index f43cbaba5892f..ca8636c35ceba 100644 --- a/src/thread/vita/SDL_syssem.c +++ b/src/thread/vita/SDL_syssem.c @@ -50,8 +50,6 @@ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) SDL_free(sem); sem = NULL; } - } else { - SDL_OutOfMemory(); } return sem; diff --git a/src/thread/windows/SDL_syscond_cv.c b/src/thread/windows/SDL_syscond_cv.c index 91a5e23bda9cb..fdc806411d411 100644 --- a/src/thread/windows/SDL_syscond_cv.c +++ b/src/thread/windows/SDL_syscond_cv.c @@ -80,23 +80,14 @@ typedef struct SDL_cond_cv static SDL_Condition *SDL_CreateCondition_cv(void) { - SDL_cond_cv *cond; - /* Relies on CONDITION_VARIABLE_INIT == 0. */ - cond = (SDL_cond_cv *)SDL_calloc(1, sizeof(*cond)); - if (!cond) { - SDL_OutOfMemory(); - } - - return (SDL_Condition *)cond; + return (SDL_Condition *)SDL_calloc(1, sizeof(SDL_cond_cv)); } static void SDL_DestroyCondition_cv(SDL_Condition *cond) { - if (cond) { - /* There are no kernel allocated resources */ - SDL_free(cond); - } + /* There are no kernel allocated resources */ + SDL_free(cond); } static int SDL_SignalCondition_cv(SDL_Condition *_cond) diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index 1d62e7e8d65fd..aef7e93126d5c 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -58,15 +58,10 @@ static pfnTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive = NULL; static SDL_Mutex *SDL_CreateMutex_srw(void) { - SDL_mutex_srw *mutex; - - mutex = (SDL_mutex_srw *)SDL_calloc(1, sizeof(*mutex)); - if (!mutex) { - SDL_OutOfMemory(); + SDL_mutex_srw *mutex = (SDL_mutex_srw *)SDL_calloc(1, sizeof(*mutex)); + if (mutex) { + pInitializeSRWLock(&mutex->srw); } - - pInitializeSRWLock(&mutex->srw); - return (SDL_Mutex *)mutex; } @@ -153,8 +148,6 @@ static SDL_Mutex *SDL_CreateMutex_cs(void) #else InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000); #endif - } else { - SDL_OutOfMemory(); } return (SDL_Mutex *)mutex; } diff --git a/src/thread/windows/SDL_sysrwlock_srw.c b/src/thread/windows/SDL_sysrwlock_srw.c index 5b5953a38985d..864743fdb00f5 100644 --- a/src/thread/windows/SDL_sysrwlock_srw.c +++ b/src/thread/windows/SDL_sysrwlock_srw.c @@ -88,10 +88,9 @@ typedef struct SDL_rwlock_srw static SDL_RWLock *SDL_CreateRWLock_srw(void) { SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *)SDL_calloc(1, sizeof(*rwlock)); - if (!rwlock) { - SDL_OutOfMemory(); + if (rwlock) { + pInitializeSRWLock(&rwlock->srw); } - pInitializeSRWLock(&rwlock->srw); return (SDL_RWLock *)rwlock; } diff --git a/src/thread/windows/SDL_syssem.c b/src/thread/windows/SDL_syssem.c index 493dd3178657b..acb0950bc9511 100644 --- a/src/thread/windows/SDL_syssem.c +++ b/src/thread/windows/SDL_syssem.c @@ -85,17 +85,13 @@ static SDL_Semaphore *SDL_CreateSemaphore_atom(Uint32 initial_value) sem = (SDL_sem_atom *)SDL_malloc(sizeof(*sem)); if (sem) { sem->count = initial_value; - } else { - SDL_OutOfMemory(); } return (SDL_Semaphore *)sem; } static void SDL_DestroySemaphore_atom(SDL_Semaphore *sem) { - if (sem) { - SDL_free(sem); - } + SDL_free(sem); } static int SDL_WaitSemaphoreTimeoutNS_atom(SDL_Semaphore *_sem, Sint64 timeoutNS) @@ -226,6 +222,7 @@ static SDL_Semaphore *SDL_CreateSemaphore_kern(Uint32 initial_value) sem = (SDL_sem_kern *)SDL_malloc(sizeof(*sem)); if (sem) { /* Create the semaphore, with max value 32K */ +// !!! FIXME: CreateSemaphoreEx is available in Vista and later, so if XP support is dropped, we can lose this #ifdef. #ifdef __WINRT__ sem->id = CreateSemaphoreEx(NULL, initial_value, 32 * 1024, NULL, 0, SEMAPHORE_ALL_ACCESS); #else @@ -237,8 +234,6 @@ static SDL_Semaphore *SDL_CreateSemaphore_kern(Uint32 initial_value) SDL_free(sem); sem = NULL; } - } else { - SDL_OutOfMemory(); } return (SDL_Semaphore *)sem; } diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index a5ca6757972bc..4b72503d6d5f1 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -297,7 +297,6 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para } else { timer = (SDL_Timer *)SDL_malloc(sizeof(*timer)); if (!timer) { - SDL_OutOfMemory(); return 0; } } @@ -311,7 +310,6 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); if (!entry) { SDL_free(timer); - SDL_OutOfMemory(); return 0; } entry->timer = timer; @@ -423,7 +421,6 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *para entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); if (!entry) { - SDL_OutOfMemory(); return 0; } entry->timerID = ++data->nextID; diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index a9e82465c351d..2bfd6edb43f8a 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -1081,7 +1081,7 @@ static int RLEAlphaSurface(SDL_Surface *surface) maxsize += sizeof(RLEDestFormat); rlebuf = (Uint8 *)SDL_malloc(maxsize); if (!rlebuf) { - return SDL_OutOfMemory(); + return -1; } { /* save the destination format so we can undo the encoding later */ @@ -1300,7 +1300,7 @@ static int RLEColorkeySurface(SDL_Surface *surface) rlebuf = (Uint8 *)SDL_malloc(maxsize); if (!rlebuf) { - return SDL_OutOfMemory(); + return -1; } /* Set up the conversion */ diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c index df116314b54cd..e6266724e855e 100644 --- a/src/video/SDL_clipboard.c +++ b/src/video/SDL_clipboard.c @@ -97,7 +97,7 @@ int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanu } if (num_allocated < num_mime_types) { SDL_ClearClipboardData(); - return SDL_OutOfMemory(); + return -1; } _this->num_clipboard_mime_types = num_mime_types; } @@ -156,8 +156,6 @@ void *SDL_GetInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type if (data) { SDL_memcpy(data, provided_data, *size); SDL_memset((Uint8 *)data + *size, 0, sizeof(Uint32)); - } else { - SDL_OutOfMemory(); } } } diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index a2d72114bf64e..60c66f37dd7d7 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -476,7 +476,7 @@ int SDL_EGL_LoadLibraryOnly(SDL_VideoDevice *_this, const char *egl_path) _this->egl_data = (struct SDL_EGL_VideoData *)SDL_calloc(1, sizeof(SDL_EGL_VideoData)); if (!_this->egl_data) { - return SDL_OutOfMemory(); + return -1; } if (SDL_EGL_LoadLibraryInternal(_this, egl_path) < 0) { diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index aaeb1d9f2a819..d7be3e1368e34 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -565,7 +565,6 @@ SDL_PixelFormat *SDL_CreatePixelFormat(Uint32 pixel_format) format = SDL_malloc(sizeof(*format)); if (!format) { SDL_AtomicUnlock(&formats_lock); - SDL_OutOfMemory(); return NULL; } if (SDL_InitFormat(format, pixel_format) < 0) { @@ -705,14 +704,12 @@ SDL_Palette *SDL_CreatePalette(int ncolors) palette = (SDL_Palette *)SDL_malloc(sizeof(*palette)); if (!palette) { - SDL_OutOfMemory(); return NULL; } palette->colors = (SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors)); if (!palette->colors) { SDL_free(palette); - SDL_OutOfMemory(); return NULL; } palette->ncolors = ncolors; @@ -989,7 +986,6 @@ static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) } map = (Uint8 *)SDL_calloc(256, sizeof(Uint8)); if (!map) { - SDL_OutOfMemory(); return NULL; } for (i = 0; i < src->ncolors; ++i) { @@ -1012,7 +1008,6 @@ static Uint8 *Map1toN(SDL_PixelFormat *src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); map = (Uint8 *)SDL_calloc(256, bpp); if (!map) { - SDL_OutOfMemory(); return NULL; } @@ -1048,7 +1043,6 @@ SDL_BlitMap *SDL_AllocBlitMap(void) /* Allocate the empty map */ map = (SDL_BlitMap *)SDL_calloc(1, sizeof(*map)); if (!map) { - SDL_OutOfMemory(); return NULL; } map->info.r = 0xFF; diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index bc71c541341b8..b59df0c51eb45 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -136,14 +136,12 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) if (SDL_CalculateSize(format, width, height, &size, &pitch, SDL_FALSE /* not minimal pitch */) < 0) { /* Overflow... */ - SDL_OutOfMemory(); return NULL; } /* Allocate the surface */ surface = (SDL_Surface *)SDL_calloc(1, sizeof(*surface)); if (!surface) { - SDL_OutOfMemory(); return NULL; } @@ -182,7 +180,6 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size); if (!surface->pixels) { SDL_DestroySurface(surface); - SDL_OutOfMemory(); return NULL; } surface->flags |= SDL_SIMD_ALIGNED; @@ -232,7 +229,6 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc if (SDL_CalculateSize(format, width, height, NULL, &minimalPitch, SDL_TRUE /* minimal pitch */) < 0) { /* Overflow... */ - SDL_OutOfMemory(); return NULL; } diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index ee69721939807..3f416f2b738af 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -277,7 +277,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_DestroyRenderer(renderer); - return SDL_OutOfMemory(); + return -1; } SDL_SetPropertyWithCleanup(props, SDL_WINDOWTEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); @@ -324,7 +324,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U const size_t allocsize = (size_t)h * data->pitch; data->pixels = SDL_malloc((allocsize > 0) ? allocsize : 1); if (!data->pixels) { - return SDL_OutOfMemory(); + return -1; } } @@ -657,13 +657,11 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send new_display = (SDL_VideoDisplay *)SDL_malloc(sizeof(*new_display)); if (!new_display) { - SDL_OutOfMemory(); return 0; } displays = (SDL_VideoDisplay **)SDL_realloc(_this->displays, (_this->num_displays + 1) * sizeof(*displays)); if (!displays) { - SDL_OutOfMemory(); SDL_free(new_display); return 0; } @@ -767,8 +765,6 @@ SDL_DisplayID *SDL_GetDisplays(int *count) if (count) { *count = 0; } - - SDL_OutOfMemory(); } return displays; } @@ -1105,8 +1101,6 @@ const SDL_DisplayMode **SDL_GetFullscreenDisplayModes(SDL_DisplayID displayID, i if (count) { *count = 0; } - - SDL_OutOfMemory(); } return modes; } @@ -2020,7 +2014,6 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) window = (SDL_Window *)SDL_calloc(1, sizeof(*window)); if (!window) { - SDL_OutOfMemory(); return NULL; } window->magic = &_this->window_magic; diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index a16908a9d385f..f31d1009d4353 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -149,7 +149,6 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList( } if (!retval) { - SDL_OutOfMemory(); return NULL; } @@ -229,7 +228,6 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); if (!physicalDevices) { - SDL_OutOfMemory(); goto error; } @@ -272,7 +270,6 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, displayProperties = SDL_malloc(sizeof(VkDisplayPropertiesKHR) * displayPropertiesCount); if (!displayProperties) { - SDL_OutOfMemory(); goto error; } @@ -301,7 +298,6 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, displayModeProperties = SDL_malloc(sizeof(VkDisplayModePropertiesKHR) * displayModePropertiesCount); if (!displayModeProperties) { - SDL_OutOfMemory(); goto error; } @@ -348,7 +344,6 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, displayPlaneProperties = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * displayPlanePropertiesCount); if (!displayPlaneProperties) { - SDL_OutOfMemory(); goto error; } @@ -380,7 +375,6 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, planeSupportedDisplays = SDL_malloc(sizeof(VkDisplayKHR) * planeSupportedDisplaysCount); if (!planeSupportedDisplays) { SDL_free(displayPlaneProperties); - SDL_OutOfMemory(); goto error; } diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c index 6eb248bb66ceb..e8db133818b56 100644 --- a/src/video/SDL_yuv.c +++ b/src/video/SDL_yuv.c @@ -616,7 +616,7 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height, tmp = SDL_malloc((size_t)tmp_pitch * height); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } /* convert src/src_format to tmp/ARGB8888 */ @@ -997,7 +997,7 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height, tmp = SDL_malloc((size_t)tmp_pitch * height); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } /* convert src/src_format to tmp/ARGB8888 */ @@ -1086,7 +1086,7 @@ static int SDL_ConvertPixels_SwapUVPlanes(int width, int height, const void *src /* Allocate a temporary row for the swap */ tmp = (Uint8 *)SDL_malloc(UVwidth); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } for (y = 0; y < UVheight; ++y) { SDL_memcpy(tmp, row1, UVwidth); @@ -1144,7 +1144,7 @@ static int SDL_TARGETING("sse2") SDL_ConvertPixels_PackUVPlanes_to_NV_SSE2(int w /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch); if (tmp == NULL) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch); src = tmp; @@ -1210,7 +1210,7 @@ static int SDL_TARGETING("sse2") SDL_ConvertPixels_SplitNV_to_UVPlanes_SSE2(int /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch); if (tmp == NULL) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch); src = tmp; @@ -1322,7 +1322,7 @@ static int SDL_ConvertPixels_PackUVPlanes_to_NV_std(int width, int height, const /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch); src = tmp; @@ -1376,7 +1376,7 @@ static int SDL_ConvertPixels_SplitNV_to_UVPlanes_std(int width, int height, cons /* Need to make a copy of the buffer so we don't clobber it while converting */ tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch); if (!tmp) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch); src = tmp; diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c index bc97260b1b776..c3b7b14f2a2bc 100644 --- a/src/video/android/SDL_androidmouse.c +++ b/src/video/android/SDL_androidmouse.c @@ -68,10 +68,7 @@ static SDL_Cursor *Android_WrapCursor(int custom_cursor, int system_cursor) } else { SDL_free(cursor); cursor = NULL; - SDL_OutOfMemory(); } - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 1d6d0c282b1d2..e9b42a64dd240 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -87,13 +87,11 @@ static SDL_VideoDevice *Android_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!data) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 911345d22549b..c33a5ceef04c5 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -62,7 +62,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); if (!data) { - retval = SDL_OutOfMemory(); + retval = -1; goto endfunction; } diff --git a/src/video/cocoa/SDL_cocoaclipboard.m b/src/video/cocoa/SDL_cocoaclipboard.m index a6f85a13bcb97..a02c1f0622b73 100644 --- a/src/video/cocoa/SDL_cocoaclipboard.m +++ b/src/video/cocoa/SDL_cocoaclipboard.m @@ -148,8 +148,6 @@ int Cocoa_SetClipboardData(SDL_VideoDevice *_this) if (data) { [itemData getBytes: data length: length]; SDL_memset((Uint8 *)data + length, 0, sizeof(Uint32)); - } else { - SDL_OutOfMemory(); } break; } diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index e570397ee2521..49f828125195e 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -393,7 +393,7 @@ int Cocoa_InitMouse(SDL_VideoDevice *_this) SDL_Mouse *mouse = SDL_GetMouse(); SDL_MouseData *driverdata = (SDL_MouseData *)SDL_calloc(1, sizeof(SDL_MouseData)); if (driverdata == NULL) { - return SDL_OutOfMemory(); + return -1; } mouse->driverdata = driverdata; diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 0d93a5ef0649a..588d9e8c7b359 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -68,7 +68,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) data = nil; } if (!data) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 964cfa0e67427..debb76fdc3c66 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2458,7 +2458,6 @@ void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V retIccProfileData = SDL_malloc([iccProfileData length]); if (!retIccProfileData) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index 6a85ac9800e26..64dad5afd7c18 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -84,7 +84,6 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } device->is_dummy = SDL_TRUE; diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c index 2362d88373e0a..40d1af8afdffb 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.c +++ b/src/video/emscripten/SDL_emscriptenmouse.c @@ -42,14 +42,11 @@ static SDL_Cursor *Emscripten_CreateCursorFromString(const char *cursor_str, SDL_bool is_custom) { - SDL_Cursor *cursor; Emscripten_CursorData *curdata; - - cursor = SDL_calloc(1, sizeof(SDL_Cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(SDL_Cursor)); if (cursor) { curdata = (Emscripten_CursorData *)SDL_calloc(1, sizeof(*curdata)); if (!curdata) { - SDL_OutOfMemory(); SDL_free(cursor); return NULL; } @@ -57,8 +54,6 @@ static SDL_Cursor *Emscripten_CreateCursorFromString(const char *cursor_str, SDL curdata->system_cursor = cursor_str; curdata->is_custom = is_custom; cursor->driverdata = curdata; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index 43e74764c2cfc..000dc192d4290 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -62,7 +62,6 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } @@ -181,7 +180,7 @@ static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, S /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!wdata) { - return SDL_OutOfMemory(); + return -1; } selector = SDL_GetHint(SDL_HINT_EMSCRIPTEN_CANVAS_SELECTOR); diff --git a/src/video/gdk/SDL_gdktextinput.cpp b/src/video/gdk/SDL_gdktextinput.cpp index b073198817f2a..c4bdc83ea6e9a 100644 --- a/src/video/gdk/SDL_gdktextinput.cpp +++ b/src/video/gdk/SDL_gdktextinput.cpp @@ -88,10 +88,7 @@ static void SDLCALL GDK_InternalHintCallback( *(char **)userdata = NULL; } else { char *newString = SDL_strdup(newValue); - if (!newString) { - /* couldn't strdup, oh well */ - SDL_OutOfMemory(); - } else { + if (newString) { /* free previous value and write the new one */ SDL_free(*(char **)userdata); *(char **)userdata = newString; @@ -128,9 +125,7 @@ static void CALLBACK GDK_InternalTextEntryCallback(XAsyncBlock *asyncBlock) } else if (resultSize > 0) { /* +1 to be super sure that the buffer will be null terminated */ resultBuffer = (char *)SDL_calloc(sizeof(*resultBuffer), 1 + (size_t)resultSize); - if (!resultBuffer) { - SDL_OutOfMemory(); - } else { + if (resultBuffer) { /* still pass the original size that we got from ResultSize */ if (FAILED(hR = XGameUiShowTextEntryResult( asyncBlock, @@ -263,7 +258,6 @@ void GDK_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) g_TextBlock = (XAsyncBlock *)SDL_calloc(1, sizeof(*g_TextBlock)); if (!g_TextBlock) { - SDL_OutOfMemory(); return; } diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 6e881a6e9bf94..470242d992512 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -165,8 +165,6 @@ static SDL_Cursor * HAIKU_CreateSystemCursor(SDL_SystemCursor id) cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor)); if (cursor) { cursor->driverdata = (void *)new BCursor(cursorId); - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c index 1e092726aa02e..513f5f5338082 100644 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.c +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c @@ -159,7 +159,7 @@ static int KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor) ready_buffer = (uint8_t *)SDL_calloc(1, bufsize); if (!ready_buffer) { - ret = SDL_OutOfMemory(); + ret = -1; goto cleanup; } @@ -237,12 +237,10 @@ static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_ cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); if (!cursor) { - SDL_OutOfMemory(); goto cleanup; } curdata = (KMSDRM_CursorData *)SDL_calloc(1, sizeof(*curdata)); if (!curdata) { - SDL_OutOfMemory(); goto cleanup; } @@ -260,7 +258,6 @@ static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_ curdata->buffer = (uint32_t *)SDL_malloc(curdata->buffer_size); if (!curdata->buffer) { - SDL_OutOfMemory(); goto cleanup; } diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index ac28f6e168479..4ec049d677b4a 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -261,13 +261,11 @@ static SDL_VideoDevice *KMSDRM_CreateDevice(void) device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } viddata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!viddata) { - SDL_OutOfMemory(); goto cleanup; } viddata->devindex = devindex; @@ -364,7 +362,6 @@ KMSDRM_FBInfo *KMSDRM_FBFromBO(SDL_VideoDevice *_this, struct gbm_bo *bo) fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo)); if (!fb_info) { - SDL_OutOfMemory(); return NULL; } @@ -689,7 +686,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto /* Reserve memory for the new display's driverdata. */ dispdata = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); if (!dispdata) { - ret = SDL_OutOfMemory(); + ret = -1; goto cleanup; } @@ -852,7 +849,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); if (!modedata) { - ret = SDL_OutOfMemory(); + ret = -1; goto cleanup; } @@ -1460,7 +1457,7 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti /* Allocate window internal data */ windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!windata) { - return SDL_OutOfMemory(); + return -1; } /* Setup driver data for this window */ @@ -1559,7 +1556,7 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti SDL_Window **new_windows = (SDL_Window **)SDL_realloc(viddata->windows, new_max_windows * sizeof(SDL_Window *)); if (!new_windows) { - return SDL_OutOfMemory(); + return -1; } viddata->windows = new_windows; viddata->max_windows = new_max_windows; diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 727dab6a842c4..09930621065b2 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -54,7 +54,7 @@ int SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, framebuffer = SDL_CreateSurface(w, h, FRAMEBUFFER_FORMAT); if (!framebuffer) { - return SDL_OutOfMemory(); + return -1; } SDL_SetPropertyWithCleanup(SDL_GetWindowProperties(window), N3DS_SURFACE, framebuffer, CleanupSurface, NULL); diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c index 6eb88ec3d7e01..4e55642fe6da2 100644 --- a/src/video/n3ds/SDL_n3dsvideo.c +++ b/src/video/n3ds/SDL_n3dsvideo.c @@ -56,7 +56,6 @@ static SDL_VideoDevice *N3DS_CreateDevice(void) { SDL_VideoDevice *device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } @@ -105,7 +104,7 @@ static int AddN3DSDisplay(gfxScreen_t screen) SDL_VideoDisplay display; SDL_DisplayData *display_driver_data = SDL_calloc(1, sizeof(SDL_DisplayData)); if (!display_driver_data) { - return SDL_OutOfMemory(); + return -1; } SDL_zero(mode); @@ -155,7 +154,7 @@ static int N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Pro SDL_DisplayData *display_data; SDL_WindowData *window_data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!window_data) { - return SDL_OutOfMemory(); + return -1; } display_data = SDL_GetDisplayDriverDataForWindow(window); window_data->screen = display_data->screen; diff --git a/src/video/ngage/SDL_ngagevideo.cpp b/src/video/ngage/SDL_ngagevideo.cpp index d9af15d27616a..5d30d42259154 100644 --- a/src/video/ngage/SDL_ngagevideo.cpp +++ b/src/video/ngage/SDL_ngagevideo.cpp @@ -105,14 +105,12 @@ static SDL_VideoDevice *NGAGE_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } /* Initialize internal N-Gage specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!phdata) { - SDL_OutOfMemory(); SDL_free(device); return 0; } diff --git a/src/video/ngage/SDL_ngagewindow.cpp b/src/video/ngage/SDL_ngagewindow.cpp index 7a305ec3368d2..44296e1f00552 100644 --- a/src/video/ngage/SDL_ngagewindow.cpp +++ b/src/video/ngage/SDL_ngagewindow.cpp @@ -37,7 +37,7 @@ int NGAGE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie NGAGE_Window *ngage_window = (NGAGE_Window *)SDL_calloc(1, sizeof(NGAGE_Window)); if (!ngage_window) { - return SDL_OutOfMemory(); + return -1; } window->driverdata = ngage_window; diff --git a/src/video/offscreen/SDL_offscreenvideo.c b/src/video/offscreen/SDL_offscreenvideo.c index f4955862a834d..2b66260bda060 100644 --- a/src/video/offscreen/SDL_offscreenvideo.c +++ b/src/video/offscreen/SDL_offscreenvideo.c @@ -57,7 +57,6 @@ static SDL_VideoDevice *OFFSCREEN_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } diff --git a/src/video/offscreen/SDL_offscreenwindow.c b/src/video/offscreen/SDL_offscreenwindow.c index f90bba6822959..a51f8fd364de2 100644 --- a/src/video/offscreen/SDL_offscreenwindow.c +++ b/src/video/offscreen/SDL_offscreenwindow.c @@ -32,7 +32,7 @@ int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Prope SDL_WindowData *offscreen_window = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!offscreen_window) { - return SDL_OutOfMemory(); + return -1; } window->driverdata = offscreen_window; diff --git a/src/video/ps2/SDL_ps2video.c b/src/video/ps2/SDL_ps2video.c index ea12f7cbde133..273e97784f84b 100644 --- a/src/video/ps2/SDL_ps2video.c +++ b/src/video/ps2/SDL_ps2video.c @@ -96,7 +96,6 @@ static SDL_VideoDevice *PS2_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 27f9b47dbff61..95d0d387c2fcd 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -52,21 +52,18 @@ static SDL_VideoDevice *PSP_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } /* Initialize internal PSP specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!phdata) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } gldata = (SDL_GLDriverData *)SDL_calloc(1, sizeof(SDL_GLDriverData)); if (!gldata) { - SDL_OutOfMemory(); SDL_free(device); SDL_free(phdata); return NULL; @@ -197,7 +194,7 @@ int PSP_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!wdata) { - return SDL_OutOfMemory(); + return -1; } /* Setup driver data for this window */ diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index 1d915270c27dd..1bd8f839b7858 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -66,12 +66,10 @@ static SDL_Cursor *RPI_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); if (!cursor) { - SDL_OutOfMemory(); return NULL; } curdata = (RPI_CursorData *)SDL_calloc(1, sizeof(*curdata)); if (!curdata) { - SDL_OutOfMemory(); SDL_free(cursor); return NULL; } diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 5b1c45ad07700..25efc514cf3a6 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -77,14 +77,12 @@ static SDL_VideoDevice *RPI_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } /* Initialize internal data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!phdata) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } @@ -236,7 +234,7 @@ int RPI_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!wdata) { - return SDL_OutOfMemory(); + return -1; } display = SDL_GetVideoDisplayForWindow(window); displaydata = display->driverdata; diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c index 1f53f85af4b81..9a884c86f5512 100644 --- a/src/video/riscos/SDL_riscosframebuffer.c +++ b/src/video/riscos/SDL_riscosframebuffer.c @@ -63,7 +63,7 @@ int RISCOS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, U size = sizeof(sprite_area) + sizeof(sprite_header) + ((*pitch) * h); driverdata->fb_area = SDL_malloc(size); if (!driverdata->fb_area) { - return SDL_OutOfMemory(); + return -1; } driverdata->fb_area->size = size; diff --git a/src/video/riscos/SDL_riscosmodes.c b/src/video/riscos/SDL_riscosmodes.c index d5cb447528e1c..eb0aa4bc60571 100644 --- a/src/video/riscos/SDL_riscosmodes.c +++ b/src/video/riscos/SDL_riscosmodes.c @@ -220,7 +220,7 @@ int RISCOS_InitModes(SDL_VideoDevice *_this) size = measure_mode_block(current_mode); mode.driverdata = copy_memory(current_mode, size, size); if (!mode.driverdata) { - return SDL_OutOfMemory(); + return -1; } if (SDL_AddBasicVideoDisplay(&mode) == 0) { @@ -247,7 +247,7 @@ int RISCOS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) block = SDL_malloc(-regs.r[7]); if (!block) { - return SDL_OutOfMemory(); + return -1; } regs.r[6] = (int)block; @@ -270,7 +270,7 @@ int RISCOS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) mode.driverdata = convert_mode_block(pos + 4); if (!mode.driverdata) { SDL_free(block); - return SDL_OutOfMemory(); + return -1; } if (!SDL_AddFullscreenDisplayMode(display, &mode)) { diff --git a/src/video/riscos/SDL_riscosmouse.c b/src/video/riscos/SDL_riscosmouse.c index 40b7cf2bb0413..de31bcdcf4478 100644 --- a/src/video/riscos/SDL_riscosmouse.c +++ b/src/video/riscos/SDL_riscosmouse.c @@ -30,14 +30,10 @@ static SDL_Cursor *RISCOS_CreateDefaultCursor() { - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { /* NULL is used to indicate the default cursor */ cursor->driverdata = NULL; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c index d132abdb80f9c..399d6ce078508 100644 --- a/src/video/riscos/SDL_riscosvideo.c +++ b/src/video/riscos/SDL_riscosvideo.c @@ -55,14 +55,12 @@ static SDL_VideoDevice *RISCOS_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } /* Initialize internal data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!phdata) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c index 2b27bf7f79a49..aceb378a2c462 100644 --- a/src/video/riscos/SDL_riscoswindow.c +++ b/src/video/riscos/SDL_riscoswindow.c @@ -34,7 +34,7 @@ int RISCOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti driverdata = (SDL_WindowData *)SDL_calloc(1, sizeof(*driverdata)); if (!driverdata) { - return SDL_OutOfMemory(); + return -1; } driverdata->window = window; diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 0c37b33421f42..3b751d521760d 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -67,13 +67,11 @@ static void UIKit_DeleteDevice(SDL_VideoDevice *device) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (device) { - data = [SDL_UIKitVideoData new]; - } else { - SDL_free(device); - SDL_OutOfMemory(); - return (0); - } + if (!device) { + return NULL; + ] + + data = [SDL_UIKitVideoData new]; device->driverdata = (SDL_VideoData *)CFBridgingRetain(data); device->system_theme = UIKit_GetSystemTheme(); diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index efaa6209a15b4..8c0fad1eaafb2 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -68,14 +68,12 @@ static SDL_VideoDevice *VITA_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } /* Initialize internal VITA specific data */ phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!phdata) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } @@ -83,7 +81,6 @@ static SDL_VideoDevice *VITA_Create() gldata = (SDL_GLDriverData *)SDL_calloc(1, sizeof(SDL_GLDriverData)); if (!gldata) { - SDL_OutOfMemory(); SDL_free(device); SDL_free(phdata); return NULL; @@ -231,7 +228,7 @@ int VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties /* Allocate window internal data */ wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!wdata) { - return SDL_OutOfMemory(); + return -1; } /* Setup driver data for this window */ diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index f9d2daa2e5557..3a6f56e16218f 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -49,14 +49,12 @@ static SDL_VideoDevice *VIVANTE_Create() /* Initialize SDL_VideoDevice structure */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } /* Initialize internal data */ data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!data) { - SDL_OutOfMemory(); SDL_free(device); return NULL; } @@ -125,7 +123,7 @@ static int VIVANTE_AddVideoDisplays(SDL_VideoDevice *_this) data = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); if (!data) { - return SDL_OutOfMemory(); + return -1; } SDL_zero(mode); @@ -249,7 +247,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert /* Allocate window internal data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); if (!data) { - return SDL_OutOfMemory(); + return -1; } /* Setup driver data for this window */ diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 00da373058061..9d9808e659a19 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -119,7 +119,7 @@ static ssize_t read_pipe(int fd, void **buffer, size_t *total_length) } if (!output_buffer) { - bytes_read = SDL_OutOfMemory(); + bytes_read = -1; } else { SDL_memcpy((Uint8 *)output_buffer + pos, temp, bytes_read); SDL_memset((Uint8 *)output_buffer + (new_buffer_length - sizeof(Uint32)), 0, sizeof(Uint32)); @@ -158,7 +158,7 @@ static int mime_data_list_add(struct wl_list *list, if (buffer) { internal_buffer = SDL_malloc(length); if (!internal_buffer) { - return SDL_OutOfMemory(); + return -1; } SDL_memcpy(internal_buffer, buffer, length); } @@ -168,14 +168,14 @@ static int mime_data_list_add(struct wl_list *list, if (!mime_data) { mime_data = SDL_calloc(1, sizeof(*mime_data)); if (!mime_data) { - status = SDL_OutOfMemory(); + status = -1; } else { WAYLAND_wl_list_insert(list, &(mime_data->link)); mime_type_length = SDL_strlen(mime_type) + 1; mime_data->mime_type = SDL_malloc(mime_type_length); if (!mime_data->mime_type) { - status = SDL_OutOfMemory(); + status = -1; } else { SDL_memcpy(mime_data->mime_type, mime_type, mime_type_length); } @@ -278,9 +278,7 @@ static void *Wayland_clone_data_buffer(const void *buffer, size_t *len) void *clone = NULL; if (*len > 0 && buffer) { clone = SDL_malloc((*len)+sizeof(Uint32)); - if (!clone) { - SDL_OutOfMemory(); - } else { + if (clone) { SDL_memcpy(clone, buffer, *len); SDL_memset((Uint8 *)clone + *len, 0, sizeof(Uint32)); } diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index e8eb58be2dad5..ebdf546d55efb 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -1765,7 +1765,6 @@ SDL_WaylandDataSource *Wayland_data_source_create(SDL_VideoDevice *_this) } else { data_source = SDL_calloc(1, sizeof(*data_source)); if (!data_source) { - SDL_OutOfMemory(); wl_data_source_destroy(id); } else { data_source->source = id; @@ -1799,7 +1798,6 @@ SDL_WaylandPrimarySelectionSource *Wayland_primary_selection_source_create(SDL_V } else { primary_selection_source = SDL_calloc(1, sizeof(*primary_selection_source)); if (!primary_selection_source) { - SDL_OutOfMemory(); zwp_primary_selection_source_v1_destroy(id); } else { primary_selection_source->source = id; @@ -1848,12 +1846,8 @@ static const struct zwp_primary_selection_offer_v1_listener primary_selection_of static void data_device_handle_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id) { - SDL_WaylandDataOffer *data_offer = NULL; - - data_offer = SDL_calloc(1, sizeof(*data_offer)); - if (!data_offer) { - SDL_OutOfMemory(); - } else { + SDL_WaylandDataOffer *data_offer = SDL_calloc(1, sizeof(*data_offer)); + if (data_offer) { data_offer->offer = id; data_offer->data_device = data; WAYLAND_wl_list_init(&(data_offer->mimes)); @@ -2158,12 +2152,8 @@ static const struct wl_data_device_listener data_device_listener = { static void primary_selection_device_handle_offer(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id) { - SDL_WaylandPrimarySelectionOffer *primary_selection_offer = NULL; - - primary_selection_offer = SDL_calloc(1, sizeof(*primary_selection_offer)); - if (!primary_selection_offer) { - SDL_OutOfMemory(); - } else { + SDL_WaylandPrimarySelectionOffer *primary_selection_offer = SDL_calloc(1, sizeof(*primary_selection_offer)); + if (primary_selection_offer) { primary_selection_offer->offer = id; primary_selection_offer->primary_selection_device = data; WAYLAND_wl_list_init(&(primary_selection_offer->mimes)); diff --git a/src/video/wayland/SDL_waylandmessagebox.c b/src/video/wayland/SDL_waylandmessagebox.c index 2fda9eef98d9e..2af96ddec7934 100644 --- a/src/video/wayland/SDL_waylandmessagebox.c +++ b/src/video/wayland/SDL_waylandmessagebox.c @@ -223,7 +223,7 @@ int Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *button output = SDL_malloc(output_len + 1); if (!output) { close(fd_pipe[0]); - return SDL_OutOfMemory(); + return -1; } output[0] = '\0'; diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 7012c2fb1945e..c670cdc18a13a 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -302,7 +302,6 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa SDL_WaylandCursorTheme *new_cursor_themes = SDL_realloc(vdata->cursor_themes, sizeof(SDL_WaylandCursorTheme) * (vdata->num_cursor_themes + 1)); if (!new_cursor_themes) { - SDL_OutOfMemory(); return SDL_FALSE; } vdata->cursor_themes = new_cursor_themes; @@ -504,15 +503,12 @@ static int create_buffer_from_shm(Wayland_CursorData *d, static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) { - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { SDL_VideoDevice *vd = SDL_GetVideoDevice(); SDL_VideoData *wd = vd->driverdata; Wayland_CursorData *data = SDL_calloc(1, sizeof(Wayland_CursorData)); if (!data) { - SDL_OutOfMemory(); SDL_free(cursor); return NULL; } @@ -540,8 +536,6 @@ static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot data->hot_y = hot_y; data->w = surface->w; data->h = surface->h; - } else { - SDL_OutOfMemory(); } return cursor; @@ -550,13 +544,10 @@ static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot static SDL_Cursor *Wayland_CreateSystemCursor(SDL_SystemCursor id) { SDL_VideoData *data = SDL_GetVideoDevice()->driverdata; - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { Wayland_CursorData *cdata = SDL_calloc(1, sizeof(Wayland_CursorData)); if (!cdata) { - SDL_OutOfMemory(); SDL_free(cursor); return NULL; } @@ -569,8 +560,6 @@ static SDL_Cursor *Wayland_CreateSystemCursor(SDL_SystemCursor id) * is output-specific. See wayland_get_system_cursor for the rest! */ cdata->system_cursor = id; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index dfcf717c65a1c..55b403aecc067 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -149,7 +149,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) if (!data) { WAYLAND_wl_display_disconnect(display); SDL_WAYLAND_UnloadSymbols(); - SDL_OutOfMemory(); return NULL; } @@ -163,7 +162,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) SDL_free(data); WAYLAND_wl_display_disconnect(display); SDL_WAYLAND_UnloadSymbols(); - SDL_OutOfMemory(); return NULL; } diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index ad2ce5c41fedc..ce7a383ea46ea 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1988,7 +1988,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert data = SDL_calloc(1, sizeof(*data)); if (!data) { - return SDL_OutOfMemory(); + return -1; } c = _this->driverdata; diff --git a/src/video/windows/SDL_windowsclipboard.c b/src/video/windows/SDL_windowsclipboard.c index 933cce0294d86..8a1e4a4271281 100644 --- a/src/video/windows/SDL_windowsclipboard.c +++ b/src/video/windows/SDL_windowsclipboard.c @@ -125,8 +125,6 @@ static void *WIN_ConvertDIBtoBMP(HANDLE hMem, size_t *size) pbfh->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + bih_size); SDL_memcpy((Uint8 *)bmp + sizeof(BITMAPFILEHEADER), dib, dib_size); *size = bmp_size; - } else { - SDL_OutOfMemory(); } } else { SDL_SetError("Invalid BMP data"); diff --git a/src/video/windows/SDL_windowsframebuffer.c b/src/video/windows/SDL_windowsframebuffer.c index 9be7cc83b4278..d2047577991ca 100644 --- a/src/video/windows/SDL_windowsframebuffer.c +++ b/src/video/windows/SDL_windowsframebuffer.c @@ -47,7 +47,7 @@ int WIN_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); info = (LPBITMAPINFO)SDL_small_alloc(Uint8, size, &isstack); if (!info) { - return SDL_OutOfMemory(); + return -1; } SDL_memset(info, 0, size); diff --git a/src/video/windows/SDL_windowsmessagebox.c b/src/video/windows/SDL_windowsmessagebox.c index 689121c2a1e47..19b48f24c4be2 100644 --- a/src/video/windows/SDL_windowsmessagebox.c +++ b/src/video/windows/SDL_windowsmessagebox.c @@ -345,7 +345,6 @@ static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space) if (size > dialog->size) { void *data = SDL_realloc(dialog->data, size); if (!data) { - SDL_OutOfMemory(); return SDL_FALSE; } dialog->data = data; diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 6bd9515b68562..21e19685b163d 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -72,13 +72,9 @@ static int ToggleRawInput(SDL_bool enabled) static SDL_Cursor *WIN_CreateDefaultCursor() { - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { cursor->driverdata = LoadCursor(NULL, IDC_ARROW); - } else { - SDL_OutOfMemory(); } return cursor; @@ -125,7 +121,6 @@ static HBITMAP CreateMaskBitmap(SDL_Surface *surface) pixels = SDL_small_alloc(Uint8, pitch * surface->h, &isstack); if (!pixels) { - SDL_OutOfMemory(); return NULL; } @@ -190,7 +185,6 @@ static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) cursor->driverdata = hcursor; } else { DestroyCursor(hcursor); - SDL_OutOfMemory(); } return cursor; @@ -285,8 +279,6 @@ static SDL_Cursor *WIN_CreateSystemCursor(SDL_SystemCursor id) hcursor = LoadCursor(NULL, name); cursor->driverdata = hcursor; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 9216b6c7b97e4..5846b26aec0fa 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -125,7 +125,7 @@ int WIN_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) /* Allocate OpenGL memory */ _this->gl_data = (struct SDL_GLDriverData *)SDL_calloc(1, sizeof(struct SDL_GLDriverData)); if (!_this->gl_data) { - return SDL_OutOfMemory(); + return -1; } /* Load function pointers */ diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 6cfbc35d2f29c..9d6330f7a46c4 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -117,7 +117,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) } if (!data) { SDL_free(device); - SDL_OutOfMemory(); return NULL; } device->driverdata = data; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 55e2d700ed09f..43dc5a717bc1b 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -283,7 +283,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd /* Allocate the window data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); if (!data) { - return SDL_OutOfMemory(); + return -1; } data->window = window; data->hwnd = hwnd; @@ -1157,8 +1157,6 @@ void *WIN_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t SDL_SetError("Could not open ICC profile"); } SDL_free(filename_utf8); - } else { - SDL_OutOfMemory(); } return iccProfileData; } diff --git a/src/video/winrt/SDL_winrtmouse.cpp b/src/video/winrt/SDL_winrtmouse.cpp index 30ebfbcb5ce96..b46c889858225 100644 --- a/src/video/winrt/SDL_winrtmouse.cpp +++ b/src/video/winrt/SDL_winrtmouse.cpp @@ -126,8 +126,6 @@ static SDL_Cursor *WINRT_CreateSystemCursor(SDL_SystemCursor id) CoreCursor ^ *theCursor = new CoreCursor ^ (nullptr); *theCursor = ref new CoreCursor(cursorType, 0); cursor->driverdata = (void *)theCursor; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 8f8cde7e5b1e6..8f6572c8926cc 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -109,13 +109,11 @@ static SDL_VideoDevice *WINRT_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return 0; } data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!data) { - SDL_OutOfMemory(); SDL_free(device); return 0; } @@ -321,7 +319,6 @@ static int WINRT_AddDisplaysForOutput(SDL_VideoDevice *_this, IDXGIAdapter1 *dxg dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC)); if (!dxgiModes) { - SDL_OutOfMemory(); goto done; } diff --git a/src/video/x11/SDL_x11clipboard.c b/src/video/x11/SDL_x11clipboard.c index 4bb7d395b26f6..708d01d10589d 100644 --- a/src/video/x11/SDL_x11clipboard.c +++ b/src/video/x11/SDL_x11clipboard.c @@ -101,9 +101,7 @@ static void *CloneDataBuffer(const void *buffer, size_t *len) void *clone = NULL; if (*len > 0 && buffer) { clone = SDL_malloc((*len)+sizeof(Uint32)); - if (!clone) { - SDL_OutOfMemory(); - } else { + if (clone) { SDL_memcpy(clone, buffer, *len); SDL_memset((Uint8 *)clone + *len, 0, sizeof(Uint32)); } diff --git a/src/video/x11/SDL_x11framebuffer.c b/src/video/x11/SDL_x11framebuffer.c index b4a0ae12a5a5b..6714a1febbfc6 100644 --- a/src/video/x11/SDL_x11framebuffer.c +++ b/src/video/x11/SDL_x11framebuffer.c @@ -128,7 +128,7 @@ int X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint *pixels = SDL_malloc((size_t)h * (*pitch)); if (!*pixels) { - return SDL_OutOfMemory(); + return -1; } data->ximage = X11_XCreateImage(display, data->visual, diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index 7eae41deb788c..2367b94496e3f 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -245,7 +245,7 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data) TextLineData *plinedata = (TextLineData *)SDL_malloc(sizeof(TextLineData) * linecount); if (!plinedata) { - return SDL_OutOfMemory(); + return -1; } data->linedata = plinedata; @@ -763,7 +763,7 @@ static int X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int if (origlocale) { origlocale = SDL_strdup(origlocale); if (!origlocale) { - return SDL_OutOfMemory(); + return -1; } (void)setlocale(LC_ALL, ""); } diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 16255c98e092b..15e681766bd7a 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -565,13 +565,13 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); if (!displaydata) { - return SDL_OutOfMemory(); + return -1; } modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); if (!modedata) { SDL_free(displaydata); - return SDL_OutOfMemory(); + return -1; } modedata->xrandr_mode = modeID; @@ -768,13 +768,13 @@ static int X11_InitModes_StdXlib(SDL_VideoDevice *_this) displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); if (!displaydata) { - return SDL_OutOfMemory(); + return -1; } modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); if (!modedata) { SDL_free(displaydata); - return SDL_OutOfMemory(); + return -1; } mode.driverdata = modedata; diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 980aed60a72e4..9c32b12f80ba3 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -69,14 +69,10 @@ static void X11_DestroyEmptyCursor(void) static SDL_Cursor *X11_CreateDefaultCursor(void) { - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { /* None is used to indicate the default cursor */ cursor->driverdata = (void *)(uintptr_t)None; - } else { - SDL_OutOfMemory(); } return cursor; @@ -124,14 +120,12 @@ static Cursor X11_CreatePixmapCursor(SDL_Surface *surface, int hot_x, int hot_y) data_bits = SDL_calloc(1, surface->h * width_bytes); if (!data_bits) { - SDL_OutOfMemory(); return None; } mask_bits = SDL_calloc(1, surface->h * width_bytes); if (!mask_bits) { SDL_free(data_bits); - SDL_OutOfMemory(); return None; } @@ -200,9 +194,7 @@ static Cursor X11_CreatePixmapCursor(SDL_Surface *surface, int hot_x, int hot_y) static SDL_Cursor *X11_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) { - SDL_Cursor *cursor; - - cursor = SDL_calloc(1, sizeof(*cursor)); + SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { Cursor x11_cursor = None; @@ -215,8 +207,6 @@ static SDL_Cursor *X11_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) x11_cursor = X11_CreatePixmapCursor(surface, hot_x, hot_y); } cursor->driverdata = (void *)(uintptr_t)x11_cursor; - } else { - SDL_OutOfMemory(); } return cursor; @@ -302,8 +292,6 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id) x11_cursor = X11_XCreateFontCursor(GetDisplay(), shape); cursor->driverdata = (void *)(uintptr_t)x11_cursor; - } else { - SDL_OutOfMemory(); } return cursor; diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index aad96462d56cb..1d5edd895fe03 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -193,7 +193,7 @@ int X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) sizeof(struct SDL_GLDriverData)); if (!_this->gl_data) { - return SDL_OutOfMemory(); + return -1; } /* Load function pointers */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 32a28ee1ac01b..6bb5f5c638955 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -123,13 +123,11 @@ static SDL_VideoDevice *X11_CreateDevice(void) /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { - SDL_OutOfMemory(); return NULL; } data = (struct SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); if (!data) { SDL_free(device); - SDL_OutOfMemory(); return NULL; } device->driverdata = data; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 5d8000d21579a..8459d861958da 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -312,7 +312,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) /* Allocate the window data */ data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); if (!data) { - return SDL_OutOfMemory(); + return -1; } data->window = window; data->xwindow = w; @@ -337,7 +337,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) SDL_WindowData ** new_windowlist = (SDL_WindowData **)SDL_realloc(windowlist, (numwindows + 1) * sizeof(*windowlist)); if (!new_windowlist) { SDL_free(data); - return SDL_OutOfMemory(); + return -1; } windowlist = new_windowlist; windowlist[numwindows] = data; @@ -543,7 +543,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI /* OK, we got a colormap, now fill it in as best as we can */ colorcells = SDL_malloc(visual->map_entries * sizeof(XColor)); if (!colorcells) { - return SDL_OutOfMemory(); + return -1; } ncolors = visual->map_entries; rmax = 0xffff; @@ -971,7 +971,7 @@ int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i propdata = SDL_malloc(propsize * sizeof(long)); if (!propdata) { - return SDL_OutOfMemory(); + return -1; } X11_XSync(display, False); @@ -1723,7 +1723,6 @@ void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t ret_icc_profile_data = SDL_malloc(real_nitems); if (!ret_icc_profile_data) { - SDL_OutOfMemory(); return NULL; } diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index ef97d33c31c3c..4e8710c83929b 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -237,7 +237,6 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, /* don't know about this device yet, query and cache it. */ devinfo = (SDL_XInput2DeviceInfo *)SDL_calloc(1, sizeof(SDL_XInput2DeviceInfo)); if (!devinfo) { - SDL_OutOfMemory(); return NULL; } diff --git a/test/testffmpeg.c b/test/testffmpeg.c index f28d60c3504c3..eadef4bd1c417 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -461,7 +461,6 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) if (!sws_container) { sws_container = (struct SwsContextContainer *)SDL_calloc(1, sizeof(*sws_container)); if (!sws_container) { - SDL_OutOfMemory(); return SDL_FALSE; } SDL_SetPropertyWithCleanup(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL); @@ -587,8 +586,6 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture) SDL_SetError("Couldn't map hardware frame"); } av_frame_free(&drm_frame); - } else { - SDL_OutOfMemory(); } return result; } diff --git a/test/testshape.c b/test/testshape.c index 459badabee030..e136bb28bc38d 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -144,7 +144,7 @@ static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_Windo g_bitmap_h = shape->h; g_bitmap = (Uint8*) SDL_malloc(shape->w * shape->h); if (!g_bitmap) { - return SDL_OutOfMemory(); + return -1; } SDL_CalculateShapeBitmap(*shape_mode, shape, g_bitmap, 1); diff --git a/test/testutils.c b/test/testutils.c index e9d505297bb89..7b99cc8b40721 100644 --- a/test/testutils.c +++ b/test/testutils.c @@ -36,7 +36,6 @@ GetNearbyFilename(const char *file) if (!path) { SDL_free(base); - SDL_OutOfMemory(); return NULL; } @@ -53,11 +52,7 @@ GetNearbyFilename(const char *file) SDL_free(path); } - path = SDL_strdup(file); - if (!path) { - SDL_OutOfMemory(); - } - return path; + return SDL_strdup(file); } /** @@ -73,16 +68,9 @@ char * GetResourceFilename(const char *user_specified, const char *def) { if (user_specified) { - char *ret = SDL_strdup(user_specified); - - if (!ret) { - SDL_OutOfMemory(); - } - - return ret; - } else { - return GetNearbyFilename(def); + return SDL_strdup(user_specified); } + return GetNearbyFilename(def); } /** diff --git a/test/testvulkan.c b/test/testvulkan.c index 231e644fff710..6cd805cc4a9a5 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -294,7 +294,6 @@ static void findPhysicalDevice(void) } physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); if (!physicalDevices) { - SDL_OutOfMemory(); quit(2); } result = vkEnumeratePhysicalDevices(vulkanContext->instance, &physicalDeviceCount, physicalDevices); @@ -330,7 +329,6 @@ static void findPhysicalDevice(void) if (!queueFamiliesProperties) { SDL_free(physicalDevices); SDL_free(deviceExtensions); - SDL_OutOfMemory(); quit(2); } } @@ -392,7 +390,6 @@ static void findPhysicalDevice(void) if (!deviceExtensions) { SDL_free(physicalDevices); SDL_free(queueFamiliesProperties); - SDL_OutOfMemory(); quit(2); } } @@ -550,7 +547,6 @@ static void getSurfaceFormats(void) vulkanContext->surfaceFormats = (VkSurfaceFormatKHR *)SDL_malloc(sizeof(VkSurfaceFormatKHR) * vulkanContext->surfaceFormatsAllocatedCount); if (!vulkanContext->surfaceFormats) { vulkanContext->surfaceFormatsCount = 0; - SDL_OutOfMemory(); quit(2); } } @@ -583,7 +579,6 @@ static void getSwapchainImages(void) } vulkanContext->swapchainImages = SDL_malloc(sizeof(VkImage) * vulkanContext->swapchainImageCount); if (!vulkanContext->swapchainImages) { - SDL_OutOfMemory(); quit(2); } result = vkGetSwapchainImagesKHR(vulkanContext->device, @@ -763,7 +758,6 @@ static void createFences(void) vulkanContext->fences = SDL_malloc(sizeof(VkFence) * vulkanContext->swapchainImageCount); if (!vulkanContext->fences) { - SDL_OutOfMemory(); quit(2); } for (i = 0; i < vulkanContext->swapchainImageCount; i++) { From f184dea16ce38cad7c8c25cf4f917c6825f20e71 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 30 Nov 2023 00:27:17 -0500 Subject: [PATCH 472/725] uikit: Patched to compile. --- src/video/uikit/SDL_uikitvideo.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 3b751d521760d..d7548baefc6b2 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -69,7 +69,7 @@ static void UIKit_DeleteDevice(SDL_VideoDevice *device) device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { return NULL; - ] + } data = [SDL_UIKitVideoData new]; From 1072b6e86e3937d0df35a2c27f58c99dad0ed7ba Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 30 Nov 2023 10:08:23 -0500 Subject: [PATCH 473/725] docs: fixed typo --- docs/README-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index f19c6159bc870..4c084b04f423e 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -489,7 +489,7 @@ The following functions have been removed: * SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath() * SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType() * SDL_GameControllerNumMappings() - replaced with SDL_GetGamepadMappings() -* SDL_GameControllerMappingForIndex() replaced with SDL_GetGamepadMappings() +* SDL_GameControllerMappingForIndex() - replaced with SDL_GetGamepadMappings() The following symbols have been renamed: * SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID From df0fd55891ee495369a19ab240f6fdc20169ed2f Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 30 Nov 2023 10:10:04 -0500 Subject: [PATCH 474/725] wikiheaders.pl: README files are no longer in Windows endline format. --- build-scripts/wikiheaders.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl index c2bb8edb42719..58abdf4eae6fa 100755 --- a/build-scripts/wikiheaders.pl +++ b/build-scripts/wikiheaders.pl @@ -1090,7 +1090,7 @@ sub usage { my $dent = $_; if ($dent =~ /\A(.*?)\.md\Z/) { # we only bridge Markdown files here. next if $1 eq 'FrontPage'; - filecopy("$wikireadmepath/$dent", "$readmepath/README-$dent", "\r\n"); + filecopy("$wikireadmepath/$dent", "$readmepath/README-$dent", "\n"); } } closedir(DH); From e4582e6edc13649668111aea4e9c04cf840bdfb8 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 30 Nov 2023 15:22:19 +0000 Subject: [PATCH 475/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_gamepad.h | 7 ++- include/SDL3/SDL_keyboard.h | 9 +-- include/SDL3/SDL_render.h | 118 +++++++++++++++++++++++------------- include/SDL3/SDL_touch.h | 18 +++--- include/SDL3/SDL_video.h | 53 ++++++++++------ 5 files changed, 130 insertions(+), 75 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index bc1d9c47b654e..f536ce352ab66 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -317,9 +317,10 @@ extern DECLSPEC int SDLCALL SDL_ReloadGamepadMappings(void); * You must free the returned pointer with SDL_free() when you are done with * it, but you do _not_ free each string in the array. * - * \param count a pointer filled in with the number of mappings returned, can be NULL. - * \returns an array of the mapping strings, NULL-terminated. Must be freed with SDL_free(). - * Returns NULL on error. + * \param count a pointer filled in with the number of mappings returned, can + * be NULL. + * \returns an array of the mapping strings, NULL-terminated. Must be freed + * with SDL_free(). Returns NULL on error. * * \since This function is available since SDL 3.0.0. */ diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index b56f5e85d9bc6..35f6141ba9995 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -300,10 +300,11 @@ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); extern DECLSPEC SDL_bool SDLCALL SDL_TextInputShown(void); /** - * Set the rectangle used to type Unicode text inputs. Native input methods - * will place a window with word suggestions near it, without covering the - * text being inputted. - * + * Set the rectangle used to type Unicode text inputs. + * + * Native input methods will place a window with word suggestions near it, + * without covering the text being inputted. + * * To start text input in a given location, this function is intended to be * called before SDL_StartTextInput, although some platforms support moving * the rectangle even while text input (and a composition) is active. diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index d235e40ae41a4..af5889ba9de92 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -251,9 +251,12 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * These are the supported properties: * * - "window" (pointer) - the window where rendering is displayed - * - "surface" (pointer) - the surface where rendering is displayed, if you want a software renderer without a window - * - "name" (string) - the name of the rendering driver to use, if a specific one is desired - * - "present_vsync" (boolean) - true if you want present synchronized with the refresh rate + * - "surface" (pointer) - the surface where rendering is displayed, if you + * want a software renderer without a window + * - "name" (string) - the name of the rendering driver to use, if a specific + * one is desired + * - "present_vsync" (boolean) - true if you want present synchronized with + * the refresh rate * * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call @@ -447,36 +450,52 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * These are the supported properties: * - * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer - * - "access" (number) - one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC + * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, + * defaults to the best RGBA format for the renderer + * - "access" (number) - one of the enumerated values in SDL_TextureAccess, + * defaults to SDL_TEXTUREACCESS_STATIC * - "width" (number) - the width of the texture in pixels, required * - "height" (number) - the height of the texture in pixels, required * * With the direct3d11 renderer: * - * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. - * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the + * texture, if you want to wrap an existing texture. + * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. * * With the direct3d12 renderer: * - * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the texture, if you want to wrap an existing texture. - * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the + * texture, if you want to wrap an existing texture. + * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * - "opengl.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. - * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - "opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - "opengl.texture" (number) - the GLuint texture associated with the + * texture, if you want to wrap an existing texture. + * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV + * plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengl.texture_u" (number) - the GLuint texture associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "opengl.texture_v" (number) - the GLuint texture associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * - "opengles2.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. - * - "opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - "opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - "opengles2.texture" (number) - the GLuint texture associated with the + * texture, if you want to wrap an existing texture. + * - "opengles2.texture_uv" (number) - the GLuint texture associated with the + * UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengles2.texture_u" (number) - the GLuint texture associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "opengles2.texture_v" (number) - the GLuint texture associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. * * \param renderer the rendering context * \param props the properties to use @@ -501,31 +520,47 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * * With the direct3d11 renderer: * - * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture - * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture - * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture + * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated + * with the texture + * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated + * with the U plane of a YUV texture + * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated + * with the V plane of a YUV texture * * With the direct3d12 renderer: * - * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture - * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture - * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture + * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated + * with the texture + * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated + * with the U plane of a YUV texture + * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated + * with the V plane of a YUV texture * * With the opengl renderer: * - * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture - * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture - * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture - * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) - * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) + * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated + * with the texture + * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated + * with the UV plane of an NV12 texture + * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated + * with the U plane of a YUV texture + * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated + * with the V plane of a YUV texture + * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the + * texture (0.0 - 1.0) + * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the + * texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture - * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture - * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture + * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated + * with the texture + * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture + * associated with the UV plane of an NV12 texture + * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture + * associated with the U plane of a YUV texture + * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture + * associated with the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call @@ -1565,15 +1600,14 @@ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); * * In all other cases, you can ignore this function. * - * This call makes SDL flush any pending rendering work it was queueing up - * to do later in a single batch, and marks any internal cached state as - * invalid, so it'll prepare all its state again later, from scratch. + * This call makes SDL flush any pending rendering work it was queueing up to + * do later in a single batch, and marks any internal cached state as invalid, + * so it'll prepare all its state again later, from scratch. * * This means you do not need to save state in your rendering code to protect - * the SDL renderer. However, there lots of arbitrary pieces of Direct3D - * and OpenGL state that can confuse things; you should use your best - * judgement and be prepared to make changes if specific state needs to be - * protected. + * the SDL renderer. However, there lots of arbitrary pieces of Direct3D and + * OpenGL state that can confuse things; you should use your best judgement + * and be prepared to make changes if specific state needs to be protected. * * \param renderer the rendering context * \returns 0 on success or a negative error code on failure; call diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index 26558c7dbfc56..58a8461c93f85 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -68,16 +68,16 @@ typedef struct SDL_Finger * Get a list of registered touch devices. * * On some platforms SDL first sees the touch device if it was actually used. - * Therefore the returned list might be empty, although devices are - * available. After using all devices at least once the number will be - * correct. + * Therefore the returned list might be empty, although devices are available. + * After using all devices at least once the number will be correct. * * This was fixed for Android in SDL 2.0.1. * - * \param count a pointer filled in with the number of devices returned, can be NULL. - * \returns a 0 terminated array of touch device IDs which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. + * \param count a pointer filled in with the number of devices returned, can + * be NULL. + * \returns a 0 terminated array of touch device IDs which should be freed + * with SDL_free(), or NULL on error; call SDL_GetError() for more + * details. * * \since This function is available since SDL 3.0.0. */ @@ -89,8 +89,8 @@ extern DECLSPEC SDL_TouchID *SDLCALL SDL_GetTouchDevices(int *count); * You do not own the returned string, do not modify or free it. * * \param touchID the touch device instance ID. - * \returns touch device name, or NULL on error; call SDL_GetError() for - * more details. + * \returns touch device name, or NULL on error; call SDL_GetError() for more + * details. * * \since This function is available since SDL 3.0.0. */ diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index c12c1115b32e3..8f9e398bf473b 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -750,7 +750,8 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, i * input events. - 'SDL_WINDOW_POPUP_MENU': The popup window is a popup menu. * The topmost popup menu will implicitly gain the keyboard focus. * - * The following flags are not relevant to popup window creation and will be ignored: + * The following flags are not relevant to popup window creation and will be + * ignored: * * - 'SDL_WINDOW_MINIMIZED' * - 'SDL_WINDOW_MAXIMIZED' @@ -803,45 +804,63 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * - "always-on-top" (boolean) - true if the window should be always on top * - "borderless" (boolean) - true if the window has no window decoration - * - "focusable" (boolean) - true if the window should accept keyboard input (defaults true) - * - "fullscreen" (boolean) - true if the window should start in fullscreen mode at desktop resolution + * - "focusable" (boolean) - true if the window should accept keyboard input + * (defaults true) + * - "fullscreen" (boolean) - true if the window should start in fullscreen + * mode at desktop resolution * - "height" (number) - the height of the window * - "hidden" (boolean) - true if the window should start hidden - * - "high-pixel-density" (boolean) - true if the window uses a high pixel density buffer if possible + * - "high-pixel-density" (boolean) - true if the window uses a high pixel + * density buffer if possible * - "maximized" (boolean) - true if the window should start maximized * - "menu" (boolean) - true if the window is a popup menu * - "metal" (string) - true if the window will be used with Metal rendering * - "minimized" (boolean) - true if the window should start minimized - * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse focus - * - "opengl" (boolean) - true if the window will be used with OpenGL rendering - * - "parent" (pointer) - an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties + * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse + * focus + * - "opengl" (boolean) - true if the window will be used with OpenGL + * rendering + * - "parent" (pointer) - an SDL_Window that will be the parent of this + * window, required for windows with the "toolip" and "menu" properties * - "resizable" (boolean) - true if the window should be resizable * - "title" (string) - the title of the window, in UTF-8 encoding - * - "transparent" (string) - true if the window show transparent in the areas with alpha of 0 + * - "transparent" (string) - true if the window show transparent in the areas + * with alpha of 0 * - "tooltip" (boolean) - true if the window is a tooltip - * - "utility" (boolean) - true if the window is a utility window, not showing in the task bar and window list + * - "utility" (boolean) - true if the window is a utility window, not showing + * in the task bar and window list * - "vulkan" (string) - true if the window will be used with Vulkan rendering * - "width" (number) - the width of the window - * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. - * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. + * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, + * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for + * windows with the "parent" property set. + * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, + * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for + * windows with the "parent" property set. * * On macOS: * - * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. - * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] + * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated + * with the window, if you want to wrap an existing window. + * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with + * the window, defaults to [window contentView] * * On Windows: * - * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want to wrap an existing window. - * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share pixel format with, useful for OpenGL windows + * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want + * to wrap an existing window. + * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share + * pixel format with, useful for OpenGL windows * * On X11: * - * - "x11.window" (number) - the X11 Window associated with the window, if you want to wrap an existing window. + * - "x11.window" (number) - the X11 Window associated with the window, if you + * want to wrap an existing window. * * The SDL_Window is implicitly shown if the "hidden" property is not set. * - * Windows with the "tooltip" and "menu" properties are popup windows and have the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. + * Windows with the "tooltip" and "menu" properties are popup windows and have + * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. * * \param props the properties to use * \returns the window that was created or NULL on failure; call From 744a29b88fd1c0444a459f6b3ae6e51381dcc54b Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Thu, 30 Nov 2023 21:53:00 +0200 Subject: [PATCH 476/725] WGI: Cleanup code a bit (#8647) --- .../windows/SDL_windows_gaming_input.c | 365 ++++++++---------- 1 file changed, 165 insertions(+), 200 deletions(-) diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index f0ee81d22f37a..db946a0f909ad 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef ____FIReference_1_INT32_INTERFACE_DEFINED__ /* MinGW-64 uses __FIReference_1_INT32 instead of Microsoft's __FIReference_1_int */ @@ -43,7 +44,7 @@ struct joystick_hwdata { __x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller; - __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller; + __x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller; __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo *battery; __x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad; __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration; @@ -57,14 +58,22 @@ typedef struct WindowsGamingInputControllerState char *name; SDL_JoystickGUID guid; SDL_JoystickType type; - int naxes; - int nhats; - int nbuttons; } WindowsGamingInputControllerState; +typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(PVOID *pCookie); +typedef HRESULT(WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory); +typedef HRESULT(WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string); +typedef HRESULT(WINAPI *WindowsDeleteString_t)(HSTRING string); +typedef PCWSTR(WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length); + static struct { - __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *statics; + CoIncrementMTAUsage_t CoIncrementMTAUsage; + RoGetActivationFactory_t RoGetActivationFactory; + WindowsCreateStringReference_t WindowsCreateStringReference; + WindowsDeleteString_t WindowsDeleteString; + WindowsGetStringRawBuffer_t WindowsGetStringRawBuffer; + __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *controller_statics; __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics *arcade_stick_statics; __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2 *arcade_stick_statics2; __x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics *flight_stick_statics; @@ -75,31 +84,25 @@ static struct EventRegistrationToken controller_added_token; EventRegistrationToken controller_removed_token; int controller_count; - SDL_bool ro_initialized; WindowsGamingInputControllerState *controllers; } wgi; -static const IID IID_IRawGameControllerStatics = { 0xEB8D0792, 0xE95A, 0x4B19, { 0xAF, 0xC7, 0x0A, 0x59, 0xF8, 0xBF, 0x75, 0x9E } }; -static const IID IID_IRawGameController = { 0x7CAD6D91, 0xA7E1, 0x4F71, { 0x9A, 0x78, 0x33, 0xE9, 0xC5, 0xDF, 0xEA, 0x62 } }; -static const IID IID_IRawGameController2 = { 0x43C0C035, 0xBB73, 0x4756, { 0xA7, 0x87, 0x3E, 0xD6, 0xBE, 0xA6, 0x17, 0xBD } }; -static const IID IID_IEventHandler_RawGameController = { 0x00621c22, 0x42e8, 0x529f, { 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72 } }; -static const IID IID_IGameController = { 0x1BAF6522, 0x5F64, 0x42C5, { 0x82, 0x67, 0xB9, 0xFE, 0x22, 0x15, 0xBF, 0xBD } }; -static const IID IID_IGameControllerBatteryInfo = { 0xDCECC681, 0x3963, 0x4DA6, { 0x95, 0x5D, 0x55, 0x3F, 0x3B, 0x6F, 0x61, 0x61 } }; -static const IID IID_IArcadeStickStatics = { 0x5C37B8C8, 0x37B1, 0x4AD8, { 0x94, 0x58, 0x20, 0x0F, 0x1A, 0x30, 0x01, 0x8E } }; -static const IID IID_IArcadeStickStatics2 = { 0x52B5D744, 0xBB86, 0x445A, { 0xB5, 0x9C, 0x59, 0x6F, 0x0E, 0x2A, 0x49, 0xDF } }; -/*static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };*/ -static const IID IID_IFlightStickStatics = { 0x5514924A, 0xFECC, 0x435E, { 0x83, 0xDC, 0x5C, 0xEC, 0x8A, 0x18, 0xA5, 0x20 } }; -/*static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };*/ -static const IID IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } }; -static const IID IID_IGamepadStatics2 = { 0x42676DC5, 0x0856, 0x47C4, { 0x92, 0x13, 0xB3, 0x95, 0x50, 0x4C, 0x3A, 0x3C } }; -/*static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };*/ -static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F, 0x94, 0x69, 0xF1, 0xE6, 0x51, 0x4C, 0x7D } }; -static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } }; -/*static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };*/ - -typedef HRESULT(WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string); -typedef HRESULT(WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory); - +/* WinRT headers in official Windows SDK contain only declarations, and we have to define these GUIDs ourselves. + * https://stackoverflow.com/a/55605485/1795050 + */ +DEFINE_GUID(IID___FIEventHandler_1_Windows__CGaming__CInput__CRawGameController, 0x00621c22, 0x42e8, 0x529f, 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics, 0x5c37b8c8, 0x37b1, 0x4ad8, 0x94, 0x58, 0x20, 0x0f, 0x1a, 0x30, 0x01, 0x8e); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2, 0x52b5d744, 0xbb86, 0x445a, 0xb5, 0x9c, 0x59, 0x6f, 0x0e, 0x2a, 0x49, 0xdf); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics, 0x5514924a, 0xfecc, 0x435e, 0x83, 0xdc, 0x5c, 0xec, 0x8a, 0x18, 0xa5, 0x20); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGameController, 0x1baf6522, 0x5f64, 0x42c5, 0x82, 0x67, 0xb9, 0xfe, 0x22, 0x15, 0xbf, 0xbd); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo, 0xdcecc681, 0x3963, 0x4da6, 0x95, 0x5d, 0x55, 0x3f, 0x3b, 0x6f, 0x61, 0x61); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics, 0x8bbce529, 0xd49c, 0x39e9, 0x95, 0x60, 0xe4, 0x7d, 0xde, 0x96, 0xb7, 0xc8); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2, 0x42676dc5, 0x0856, 0x47c4, 0x92, 0x13, 0xb3, 0x95, 0x50, 0x4c, 0x3a, 0x3c); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics, 0x3ac12cd5, 0x581b, 0x4936, 0x9f, 0x94, 0x69, 0xf1, 0xe6, 0x51, 0x4c, 0x7d); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2, 0xe666bcaa, 0xedfd, 0x4323, 0xa9, 0xf6, 0x3c, 0x38, 0x40, 0x48, 0xd1, 0xed); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, 0x7cad6d91, 0xa7e1, 0x4f71, 0x9a, 0x78, 0x33, 0xe9, 0xc5, 0xdf, 0xea, 0x62); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, 0x43c0c035, 0xbb73, 0x4756, 0xa7, 0x87, 0x3e, 0xd6, 0xbe, 0xa6, 0x17, 0xbd); +DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, 0xeb8d0792, 0xe95a, 0x4b19, 0xaf, 0xc7, 0x0a, 0x59, 0xf8, 0xbf, 0x75, 0x9e); extern SDL_bool SDL_XINPUT_Enabled(void); extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version); @@ -212,100 +215,73 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) static void WGI_LoadRawGameControllerStatics() { - WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL; - RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL; HRESULT hr; + HSTRING_HEADER class_name_header; + HSTRING class_name; -#ifdef __WINRT__ - WindowsCreateStringReferenceFunc = WindowsCreateStringReference; - RoGetActivationFactoryFunc = RoGetActivationFactory; -#else - { - WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference"); - RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory"); - } -#endif /* __WINRT__ */ - if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) { - PCWSTR pNamespace; - HSTRING_HEADER hNamespaceStringHeader; - HSTRING hNamespaceString; - - pNamespace = L"Windows.Gaming.Input.RawGameController"; - hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString); - if (SUCCEEDED(hr)) { - hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, (void **)&wgi.statics); - if (!SUCCEEDED(hr)) { - SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%lx", hr); - } + hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_RawGameController, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_RawGameController), &class_name_header, &class_name); + if (SUCCEEDED(hr)) { + hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, (void **)&wgi.controller_statics); + if (!SUCCEEDED(hr)) { + WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IRawGameControllerStatics", hr); } } } static void WGI_LoadOtherControllerStatics() { - WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL; - RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL; HRESULT hr; + HSTRING_HEADER class_name_header; + HSTRING class_name; -#ifdef __WINRT__ - WindowsCreateStringReferenceFunc = WindowsCreateStringReference; - RoGetActivationFactoryFunc = RoGetActivationFactory; -#else - { - WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference"); - RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory"); - } -#endif /* __WINRT__ */ - if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) { - PCWSTR pNamespace; - HSTRING_HEADER hNamespaceStringHeader; - HSTRING hNamespaceString; - - pNamespace = L"Windows.Gaming.Input.ArcadeStick"; - hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString); + if (!wgi.arcade_stick_statics) { + hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_ArcadeStick, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_ArcadeStick), &class_name_header, &class_name); if (SUCCEEDED(hr)) { - hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, (void **)&wgi.arcade_stick_statics); + hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics, (void **)&wgi.arcade_stick_statics); if (SUCCEEDED(hr)) { - __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2); + __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2); } else { - SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%lx", hr); + WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IArcadeStickStatics", hr); } } + } - pNamespace = L"Windows.Gaming.Input.FlightStick"; - hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString); + if (!wgi.flight_stick_statics) { + hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_FlightStick, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_FlightStick), &class_name_header, &class_name); if (SUCCEEDED(hr)) { - hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, (void **)&wgi.flight_stick_statics); + hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics, (void **)&wgi.flight_stick_statics); if (!SUCCEEDED(hr)) { - SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%lx", hr); + WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IFlightStickStatics", hr); } } + } - pNamespace = L"Windows.Gaming.Input.Gamepad"; - hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString); + if (!wgi.gamepad_statics) { + hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_Gamepad, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_Gamepad), &class_name_header, &class_name); if (SUCCEEDED(hr)) { - hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, (void **)&wgi.gamepad_statics); + hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics, (void **)&wgi.gamepad_statics); if (SUCCEEDED(hr)) { - __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, (void **)&wgi.gamepad_statics2); + __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2, (void **)&wgi.gamepad_statics2); } else { - SDL_SetError("Couldn't find IGamepadStatics: 0x%lx", hr); + WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IGamepadStatics", hr); } } + } - pNamespace = L"Windows.Gaming.Input.RacingWheel"; - hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString); + if (!wgi.racing_wheel_statics) { + hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_RacingWheel, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_RacingWheel), &class_name_header, &class_name); if (SUCCEEDED(hr)) { - hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, (void **)&wgi.racing_wheel_statics); + hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics, (void **)&wgi.racing_wheel_statics); if (SUCCEEDED(hr)) { - __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2); + __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2); } else { - SDL_SetError("Couldn't find IRacingWheelStatics: 0x%lx", hr); + WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IRacingWheelStatics", hr); } } } } -static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller) +static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller) { __x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL; __x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL; @@ -317,22 +293,22 @@ static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CI */ WGI_LoadOtherControllerStatics(); - if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) { + if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, game_controller, &gamepad)) && gamepad) { __x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad); return SDL_JOYSTICK_TYPE_GAMEPAD; } - if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) { + if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, game_controller, &arcade_stick)) && arcade_stick) { __x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick); return SDL_JOYSTICK_TYPE_ARCADE_STICK; } - if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) { + if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, game_controller, &flight_stick)) && flight_stick) { __x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick); return SDL_JOYSTICK_TYPE_FLIGHT_STICK; } - if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) { + if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, game_controller, &racing_wheel)) && racing_wheel) { __x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel); return SDL_JOYSTICK_TYPE_WHEEL; } @@ -353,7 +329,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInter } *ppvObject = NULL; - if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) { + if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID___FIEventHandler_1_Windows__CGaming__CInput__CRawGameController)) { *ppvObject = This; __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_AddRef(This); return S_OK; @@ -393,7 +369,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde return S_OK; } - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller); if (SUCCEEDED(hr)) { char *name = NULL; SDL_JoystickGUID guid = { 0 }; @@ -403,38 +379,22 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde Uint16 version = 0; SDL_JoystickType type = SDL_JOYSTICK_TYPE_UNKNOWN; __x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL; - __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL; + __x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller = NULL; SDL_bool ignore_joystick = SDL_FALSE; __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product); - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2); if (SUCCEEDED(hr)) { - typedef PCWSTR(WINAPI * WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 * length); - typedef HRESULT(WINAPI * WindowsDeleteString_t)(HSTRING string); - - WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = NULL; - WindowsDeleteString_t WindowsDeleteStringFunc = NULL; -#ifdef __WINRT__ - WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer; - WindowsDeleteStringFunc = WindowsDeleteString; -#else - { - WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer"); - WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("WindowsDeleteString"); - } -#endif /* __WINRT__ */ - if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) { - HSTRING hString; - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString); - if (SUCCEEDED(hr)) { - PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL); - if (string) { - name = WIN_StringToUTF8W(string); - } - WindowsDeleteStringFunc(hString); + HSTRING hString; + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString); + if (SUCCEEDED(hr)) { + PCWSTR string = wgi.WindowsGetStringRawBuffer(hString, NULL); + if (string) { + name = WIN_StringToUTF8W(string); } + wgi.WindowsDeleteString(hString); } __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2); } @@ -463,18 +423,18 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde } if (!ignore_joystick) { - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&game_controller); if (SUCCEEDED(hr)) { boolean wireless; - type = GetGameControllerType(gamecontroller); + type = GetGameControllerType(game_controller); - hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(gamecontroller, &wireless); + hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(game_controller, &wireless); if (SUCCEEDED(hr) && wireless) { bus = SDL_HARDWARE_BUS_BLUETOOTH; } - __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller); + __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(game_controller); } guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type); @@ -498,10 +458,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde state->guid = guid; state->type = type; - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons); - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes); - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(controller, &state->nhats); - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller); ++wgi.controller_count; @@ -536,7 +492,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemo return S_OK; } - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller); if (SUCCEEDED(hr)) { int i; @@ -609,7 +565,22 @@ static int WGI_JoystickInit(void) if (FAILED(WIN_RoInitialize())) { return SDL_SetError("RoInitialize() failed"); } - wgi.ro_initialized = SDL_TRUE; + +#ifdef __WINRT__ + wgi.CoIncrementMTAUsage = CoIncrementMTAUsage; + wgi.RoGetActivationFactory = RoGetActivationFactory; + wgi.WindowsCreateStringReference = WindowsCreateStringReference; + wgi.WindowsDeleteString = WindowsDeleteString; + wgi.WindowsGetStringRawBuffer = WindowsGetStringRawBuffer; +#else +#define RESOLVE(x) wgi.x = (x##_t)WIN_LoadComBaseFunction(#x); if (!wgi.x) return WIN_SetError("GetProcAddress failed for " #x); + RESOLVE(CoIncrementMTAUsage); + RESOLVE(RoGetActivationFactory); + RESOLVE(WindowsCreateStringReference); + RESOLVE(WindowsDeleteString); + RESOLVE(WindowsGetStringRawBuffer); +#undef RESOLVE +#endif /* __WINRT__ */ #ifndef __WINRT__ { @@ -620,15 +591,9 @@ static int WGI_JoystickInit(void) */ static PVOID cookie = NULL; if (!cookie) { - typedef HRESULT(WINAPI * CoIncrementMTAUsage_t)(PVOID * pCookie); - CoIncrementMTAUsage_t CoIncrementMTAUsageFunc = (CoIncrementMTAUsage_t)WIN_LoadComBaseFunction("CoIncrementMTAUsage"); - if (CoIncrementMTAUsageFunc) { - if (FAILED(CoIncrementMTAUsageFunc(&cookie))) { - return SDL_SetError("CoIncrementMTAUsage() failed"); - } - } else { - /* CoIncrementMTAUsage() is present since Win8, so we should never make it here. */ - return SDL_SetError("CoIncrementMTAUsage() not found"); + hr = wgi.CoIncrementMTAUsage(&cookie); + if (FAILED(hr)) { + return WIN_SetErrorFromHRESULT("CoIncrementMTAUsage() failed", hr); } } } @@ -636,20 +601,20 @@ static int WGI_JoystickInit(void) WGI_LoadRawGameControllerStatics(); - if (wgi.statics) { + if (wgi.controller_statics) { __FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers; - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.statics, &controller_added.iface, &wgi.controller_added_token); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.controller_statics, &controller_added.iface, &wgi.controller_added_token); if (!SUCCEEDED(hr)) { - SDL_SetError("add_RawGameControllerAdded() failed: 0x%lx\n", hr); + WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IRawGameControllerStatics.add_RawGameControllerAdded failed", hr); } - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.statics, &controller_removed.iface, &wgi.controller_removed_token); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.controller_statics, &controller_removed.iface, &wgi.controller_removed_token); if (!SUCCEEDED(hr)) { - SDL_SetError("add_RawGameControllerRemoved() failed: 0x%lx\n", hr); + WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IRawGameControllerStatics.add_RawGameControllerRemoved failed", hr); } - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_get_RawGameControllers(wgi.statics, &controllers); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_get_RawGameControllers(wgi.controller_statics, &controllers); if (SUCCEEDED(hr)) { unsigned i, count = 0; @@ -660,7 +625,7 @@ static int WGI_JoystickInit(void) hr = __FIVectorView_1_Windows__CGaming__CInput__CRawGameController_GetAt(controllers, i, &controller); if (SUCCEEDED(hr) && controller) { - IEventHandler_CRawGameControllerVtbl_InvokeAdded(&controller_added.iface, NULL, controller); + __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_Invoke(&controller_added.iface, NULL, controller); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller); } } @@ -725,60 +690,23 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index) hwdata->controller = state->controller; __x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(hwdata->controller); - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameController, (void **)&hwdata->gamecontroller); - __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameControllerBatteryInfo, (void **)&hwdata->battery); + __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&hwdata->game_controller); + __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo, (void **)&hwdata->battery); if (wgi.gamepad_statics2) { - __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->gamecontroller, &hwdata->gamepad); + __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->game_controller, &hwdata->gamepad); } - if (hwdata->gamecontroller) { - __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->gamecontroller, &wireless); + if (hwdata->game_controller) { + __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->game_controller, &wireless); } /* Initialize the joystick capabilities */ - joystick->nbuttons = state->nbuttons; - joystick->naxes = state->naxes; - joystick->nhats = state->nhats; joystick->epowerlevel = wireless ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED; + __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(hwdata->controller, &joystick->nbuttons); + __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(hwdata->controller, &joystick->naxes); + __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(hwdata->controller, &joystick->nhats); - if (wireless && hwdata->battery) { - HRESULT hr; - __x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report; - - hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report); - if (SUCCEEDED(hr) && report) { - int full_capacity = 0, curr_capacity = 0; - __FIReference_1_int *full_capacityP, *curr_capacityP; - - hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP); - if (SUCCEEDED(hr)) { - __FIReference_1_int_get_Value(full_capacityP, &full_capacity); - __FIReference_1_int_Release(full_capacityP); - } - - hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP); - if (SUCCEEDED(hr)) { - __FIReference_1_int_get_Value(curr_capacityP, &curr_capacity); - __FIReference_1_int_Release(curr_capacityP); - } - - if (full_capacity > 0) { - float ratio = (float)curr_capacity / full_capacity; - - if (ratio <= 0.05f) { - joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY; - } else if (ratio <= 0.20f) { - joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW; - } else if (ratio <= 0.70f) { - joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM; - } else { - joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL; - } - } - __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report); - } - } return 0; } @@ -789,13 +717,14 @@ static int WGI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl if (hwdata->gamepad) { HRESULT hr; + /* Note: reusing partially filled vibration data struct */ hwdata->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16; hwdata->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16; hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, hwdata->vibration); if (SUCCEEDED(hr)) { return 0; } else { - return SDL_SetError("Setting vibration failed: 0x%lx\n", hr); + return WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IGamepad.put_Vibration failed", hr); } } else { return SDL_Unsupported(); @@ -809,13 +738,14 @@ static int WGI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble if (hwdata->gamepad) { HRESULT hr; + /* Note: reusing partially filled vibration data struct */ hwdata->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16; hwdata->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16; hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, hwdata->vibration); if (SUCCEEDED(hr)) { return 0; } else { - return SDL_SetError("Setting vibration failed: 0x%lx\n", hr); + return WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IGamepad.put_Vibration failed", hr); } } else { return SDL_Unsupported(); @@ -932,6 +862,43 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick) SDL_stack_free(buttons); SDL_stack_free(hats); SDL_stack_free(axes); + + if (joystick->epowerlevel != SDL_JOYSTICK_POWER_WIRED && hwdata->battery) { + __x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report = NULL; + + hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report); + if (SUCCEEDED(hr) && report) { + int full_capacity = 0, curr_capacity = 0; + __FIReference_1_int *full_capacityP, *curr_capacityP; + + hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP); + if (SUCCEEDED(hr)) { + __FIReference_1_int_get_Value(full_capacityP, &full_capacity); + __FIReference_1_int_Release(full_capacityP); + } + + hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP); + if (SUCCEEDED(hr)) { + __FIReference_1_int_get_Value(curr_capacityP, &curr_capacity); + __FIReference_1_int_Release(curr_capacityP); + } + + if (full_capacity > 0) { + float ratio = (float)curr_capacity / full_capacity; + + if (ratio <= 0.05f) { + joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY; + } else if (ratio <= 0.20f) { + joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW; + } else if (ratio <= 0.70f) { + joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM; + } else { + joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL; + } + } + __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report); + } + } } static void WGI_JoystickClose(SDL_Joystick *joystick) @@ -942,8 +909,8 @@ static void WGI_JoystickClose(SDL_Joystick *joystick) if (hwdata->controller) { __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(hwdata->controller); } - if (hwdata->gamecontroller) { - __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->gamecontroller); + if (hwdata->game_controller) { + __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->game_controller); } if (hwdata->battery) { __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_Release(hwdata->battery); @@ -958,9 +925,9 @@ static void WGI_JoystickClose(SDL_Joystick *joystick) static void WGI_JoystickQuit(void) { - if (wgi.statics) { + if (wgi.controller_statics) { while (wgi.controller_count > 0) { - IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed.iface, NULL, wgi.controllers[wgi.controller_count - 1].controller); + __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_Invoke(&controller_removed.iface, NULL, wgi.controllers[wgi.controller_count - 1].controller); } if (wgi.controllers) { SDL_free(wgi.controllers); @@ -988,14 +955,12 @@ static void WGI_JoystickQuit(void) __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_Release(wgi.racing_wheel_statics2); } - __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.statics, wgi.controller_added_token); - __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.statics, wgi.controller_removed_token); - __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.statics); + __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.controller_statics, wgi.controller_added_token); + __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.controller_statics, wgi.controller_removed_token); + __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.controller_statics); } - if (wgi.ro_initialized) { - WIN_RoUninitialize(); - } + WIN_RoUninitialize(); SDL_zero(wgi); } From 675423f09645cc3f54a5811b256e08806b56c0a6 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Fri, 1 Dec 2023 06:39:09 +0000 Subject: [PATCH 477/725] Sync SDL3 wiki -> header --- docs/README-main-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index 40908bfdde9cb..a9d8fca549732 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -51,7 +51,7 @@ program. If for some reason you need to include SDL_main.h in a file but also _don't_ want it to generate this platform-specific code, you should define a special -macro before includin the header: +macro before including the header: ```c From 579681a3727b46fbac8b5207a6b8d80a8beeb6f5 Mon Sep 17 00:00:00 2001 From: foobit Date: Thu, 30 Nov 2023 18:44:20 -0500 Subject: [PATCH 478/725] fixed SDL_SCANCODE_LEFT array position in scancodes_windows.h --- src/events/scancodes_windows.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/scancodes_windows.h b/src/events/scancodes_windows.h index 697d2f28ff256..a41d69b2190c3 100644 --- a/src/events/scancodes_windows.h +++ b/src/events/scancodes_windows.h @@ -228,8 +228,8 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe047*/ SDL_SCANCODE_HOME, /*0xe048*/ SDL_SCANCODE_UP, /*0xe049*/ SDL_SCANCODE_PAGEUP, - /*0xe04a*/ SDL_SCANCODE_LEFT, - /*0xe04b*/ SDL_SCANCODE_UNKNOWN, + /*0xe04a*/ SDL_SCANCODE_UNKNOWN, + /*0xe04b*/ SDL_SCANCODE_LEFT, /*0xe04c*/ SDL_SCANCODE_UNKNOWN, /*0xe04d*/ SDL_SCANCODE_RIGHT, /*0xe04e*/ SDL_SCANCODE_UNKNOWN, From 66e532fa61f7915a4f356c24789b5b79b8c9dfad Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 1 Dec 2023 09:05:04 -0800 Subject: [PATCH 479/725] Handle out of memory errors without any allocation --- src/SDL_error.c | 26 ++++++++++++++------------ src/SDL_error_c.h | 9 ++++++++- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/SDL_error.c b/src/SDL_error.c index 25fe696c79fa8..b0db7aa10c084 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -32,7 +32,7 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) int result; SDL_error *error = SDL_GetErrBuf(); - error->error = 1; /* mark error as valid */ + error->error = SDL_ErrorCodeGeneric; va_start(ap, fmt); result = SDL_vsnprintf(error->str, error->len, fmt, ap); @@ -63,12 +63,20 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) const char *SDL_GetError(void) { const SDL_error *error = SDL_GetErrBuf(); - return error->error ? error->str : ""; + + switch (error->error) { + case SDL_ErrorCodeGeneric: + return error->str; + case SDL_ErrorCodeOutOfMemory: + return "Out of memory"; + default: + return ""; + } } void SDL_ClearError(void) { - SDL_GetErrBuf()->error = 0; + SDL_GetErrBuf()->error = SDL_ErrorCodeNone; } /* Very common errors go here */ @@ -76,7 +84,8 @@ int SDL_Error(SDL_errorcode code) { switch (code) { case SDL_ENOMEM: - return SDL_SetError("Out of memory"); + SDL_GetErrBuf()->error = SDL_ErrorCodeOutOfMemory; + return -1; case SDL_EFREAD: return SDL_SetError("Error reading from datastream"); case SDL_EFWRITE: @@ -92,13 +101,6 @@ int SDL_Error(SDL_errorcode code) char *SDL_GetErrorMsg(char *errstr, int maxlen) { - const SDL_error *error = SDL_GetErrBuf(); - - if (error->error) { - SDL_strlcpy(errstr, error->str, maxlen); - } else { - *errstr = '\0'; - } - + SDL_strlcpy(errstr, SDL_GetError(), maxlen); return errstr; } diff --git a/src/SDL_error_c.h b/src/SDL_error_c.h index 4c63ee00186bb..291f04b06872d 100644 --- a/src/SDL_error_c.h +++ b/src/SDL_error_c.h @@ -27,9 +27,16 @@ #ifndef SDL_error_c_h_ #define SDL_error_c_h_ +typedef enum +{ + SDL_ErrorCodeNone, + SDL_ErrorCodeGeneric, + SDL_ErrorCodeOutOfMemory, +} SDL_ErrorCode; + typedef struct SDL_error { - int error; /* This is a numeric value corresponding to the current error */ + SDL_ErrorCode error; char *str; size_t len; SDL_realloc_func realloc_func; From ecd56bb8f00782dc521712e70ad3340629f18694 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 1 Dec 2023 09:08:23 -0800 Subject: [PATCH 480/725] Removed SDL_GetErrorMsg(), trivially implemented in application code --- docs/README-migration.md | 5 +++++ include/SDL3/SDL_error.h | 17 ----------------- src/SDL_error.c | 6 ------ src/dynapi/SDL_dynapi.sym | 1 - src/dynapi/SDL_dynapi_overrides.h | 1 - src/dynapi/SDL_dynapi_procs.h | 1 - 6 files changed, 5 insertions(+), 26 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 4c084b04f423e..e6f434701d9f2 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -290,6 +290,11 @@ SDL_HasRDTSC() has been removed; there is no replacement. Don't use the RDTSC op SDL_SIMDAlloc(), SDL_SIMDRealloc(), and SDL_SIMDFree() have been removed. You can use SDL_aligned_alloc() and SDL_aligned_free() with SDL_SIMDGetAlignment() to get the same functionality. +## SDL_error.h + +The following functions have been removed: +* SDL_GetErrorMsg() - Can be implemented as `SDL_strlcpy(errstr, SDL_GetError(), maxlen);` + ## SDL_events.h The timestamp member of the SDL_Event structure now represents nanoseconds, and is populated with SDL_GetTicksNS() diff --git a/include/SDL3/SDL_error.h b/include/SDL3/SDL_error.h index 9440f42774328..26b7d33d7f966 100644 --- a/include/SDL3/SDL_error.h +++ b/include/SDL3/SDL_error.h @@ -102,23 +102,6 @@ extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fm */ extern DECLSPEC const char *SDLCALL SDL_GetError(void); -/** - * Get the last error message that was set for the current thread. - * - * This allows the caller to copy the error string into a provided buffer, but - * otherwise operates exactly the same as SDL_GetError(). - * - * \param errstr A buffer to fill with the last error message that was set for - * the current thread - * \param maxlen The size of the buffer pointed to by the errstr parameter - * \returns the pointer passed in as the `errstr` parameter. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetError - */ -extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen); - /** * Clear any previous error message for this thread. * diff --git a/src/SDL_error.c b/src/SDL_error.c index b0db7aa10c084..e7773ca492300 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -98,9 +98,3 @@ int SDL_Error(SDL_errorcode code) return SDL_SetError("Unknown SDL error"); } } - -char *SDL_GetErrorMsg(char *errstr, int maxlen) -{ - SDL_strlcpy(errstr, SDL_GetError(), maxlen); - return errstr; -} diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8d1bd4811ae38..e007e8d4a3a4b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -164,7 +164,6 @@ SDL3_0.0.0 { SDL_GetDisplayUsableBounds; SDL_GetDisplays; SDL_GetError; - SDL_GetErrorMsg; SDL_GetEventFilter; SDL_GetFullscreenDisplayModes; SDL_GetGamepadAppleSFSymbolsNameForAxis; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 3be07fa255298..9c9696d445ad2 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -188,7 +188,6 @@ #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL #define SDL_GetDisplays SDL_GetDisplays_REAL #define SDL_GetError SDL_GetError_REAL -#define SDL_GetErrorMsg SDL_GetErrorMsg_REAL #define SDL_GetEventFilter SDL_GetEventFilter_REAL #define SDL_GetFullscreenDisplayModes SDL_GetFullscreenDisplayModes_REAL #define SDL_GetGamepadAppleSFSymbolsNameForAxis SDL_GetGamepadAppleSFSymbolsNameForAxis_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 0ae19f03064ca..e055c8d06fe82 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -247,7 +247,6 @@ SDL_DYNAPI_PROC(const char*,SDL_GetDisplayName,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return) -SDL_DYNAPI_PROC(char*,SDL_GetErrorMsg,(char *a, int b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) SDL_DYNAPI_PROC(const SDL_DisplayMode**,SDL_GetFullscreenDisplayModes,(SDL_DisplayID a, int *b),(a,b),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadAppleSFSymbolsNameForAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return) From 058213366bccf7f62d4c4c6061477d7a69ea336d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 1 Dec 2023 10:51:54 -0800 Subject: [PATCH 481/725] Make sure we use alpha of 0 when clearing a transparent window with no content --- src/render/metal/SDL_render_metal.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 4686fbd888ab1..4cb7577fb2cc4 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1525,9 +1525,10 @@ static int METAL_RenderPresent(SDL_Renderer *renderer) // If we don't have a command buffer, we can't present, so activate to get one. if (data.mtlcmdencoder == nil) { - // We haven't even gotten a backbuffer yet? Clear it to black. Otherwise, load the existing data. + // We haven't even gotten a backbuffer yet? Load and clear it. Otherwise, load the existing data. if (data.mtlbackbuffer == nil) { - MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f); + float alpha = (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_TRANSPARENT) ? 0.0f : 1.0f; + MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, alpha); ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, nil); } else { ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil); From 7c71e72193348f19570fc77852aff2ddf510a84b Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 1 Dec 2023 15:58:13 +0100 Subject: [PATCH 482/725] SDL_render: Call InvalidateCachedState to initialise some of driverdata values (eg '*_dirty' to 1). At the earliest place, immediatly after driverdata is set. (Doing it in SDL_render.c, after creation, would be too late, because there're renderers that already use/change those values in the CreateRender() function). --- src/render/direct3d/SDL_render_d3d.c | 14 ++++---------- src/render/direct3d11/SDL_render_d3d11.c | 1 + src/render/direct3d12/SDL_render_d3d12.c | 2 ++ src/render/metal/SDL_render_metal.m | 1 + src/render/opengl/SDL_render_gl.c | 3 +-- src/render/opengles2/SDL_render_gles2.c | 2 +- src/render/ps2/SDL_render_ps2.c | 1 + src/render/psp/SDL_render_psp.c | 1 + src/render/software/SDL_render_sw.c | 1 + src/render/vitagxm/SDL_render_vita_gxm.c | 1 + 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 744055bcb3d58..2ab49bd29f188 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1511,12 +1511,9 @@ static int D3D_Reset(SDL_Renderer *renderer) IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget); D3D_InitRenderState(data); D3D_SetRenderTargetInternal(renderer, renderer->target); - data->drawstate.viewport_dirty = SDL_TRUE; - data->drawstate.cliprect_dirty = SDL_TRUE; - data->drawstate.cliprect_enabled_dirty = SDL_TRUE; - data->drawstate.texture = NULL; - data->drawstate.shader = NULL; - data->drawstate.blend = SDL_BLENDMODE_INVALID; + + D3D_InvalidateCachedState(renderer); + IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX *)&d3dmatrix); /* Let the application know that render targets were reset */ @@ -1605,6 +1602,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer->info = D3D_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + D3D_InvalidateCachedState(renderer); SDL_GetWindowSizeInPixels(window, &w, &h); if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) { @@ -1710,10 +1708,6 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } } #endif - data->drawstate.viewport_dirty = SDL_TRUE; - data->drawstate.cliprect_dirty = SDL_TRUE; - data->drawstate.cliprect_enabled_dirty = SDL_TRUE; - data->drawstate.blend = SDL_BLENDMODE_INVALID; SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d9.device", data->device); diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 9dfeb928b7eb7..1c14a515079db 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -2472,6 +2472,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->info = D3D11_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + D3D11_InvalidateCachedState(renderer); #if SDL_WINAPI_FAMILY_PHONE /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1. diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 91fdffbdec47d..d1cafa5bf450d 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -480,6 +480,7 @@ static void D3D12_ResetCommandList(D3D12_RenderData *data) data->cliprectDirty = SDL_TRUE; data->viewportDirty = SDL_TRUE; data->currentRenderTargetView.ptr = 0; + /* FIXME should we also clear currentSampler.ptr and currentRenderTargetView.ptr ? (and use D3D12_InvalidateCachedState() instead) */ /* Release any upload buffers that were inflight */ for (i = 0; i < data->currentUploadBuffer; ++i) { @@ -3023,6 +3024,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->info = D3D12_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + D3D12_InvalidateCachedState(renderer); if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 4cb7577fb2cc4..3d3e0586e38f9 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1796,6 +1796,7 @@ in case we want to use it later (recreating the renderer) } renderer->driverdata = (void *)CFBridgingRetain(data); + METAL_InvalidateCachedState(renderer); renderer->window = window; data.mtlview = view; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 96ca76bd62a00..43c69602b66b8 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1832,6 +1832,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea renderer->info = GL_RenderDriver.info; renderer->info.flags = 0; /* will set some flags below. */ renderer->driverdata = data; + GL_InvalidateCachedState(renderer); renderer->window = window; data->context = SDL_GL_CreateContext(window); @@ -2008,8 +2009,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea /* This ended up causing video discrepancies between OpenGL and Direct3D */ /* data->glEnable(GL_LINE_SMOOTH); */ - data->drawstate.blend = SDL_BLENDMODE_INVALID; - data->drawstate.shader = SHADER_INVALID; data->drawstate.color = 0xFFFFFFFF; data->drawstate.clear_color = 0xFFFFFFFF; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 1ea3afde8308c..1173822efad7d 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -2119,6 +2119,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c renderer->info = GLES2_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + GLES2_InvalidateCachedState(renderer); renderer->window = window; /* Create an OpenGL ES 2.0 context */ @@ -2255,7 +2256,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - data->drawstate.blend = SDL_BLENDMODE_INVALID; data->drawstate.clear_color = 0xFFFFFFFF; data->drawstate.projection[3][0] = -1.0f; data->drawstate.projection[3][3] = 1.0f; diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index b715a8586e785..dca67c364ee0d 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -669,6 +669,7 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre renderer->info = PS2_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + PS2_InvalidateCachedState(renderer); renderer->window = window; if (data->vsync) { diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index df70837204d64..6769238aee705 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -1338,6 +1338,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer->info = PSP_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + PSP_InvalidateCachedState(renderer); renderer->window = window; data->initialized = SDL_TRUE; diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index efa30f312c3de..1ba010a2e3363 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -1146,6 +1146,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) renderer->DestroyRenderer = SW_DestroyRenderer; renderer->info = SW_RenderDriver.info; renderer->driverdata = data; + SW_InvalidateCachedState(renderer); SW_SelectBestFormats(renderer, surface->format->format); diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index ade52281e92a8..6b3831b658281 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -255,6 +255,7 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat renderer->info = VITA_GXM_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; + VITA_GXM_InvalidateCachedState(renderer); renderer->window = window; data->initialized = SDL_TRUE; From ac0751a652741d6b54e48ff8e6955cf6fd7f7058 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 3 Dec 2023 14:42:28 -0800 Subject: [PATCH 483/725] Added SDL_strnstr() --- CMakeLists.txt | 2 +- include/SDL3/SDL_stdinc.h | 2 + include/build_config/SDL_build_config.h.cmake | 1 + src/dynapi/SDL_dynapi.sym | 2 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/stdlib/SDL_string.c | 42 ++++++++--- test/testautomation_stdlib.c | 75 ++++++++++++++++++- 8 files changed, 113 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fab3c11e20640..8af562830bdb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1065,7 +1065,7 @@ if(SDL_LIBC) realloc rindex round roundf scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr strcmp strlcat strlcpy strlen strncmp strnlen - strrchr strstr strtod strtok_r strtol strtoll strtoul strtoull + strrchr strstr strnstr strtod strtok_r strtol strtoll strtoul strtoull tan tanf trunc truncf unsetenv vsnprintf vsscanf diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 50d81825c4ef9..a257513f3aea4 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -546,6 +546,7 @@ extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, c extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr); extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle); +extern DECLSPEC wchar_t *SDLCALL SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen); extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2); extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); @@ -566,6 +567,7 @@ extern DECLSPEC char *SDLCALL SDL_strlwr(char *str); extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c); extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c); extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle); +extern DECLSPEC char *SDLCALL SDL_strnstr(const char *haystack, const char *needle, size_t maxlen); extern DECLSPEC char *SDLCALL SDL_strcasestr(const char *haystack, const char *needle); extern DECLSPEC char *SDLCALL SDL_strtok_r(char *s1, const char *s2, char **saveptr); extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str); diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 4c5f9b31c0dbc..b725a98e14806 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -116,6 +116,7 @@ #cmakedefine HAVE_STRCHR 1 #cmakedefine HAVE_STRRCHR 1 #cmakedefine HAVE_STRSTR 1 +#cmakedefine HAVE_STRNSTR 1 #cmakedefine HAVE_STRTOK_R 1 #cmakedefine HAVE_ITOA 1 #cmakedefine HAVE__LTOA 1 diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index e007e8d4a3a4b..61bf3069149ea 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -960,6 +960,8 @@ SDL3_0.0.0 { SDL_GetGamepadMappings; SDL_GetTouchDevices; SDL_GetTouchDeviceName; + SDL_strnstr; + SDL_wcsnstr; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 9c9696d445ad2..bc03b31787fd2 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -985,3 +985,5 @@ #define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL #define SDL_GetTouchDevices SDL_GetTouchDevices_REAL #define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL +#define SDL_strnstr SDL_strnstr_REAL +#define SDL_wcsnstr SDL_wcsnstr_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index e055c8d06fe82..02d9aebae5be0 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1010,3 +1010,5 @@ SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) +SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) +SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index cdc51ef8db509..8570d4fa1ac54 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -468,19 +468,28 @@ wchar_t *SDL_wcsdup(const wchar_t *string) return newstr; } -wchar_t *SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle) +wchar_t *SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen) { -#ifdef HAVE_WCSSTR - return SDL_const_cast(wchar_t *, wcsstr(haystack, needle)); -#else size_t length = SDL_wcslen(needle); - while (*haystack) { - if (SDL_wcsncmp(haystack, needle, length) == 0) { + if (length == 0) { + return (wchar_t *)haystack; + } + while (maxlen >= length && *haystack) { + if (maxlen >= length && SDL_wcsncmp(haystack, needle, length) == 0) { return (wchar_t *)haystack; } ++haystack; + --maxlen; } return NULL; +} + +wchar_t *SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle) +{ +#ifdef HAVE_WCSSTR + return SDL_const_cast(wchar_t *, wcsstr(haystack, needle)); +#else + return SDL_wcsnstr(haystack, needle, SDL_wcslen(haystack)); #endif /* HAVE_WCSSTR */ } @@ -821,22 +830,35 @@ char *SDL_strrchr(const char *string, int c) #endif /* HAVE_STRRCHR */ } -char *SDL_strstr(const char *haystack, const char *needle) +char *SDL_strnstr(const char *haystack, const char *needle, size_t maxlen) { -#ifdef HAVE_STRSTR - return SDL_const_cast(char *, strstr(haystack, needle)); +#ifdef HAVE_STRNSTR + return SDL_const_cast(char *, strnstr(haystack, needle, maxlen)); #else size_t length = SDL_strlen(needle); - while (*haystack) { + if (length == 0) { + return (char *)haystack; + } + while (maxlen >= length && *haystack) { if (SDL_strncmp(haystack, needle, length) == 0) { return (char *)haystack; } ++haystack; + --maxlen; } return NULL; #endif /* HAVE_STRSTR */ } +char *SDL_strstr(const char *haystack, const char *needle) +{ +#ifdef HAVE_STRSTR + return SDL_const_cast(char *, strstr(haystack, needle)); +#else + return SDL_strnstr(haystack, needle, SDL_strlen(haystack)); +#endif /* HAVE_STRSTR */ +} + char *SDL_strcasestr(const char *haystack, const char *needle) { #ifdef HAVE_STRCASESTR diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index eab676d795a61..d4abe2a2b2771 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -60,6 +60,68 @@ static int stdlib_strlcpy(void *arg) return TEST_COMPLETED; } +/** + * Call to SDL_strstr + */ +static int stdlib_strstr(void *arg) +{ + char *result; + const char *text = "abcdef"; + const char *expected; + + result = SDL_strstr(text, ""); + expected = text; + SDLTest_AssertPass("Call to SDL_strstr(text, \"\")"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strstr(text, "abc"); + expected = text; + SDLTest_AssertPass("Call to SDL_strstr(text, \"abc\")"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strstr(text, "bcd"); + expected = text+1; + SDLTest_AssertPass("Call to SDL_strstr(text, \"bcd\")"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strstr(text, "xyz"); + expected = NULL; + SDLTest_AssertPass("Call to SDL_strstr(text, \"xyz\")"); + SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result); + + result = SDL_strnstr(text, "", SDL_strlen(text)); + expected = text; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"\", SDL_strlen(text))"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strnstr(text, "abc", SDL_strlen(text)); + expected = text; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"abc\", SDL_strlen(text))"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strnstr(text, "bcd", SDL_strlen(text)); + expected = text+1; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"bcd\", SDL_strlen(text))"); + SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result); + + result = SDL_strnstr(text, "bcd", 3); + expected = NULL; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"bcd\", 3)"); + SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result); + + result = SDL_strnstr(text, "xyz", 3); + expected = NULL; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"xyz\", 3)"); + SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result); + + result = SDL_strnstr(text, "xyz", SDL_strlen(text)*100000); + expected = NULL; + SDLTest_AssertPass("Call to SDL_strnstr(text, \"xyz\", SDL_strlen(text)*100000)"); + SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result); + + return TEST_COMPLETED; +} + #if defined(HAVE_WFORMAT) || defined(HAVE_WFORMAT_EXTRA_ARGS) #pragma GCC diagnostic push #ifdef HAVE_WFORMAT @@ -930,22 +992,26 @@ static const SDLTest_TestCaseReference stdlibTest2 = { }; static const SDLTest_TestCaseReference stdlibTest3 = { - stdlib_snprintf, "stdlib_snprintf", "Call to SDL_snprintf", TEST_ENABLED + stdlib_strstr, "stdlib_strstr", "Call to SDL_strstr", TEST_ENABLED }; static const SDLTest_TestCaseReference stdlibTest4 = { - stdlib_swprintf, "stdlib_swprintf", "Call to SDL_swprintf", TEST_ENABLED + stdlib_snprintf, "stdlib_snprintf", "Call to SDL_snprintf", TEST_ENABLED }; static const SDLTest_TestCaseReference stdlibTest5 = { - stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED + stdlib_swprintf, "stdlib_swprintf", "Call to SDL_swprintf", TEST_ENABLED }; static const SDLTest_TestCaseReference stdlibTest6 = { - stdlib_sscanf, "stdlib_sscanf", "Call to SDL_sscanf", TEST_ENABLED + stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED }; static const SDLTest_TestCaseReference stdlibTest7 = { + stdlib_sscanf, "stdlib_sscanf", "Call to SDL_sscanf", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference stdlibTest8 = { stdlib_aligned_alloc, "stdlib_aligned_alloc", "Call to SDL_aligned_alloc", TEST_ENABLED }; @@ -962,6 +1028,7 @@ static const SDLTest_TestCaseReference *stdlibTests[] = { &stdlibTest5, &stdlibTest6, &stdlibTest7, + &stdlibTest8, &stdlibTestOverflow, NULL }; From 14380ec48a32a2a8f316fe3c315f07f8aa0a92de Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 3 Dec 2023 14:56:21 -0800 Subject: [PATCH 484/725] Fixed signed/unsigned comparison warning --- src/joystick/SDL_gamepad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index d7fc41028cfdd..fd07774849e27 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -2079,7 +2079,7 @@ char **SDL_GetGamepadMappings(int *count) if (!mappings) { failed = SDL_TRUE; } else { - size_t i = 0; + int i = 0; for (GamepadMapping_t *mapping = s_pSupportedGamepads; mapping; mapping = mapping->next) { if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { continue; From 6cfce101fbdc99dfbf8af33576489e751a752f08 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 07:48:13 -0800 Subject: [PATCH 485/725] Don't call the property cleanup function if setting the property fails Fixes https://github.com/libsdl-org/SDL/issues/8659 --- src/SDL_properties.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index b883a4d37dcd1..27271a4872993 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -54,13 +54,13 @@ static SDL_PropertiesID SDL_last_properties_id; static SDL_PropertiesID SDL_global_properties; -static void SDL_FreeProperty(const void *key, const void *value, void *data) +static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void *data, SDL_bool cleanup) { SDL_Property *property = (SDL_Property *)value; if (property) { switch (property->type) { case SDL_PROPERTY_TYPE_POINTER: - if (property->cleanup) { + if (property->cleanup && cleanup) { property->cleanup(property->userdata, property->value.pointer_value); } break; @@ -78,6 +78,11 @@ static void SDL_FreeProperty(const void *key, const void *value, void *data) SDL_free((void *)value); } +static void SDL_FreeProperty(const void *key, const void *value, void *data) +{ + SDL_FreePropertyWithCleanup(key, value, data, SDL_TRUE); +} + static void SDL_FreeProperties(const void *key, const void *value, void *data) { SDL_Properties *properties = (SDL_Properties *)value; @@ -228,11 +233,11 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ int result = 0; if (!props) { - SDL_FreeProperty(NULL, property, NULL); + SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); return SDL_InvalidParamError("props"); } if (!name || !*name) { - SDL_FreeProperty(NULL, property, NULL); + SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); return SDL_InvalidParamError("name"); } @@ -241,7 +246,7 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_FreeProperty(NULL, property, NULL); + SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); return SDL_InvalidParamError("props"); } @@ -251,7 +256,7 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ if (property) { char *key = SDL_strdup(name); if (!SDL_InsertIntoHashTable(properties->props, key, property)) { - SDL_FreeProperty(key, property, NULL); + SDL_FreePropertyWithCleanup(key, property, NULL, SDL_FALSE); result = -1; } } From f3b0149756207e3af18ea3036184b681ff9bd0bd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 19:30:01 -0800 Subject: [PATCH 486/725] Fixed warning C26451: Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2). --- src/audio/SDL_wave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index cb3732305d578..1af3b97e1b273 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -985,7 +985,7 @@ static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) const size_t remainingbytes = blockleft % subblockframesize; blockframesleft = guaranteedframes; if (remainingbytes > subblockframesize - 4) { - blockframesleft += (remainingbytes % 4) * 2; + blockframesleft += (Sint64)(remainingbytes % 4) * 2; } /* Signal the truncation. */ retval = -1; From fe6b3ab0b0bad22942532c84109e4e2465692781 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 19:33:25 -0800 Subject: [PATCH 487/725] Fixed warning C6031: Return value ignored: 'CLSIDFromString'. --- src/core/windows/SDL_immdevice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index fe2de5728f7d0..97a22a47f1f39 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -103,7 +103,7 @@ static void GetMMDeviceInfo(IMMDevice *device, char **utf8dev, WAVEFORMATEXTENSI } PropVariantClear(&var); if (SUCCEEDED(IPropertyStore_GetValue(props, &SDL_PKEY_AudioEndpoint_GUID, &var))) { - CLSIDFromString(var.pwszVal, guid); + (void)CLSIDFromString(var.pwszVal, guid); } PropVariantClear(&var); IPropertyStore_Release(props); From 226f8fde09fdc315730fc64e18ad2653bc24dac2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 19:43:41 -0800 Subject: [PATCH 488/725] Fixed warning C28182: Dereferencing NULL pointer. 'streams[j]' contains the same NULL value as 'stream' did. --- src/audio/SDL_audio.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b47c840b6b54f..54f74d89b1448 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1771,7 +1771,14 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int if (retval != 0) { int j; for (j = 0; j <= i; j++) { +#ifdef _MSC_VER /* Visual Studio analyzer can't tell that we've already verified streams[j] isn't NULL */ +#pragma warning(push) +#pragma warning(disable : 28182) +#endif SDL_UnlockMutex(streams[j]->lock); +#ifdef _MSC_VER +#pragma warning(pop) +#endif } break; } @@ -1782,6 +1789,10 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int // Now that everything is verified, chain everything together. const SDL_bool iscapture = device->iscapture; for (int i = 0; i < num_streams; i++) { +#ifdef _MSC_VER /* Visual Studio analyzer can't tell that streams[i] isn't NULL if retval is 0 */ +#pragma warning(push) +#pragma warning(disable : 28182) +#endif SDL_AudioStream *stream = streams[i]; stream->bound_device = logdev; @@ -1800,6 +1811,9 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int } SDL_UnlockMutex(stream->lock); +#ifdef _MSC_VER +#pragma warning(pop) +#endif } } From 3e54061fa8f6f2af530f3643796dfb38c9f56935 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 19:45:54 -0800 Subject: [PATCH 489/725] Fixed warning C6011: Dereferencing NULL pointer 'SDL_disabled_events[hi]'. --- src/events/SDL_events.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 040e5bdc8bfc0..93588772c20ae 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -1355,7 +1355,14 @@ void SDL_SetEventEnabled(Uint32 type, SDL_bool enabled) if (enabled != current_state) { if (enabled) { +#ifdef _MSC_VER /* Visual Studio analyzer can't tell that SDL_disabled_events[hi] isn't NULL if enabled is true */ +#pragma warning(push) +#pragma warning(disable : 6011) +#endif SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif /* Gamepad events depend on joystick events */ switch (type) { From 06f8f9a891194d86ff93a5856f80510d39b75272 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 19:57:21 -0800 Subject: [PATCH 490/725] Fixed warning C6326: Potential comparison of a constant with another constant. Also fixed warning C6239: ( && ) always evaluates to the result of . Did you intend to use the bitwise-and operator? --- src/video/yuv2rgb/yuv_rgb_std_func.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/video/yuv2rgb/yuv_rgb_std_func.h b/src/video/yuv2rgb/yuv_rgb_std_func.h index 94872ec9f56cb..17b61db751e21 100644 --- a/src/video/yuv2rgb/yuv_rgb_std_func.h +++ b/src/video/yuv2rgb/yuv_rgb_std_func.h @@ -69,6 +69,12 @@ #endif +#ifdef _MSC_VER /* Visual Studio analyzer can't tell that we're building this with different constants */ +#pragma warning(push) +#pragma warning(disable : 6239) +#pragma warning(disable : 6326) +#endif + void STD_FUNCTION_NAME( uint32_t width, uint32_t height, const uint8_t *Y, const uint8_t *U, const uint8_t *V, uint32_t Y_stride, uint32_t UV_stride, @@ -227,6 +233,10 @@ void STD_FUNCTION_NAME( #undef uv_y_sample_interval } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #undef STD_FUNCTION_NAME #undef YUV_FORMAT #undef RGB_FORMAT From 0c4cb3d1539fefa66c05d131385e35fb2a205fa3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:01:15 -0800 Subject: [PATCH 491/725] Fixed warning C26451: Arithmetic overflow: Using operator '<<' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '<<' to avoid overflow (io.2). --- src/video/yuv2rgb/yuv_rgb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/video/yuv2rgb/yuv_rgb.c b/src/video/yuv2rgb/yuv_rgb.c index bf4002014af1e..f24b27b4f6f03 100644 --- a/src/video/yuv2rgb/yuv_rgb.c +++ b/src/video/yuv2rgb/yuv_rgb.c @@ -31,6 +31,11 @@ typedef struct // |G| = 1/PRECISION_FACTOR * |y_factor u_g_factor v_g_factor| * | U-128 | // |B| |y_factor u_b_factor 0 | | V-128 | +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 26451) +#endif + #define V(value) (int16_t)((value*PRECISION_FACTOR)+0.5) // for ITU-T T.871, values can be found in section 7 @@ -56,6 +61,10 @@ static const RGB2YUVParam RGB2YUV[3] = { {/*.y_shift=*/ 16, /*.matrix=*/ {{V(0.1826), V(0.6142), V(0.062)}, {-V(0.1006), -V(0.3386), V(0.4392)}, {V(0.4392), -V(0.3989), -V(0.0403)}}} }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + /* The various layouts of YUV data we support */ #define YUV_FORMAT_420 1 #define YUV_FORMAT_422 2 From 21f273ecc7926e1432776e828f2d769ea25a0cfa Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:15:42 -0800 Subject: [PATCH 492/725] Fixed warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead. --- src/SDL_internal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SDL_internal.h b/src/SDL_internal.h index 8c5463a924fb4..23a836a8395e6 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -44,6 +44,9 @@ #define HAVE_GCC_DIAGNOSTIC_PRAGMA 1 #endif +#ifdef _MSC_VER // SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe +#pragma warning(disable : 6255) +#endif #define SDL_MAX_SMALL_ALLOC_STACKSIZE 128 #define SDL_small_alloc(type, count, pisstack) ((*(pisstack) = ((sizeof(type) * (count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type *)SDL_malloc(sizeof(type) * (count)))) #define SDL_small_free(ptr, isstack) \ From a9b87ee2015c4d67484648b45dcea303064d44bc Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:22:23 -0800 Subject: [PATCH 493/725] Fixed warning C28159: Consider using 'GetTickCount64' instead of 'GetTickCount'. Reason: GetTickCount overflows roughly every 49 days. Code that does not take that into account can loop indefinitely. GetTickCount64 operates on 64 bit values and does not have that problem --- src/video/windows/SDL_windowsevents.c | 7 +++++++ src/video/windows/SDL_windowsmouse.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 620ab332bd1be..1c45f711a74b0 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1643,7 +1643,14 @@ void WIN_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window) void WIN_PumpEvents(SDL_VideoDevice *_this) { MSG msg; +#ifdef _MSC_VER /* We explicitly want to use GetTickCount(), not GetTickCount64() */ +#pragma warning(push) +#pragma warning(disable : 28159) +#endif DWORD end_ticks = GetTickCount() + 1; +#ifdef _MSC_VER +#pragma warning(pop) +#endif int new_messages = 0; #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) const Uint8 *keystate; diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 21e19685b163d..95d2e01cfde6b 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -316,10 +316,17 @@ void WIN_SetCursorPos(int x, int y) SetCursorPos(x, y); /* Flush any mouse motion prior to or associated with this warp */ +#ifdef _MSC_VER /* We explicitly want to use GetTickCount(), not GetTickCount64() */ +#pragma warning(push) +#pragma warning(disable : 28159) +#endif SDL_last_warp_time = GetTickCount(); if (!SDL_last_warp_time) { SDL_last_warp_time = 1; } +#ifdef _MSC_VER +#pragma warning(pop) +#endif } static int WIN_WarpMouse(SDL_Window *window, float x, float y) From 69b9d44bdc74ee6ffd7415c73a82040c56789613 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:25:18 -0800 Subject: [PATCH 494/725] Fixed warning C26451: Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '-' to avoid overflow (io.2). --- src/video/windows/SDL_windowskeyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 06396c603d611..c637710c3993f 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -1484,7 +1484,7 @@ static void StopDrawToBitmap(HDC hdc, HBITMAP *hhbm) static void DrawRect(HDC hdc, int left, int top, int right, int bottom, int pensize) { /* The case of no pen (PenSize = 0) is automatically taken care of. */ - const int penadjust = (int)SDL_floor(pensize / 2.0f - 0.5f); + const int penadjust = (int)SDL_floorf(pensize / 2.0f - 0.5f); left += pensize / 2; top += pensize / 2; right -= penadjust; From c7d81d936aabbdca4009d8a971f10240a04527c6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:28:42 -0800 Subject: [PATCH 495/725] Fixed warning C6031: Return value ignored: 'GetKeyboardState'. --- src/video/windows/SDL_windowskeyboard.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index c637710c3993f..f84c1bdc954ca 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -198,7 +198,9 @@ void WIN_ResetDeadKeys() WCHAR buffer[16]; int keycode, scancode, result, i; - GetKeyboardState(keyboardState); + if (!GetKeyboardState(keyboardState)) { + return; + } keycode = VK_SPACE; scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC); From 3db4695ac705b6c4c3e95c05dd5d29333d339ba9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:32:50 -0800 Subject: [PATCH 496/725] warning C6340: Mismatch on sign: 'unsigned int' passed as _Param_(3) when some signed type is required in call to 'SDL_LogDebug_REAL'. --- src/video/SDL_vulkan_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index f31d1009d4353..c2e0a600fca6b 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -408,7 +408,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_, if (extent.width >= planeCaps.minDstExtent.width && extent.height >= planeCaps.minDstExtent.height && extent.width <= planeCaps.maxDstExtent.width && extent.height <= planeCaps.maxDstExtent.height) { /* If it does, choose this plane. */ - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Choosing plane %d, minimum extent %dx%d maximum extent %dx%d", i, + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Choosing plane %u, minimum extent %ux%u maximum extent %ux%u", i, planeCaps.minDstExtent.width, planeCaps.minDstExtent.height, planeCaps.maxDstExtent.width, planeCaps.maxDstExtent.height); planeIndex = i; From 4ccc53edfeb2444101dc1f3a900ea88bf45f3b89 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:35:14 -0800 Subject: [PATCH 497/725] Fixed warning C6011: Dereferencing NULL pointer 'display'. --- src/video/SDL_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 3f416f2b738af..74cd5d50c1c7a 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1508,7 +1508,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) break; } } - if (i == _this->num_displays) { + if (!display || i == _this->num_displays) { /* Already not fullscreen on any display */ goto done; } From c9b243fb5647d651a0ae49029ce43b38c2b0aad6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:30:52 -0800 Subject: [PATCH 498/725] Fixed warning C6263: Using _alloca in a loop: this can quickly overflow stack. --- src/video/windows/SDL_windowsevents.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 1c45f711a74b0..4c2bb0be1e9b2 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1288,16 +1288,15 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) HDROP drop = (HDROP)wParam; UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0); for (i = 0; i < count; ++i) { - SDL_bool isstack; UINT size = DragQueryFile(drop, i, NULL, 0) + 1; - LPTSTR buffer = SDL_small_alloc(TCHAR, size, &isstack); + LPTSTR buffer = (LPTSTR)SDL_malloc(sizeof(TCHAR) * size); if (buffer) { if (DragQueryFile(drop, i, buffer, size)) { char *file = WIN_StringToUTF8(buffer); SDL_SendDropFile(data->window, NULL, file); SDL_free(file); } - SDL_small_free(buffer, isstack); + SDL_free(buffer); } } SDL_SendDropComplete(data->window); From 0dad56354ceb4222be569e6969475adeec5a1ca1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:54:11 -0800 Subject: [PATCH 499/725] Fixed warning C6326: Potential comparison of a constant with another constant. --- src/SDL_internal.h | 6 ++- src/video/yuv2rgb/yuv_rgb_std_func.h | 55 ++++++++++++++-------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/SDL_internal.h b/src/SDL_internal.h index 23a836a8395e6..2ae4ba2dd802f 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -44,7 +44,11 @@ #define HAVE_GCC_DIAGNOSTIC_PRAGMA 1 #endif -#ifdef _MSC_VER // SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe +#ifdef _MSC_VER /* We use constant comparison for generated code */ +#pragma warning(disable : 6326) +#endif + +#ifdef _MSC_VER /* SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe */ #pragma warning(disable : 6255) #endif #define SDL_MAX_SMALL_ALLOC_STACKSIZE 128 diff --git a/src/video/yuv2rgb/yuv_rgb_std_func.h b/src/video/yuv2rgb/yuv_rgb_std_func.h index 17b61db751e21..f359abae8b444 100644 --- a/src/video/yuv2rgb/yuv_rgb_std_func.h +++ b/src/video/yuv2rgb/yuv_rgb_std_func.h @@ -72,13 +72,12 @@ #ifdef _MSC_VER /* Visual Studio analyzer can't tell that we're building this with different constants */ #pragma warning(push) #pragma warning(disable : 6239) -#pragma warning(disable : 6326) #endif void STD_FUNCTION_NAME( - uint32_t width, uint32_t height, - const uint8_t *Y, const uint8_t *U, const uint8_t *V, uint32_t Y_stride, uint32_t UV_stride, - uint8_t *RGB, uint32_t RGB_stride, + uint32_t width, uint32_t height, + const uint8_t *Y, const uint8_t *U, const uint8_t *V, uint32_t Y_stride, uint32_t UV_stride, + uint8_t *RGB, uint32_t RGB_stride, YCbCrType yuv_type) { const YUV2RGBParam *const param = &(YUV2RGB[yuv_type]); @@ -119,26 +118,26 @@ void STD_FUNCTION_NAME( for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval) { // Compute U and V contributions, common to the four pixels - + int32_t u_tmp = ((*u_ptr)-128); int32_t v_tmp = ((*v_ptr)-128); - + int32_t r_tmp = (v_tmp*param->v_r_factor); int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor); int32_t b_tmp = (u_tmp*param->u_b_factor); - + // Compute the Y contribution for each pixel - + int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); - + y_tmp = ((y_ptr1[y_pixel_stride]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); - + #if uv_y_sample_interval > 1 y_tmp = ((y_ptr2[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr2); - + y_tmp = ((y_ptr2[y_pixel_stride]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr2); #endif @@ -155,19 +154,19 @@ void STD_FUNCTION_NAME( if (uv_x_sample_interval == 2 && x == (width-1)) { // Compute U and V contributions, common to the four pixels - + int32_t u_tmp = ((*u_ptr)-128); int32_t v_tmp = ((*v_ptr)-128); - + int32_t r_tmp = (v_tmp*param->v_r_factor); int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor); int32_t b_tmp = (u_tmp*param->u_b_factor); - + // Compute the Y contribution for each pixel - + int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); - + #if uv_y_sample_interval > 1 y_tmp = ((y_ptr2[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr2); @@ -181,28 +180,28 @@ void STD_FUNCTION_NAME( const uint8_t *y_ptr1=Y+y*Y_stride, *u_ptr=U+(y/uv_y_sample_interval)*UV_stride, *v_ptr=V+(y/uv_y_sample_interval)*UV_stride; - + uint8_t *rgb_ptr1=RGB+y*RGB_stride; - + for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval) { // Compute U and V contributions, common to the four pixels - + int32_t u_tmp = ((*u_ptr)-128); int32_t v_tmp = ((*v_ptr)-128); - + int32_t r_tmp = (v_tmp*param->v_r_factor); int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor); int32_t b_tmp = (u_tmp*param->u_b_factor); - + // Compute the Y contribution for each pixel - + int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); - + y_tmp = ((y_ptr1[y_pixel_stride]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); - + y_ptr1+=2*y_pixel_stride; u_ptr+=2*uv_pixel_stride/uv_x_sample_interval; v_ptr+=2*uv_pixel_stride/uv_x_sample_interval; @@ -212,16 +211,16 @@ void STD_FUNCTION_NAME( if (uv_x_sample_interval == 2 && x == (width-1)) { // Compute U and V contributions, common to the four pixels - + int32_t u_tmp = ((*u_ptr)-128); int32_t v_tmp = ((*v_ptr)-128); - + int32_t r_tmp = (v_tmp*param->v_r_factor); int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor); int32_t b_tmp = (u_tmp*param->u_b_factor); - + // Compute the Y contribution for each pixel - + int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor); PACK_PIXEL(rgb_ptr1); } From 54dc73aa889805978541705017aa416f04ba45c3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:57:27 -0800 Subject: [PATCH 500/725] Fixed warning C6386: Buffer overrun while writing to 'palette_saved_alpha': the writable size is 'sizeof(Uint8)*((palette_saved_alpha_ncolors))' bytes, but '2' bytes might be written. --- src/video/SDL_surface.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index b59df0c51eb45..7b26b5e2eb41d 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1210,10 +1210,12 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for if (set_opaque) { int i; palette_saved_alpha_ncolors = surface->format->palette->ncolors; - palette_saved_alpha = SDL_stack_alloc(Uint8, palette_saved_alpha_ncolors); - for (i = 0; i < palette_saved_alpha_ncolors; i++) { - palette_saved_alpha[i] = surface->format->palette->colors[i].a; - surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE; + if (palette_saved_alpha_ncolors > 0) { + palette_saved_alpha = SDL_stack_alloc(Uint8, palette_saved_alpha_ncolors); + for (i = 0; i < palette_saved_alpha_ncolors; i++) { + palette_saved_alpha[i] = surface->format->palette->colors[i].a; + surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE; + } } } } From 41bfcad5d75da3dba31e8e3a211df0d9d9539689 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:58:58 -0800 Subject: [PATCH 501/725] Fixed warning C6340: Mismatch on sign: 'unsigned short' passed as _Param_(2) when some signed type is required in call to 'SDL_SetError_REAL'. --- src/video/SDL_bmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index c5fe6c7deb01d..ef2caf7383979 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -370,7 +370,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) case 5: case 6: case 7: - SDL_SetError("%d-bpp BMP images are not supported", biBitCount); + SDL_SetError("%u bpp BMP images are not supported", biBitCount); goto done; default: break; @@ -650,7 +650,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst) if (surface->format->BitsPerPixel == 8) { intermediate_surface = surface; } else { - SDL_SetError("%d bpp BMP files not supported", + SDL_SetError("%u bpp BMP files not supported", surface->format->BitsPerPixel); goto done; } From eab2d97d071349eec3965ce0131eb8a89616fc6f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 20:59:43 -0800 Subject: [PATCH 502/725] Fixed warning C26451: Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2). --- src/video/SDL_blit_A.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_blit_A.c b/src/video/SDL_blit_A.c index 0e61c8a356e81..7ee829c5e2d92 100644 --- a/src/video/SDL_blit_A.c +++ b/src/video/SDL_blit_A.c @@ -345,7 +345,7 @@ static void SDL_TARGETING("mmx") BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info) } multmask = 0x00FF; - multmask <<= (ashift * 2); + multmask <<= ((Uint64)ashift * 2); multmask2 = 0x00FF00FF00FF00FFULL; while (height--) { From 22f44aefe74ce09f0cf01a1f720c069dd18015cb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:00:25 -0800 Subject: [PATCH 503/725] Fixed warning C6340: Mismatch on sign: 'int' passed as _Param_(3) when some unsigned type is required in call to 'SDL_sscanf_REAL'. --- src/video/SDL_blit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 44807bcb9f14b..886fcb936d9f1 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -126,7 +126,7 @@ static SDL_BlitFunc SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int SDL_BlitFuncEntry *entries) { int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST)); - static int features = 0x7fffffff; + static unsigned int features = 0x7fffffff; /* Get the available CPU features */ if (features == 0x7fffffff) { From fda039e6f81c47e38a4670419c25fad319ac7082 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:21:51 -0800 Subject: [PATCH 504/725] Fixed analyzer warnings for SDL_string.c warning C28251: Inconsistent annotation for 'SDL_vsscanf_REAL': this instance has no annotations. See c:\projects\sdl-experimental\include\sdl3\sdl_stdinc.h(597). warning C28252: Inconsistent annotation for 'SDL_vsnprintf_REAL': _Param_(3) has 'SAL_IsFormatString("printf")' on the prior instance. See c:\projects\sdl-experimental\include\sdl3\sdl_stdinc.h(600). warning C28253: Inconsistent annotation for 'SDL_vswprintf_REAL': _Param_(3) has 'SAL_IsFormatString("printf")' on this instance. See c:\projects\sdl-experimental\include\sdl3\sdl_stdinc.h(601). warning C28251: Inconsistent annotation for 'SDL_vasprintf_REAL': this instance has no annotations. See c:\projects\sdl-experimental\include\sdl3\sdl_stdinc.h(603). --- src/stdlib/SDL_string.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 8570d4fa1ac54..1456f3656b6e8 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1255,7 +1255,7 @@ static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len) } /* NOLINTNEXTLINE(readability-non-const-parameter) */ -int SDL_vsscanf(const char *text, const char *fmt, va_list ap) +int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2) { int retval = 0; @@ -1922,7 +1922,7 @@ static size_t SDL_PrintPointer(char *text, size_t maxlen, SDL_FormatInfo *info, } /* NOLINTNEXTLINE(readability-non-const-parameter) */ -int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap) +int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { size_t length = 0; @@ -2146,7 +2146,7 @@ int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *f #undef TEXT_AND_LEN_ARGS #endif /* HAVE_VSNPRINTF */ -int SDL_vswprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, va_list ap) +int SDL_vswprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, const wchar_t *fmt, va_list ap) { char *text_utf8 = NULL, *fmt_utf8 = NULL; int retval; @@ -2201,7 +2201,7 @@ int SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) return retval; } -int SDL_vasprintf(char **strp, const char *fmt, va_list ap) +int SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { int retval; int size = 100; /* Guess we need no more than 100 bytes */ From 8a82f7e837180cdd9974af36638fd523d4552420 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:24:37 -0800 Subject: [PATCH 505/725] Fixed warning C33005: VARIANT '&valueX' was provided as an _In_ or _InOut_ parameter but was not initialized --- src/sensor/windows/SDL_windowssensor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index cbd98875c2d66..e61e826990be0 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -150,7 +150,7 @@ static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents * if (pSensor == SDL_sensors[i].sensor) { if (SDL_sensors[i].sensor_opened) { HRESULT hrX, hrY, hrZ; - PROPVARIANT valueX, valueY, valueZ; + PROPVARIANT valueX = { 0 }, valueY = { 0 }, valueZ = { 0 }; SYSTEMTIME sensor_systemtime; FILETIME sensor_filetime; Uint64 sensor_timestamp; From b512182222b64e178fae0a96075d1779392f60a9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:25:50 -0800 Subject: [PATCH 506/725] Fixed warning C6340: Mismatch on sign: 'unsigned int' passed as _Param_(2) when some signed type is required in call to 'SDL_SetError_REAL'. --- src/sensor/SDL_sensor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index b706261d236d0..4253af0d7d252 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -236,7 +236,7 @@ static SDL_bool SDL_GetDriverAndSensorIndex(SDL_SensorID instance_id, SDL_Sensor } } } - SDL_SetError("Sensor %" SDL_PRIs32 " not found", instance_id); + SDL_SetError("Sensor %" SDL_PRIu32 " not found", instance_id); return SDL_FALSE; } From 3775d9be4bffddbbf11c3a48a4a02f27d4a34dea Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:26:49 -0800 Subject: [PATCH 507/725] Fixed warning C28251: Inconsistent annotation for 'SDL_LogMessageV_REAL': this instance has no annotations. --- src/SDL_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SDL_log.c b/src/SDL_log.c index 89cc380c863b1..aea6ce38697e8 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -282,7 +282,7 @@ static const char *GetCategoryPrefix(int category) } #endif /* __ANDROID__ */ -void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap) +void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { char *message = NULL; char stack_buf[SDL_MAX_LOG_MESSAGE_STACK]; From 230581f4a8992dc1f1c0d030375c964104be4c26 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:28:27 -0800 Subject: [PATCH 508/725] Fixed warning C26451: Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2). --- src/render/software/SDL_rotate.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/render/software/SDL_rotate.c b/src/render/software/SDL_rotate.c index 637653a5b3841..7689b68a5510c 100644 --- a/src/render/software/SDL_rotate.c +++ b/src/render/software/SDL_rotate.c @@ -296,8 +296,8 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i int y; for (y = 0; y < dst->h; y++) { int x; - double src_x = (rect_dest->x + 0 + 0.5 - center->x); - double src_y = (rect_dest->y + y + 0.5 - center->y); + double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); + double src_y = ((double)rect_dest->y + y + 0.5 - center->y); int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); for (x = 0; x < dst->w; x++) { @@ -364,8 +364,8 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i int y; for (y = 0; y < dst->h; y++) { int x; - double src_x = (rect_dest->x + 0 + 0.5 - center->x); - double src_y = (rect_dest->y + y + 0.5 - center->y); + double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); + double src_y = ((double)rect_dest->y + y + 0.5 - center->y); int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); for (x = 0; x < dst->w; x++) { @@ -437,8 +437,8 @@ static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int isin, int */ for (y = 0; y < dst->h; y++) { int x; - double src_x = (rect_dest->x + 0 + 0.5 - center->x); - double src_y = (rect_dest->y + y + 0.5 - center->y); + double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x); + double src_y = ((double)rect_dest->y + y + 0.5 - center->y); int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half); int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half); for (x = 0; x < dst->w; x++) { From 6ee34380f4f292001adbbd1227847c418ccbb03b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:29:29 -0800 Subject: [PATCH 509/725] Fixed warning C6011: Dereferencing NULL pointer 'viewport'. --- src/render/software/SDL_render_sw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 1ba010a2e3363..591bb89c2a2f9 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -643,7 +643,7 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate) const SDL_Rect *cliprect = drawstate->cliprect; SDL_assert_release(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */ - if (cliprect) { + if (cliprect && viewport) { SDL_Rect clip_rect; clip_rect.x = cliprect->x + viewport->x; clip_rect.y = cliprect->y + viewport->y; From a28769759b0ed12b08028556cebe97d5d1c0d965 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:33:27 -0800 Subject: [PATCH 510/725] Fixed warning C26052: Potentially unconstrained access using expression '(signed char *)info' --- src/render/opengles2/SDL_render_gles2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 1173822efad7d..2e6d6fb1dce9f 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -543,20 +543,19 @@ static GLuint GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, G } if (!compileSuccessful) { - SDL_bool isstack = SDL_FALSE; char *info = NULL; int length = 0; data->glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); if (length > 0) { - info = SDL_small_alloc(char, length, &isstack); + info = (char *)SDL_malloc(length); if (info) { data->glGetShaderInfoLog(id, length, &length, info); } } if (info) { SDL_SetError("Failed to load the shader %d: %s", type, info); - SDL_small_free(info, isstack); + SDL_free(info); } else { SDL_SetError("Failed to load the shader %d", type); } From 2b5c7db6458fc1d7289feec296d764c4c5e1e6b1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:38:37 -0800 Subject: [PATCH 511/725] Fixed analyze warnings in SDL_render_d3d12.c warning C6011: Dereferencing NULL pointer 'data->swapChain'. warning C6011: Dereferencing NULL pointer 'data->debugInterface'. --- src/render/direct3d12/SDL_render_d3d12.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index d1cafa5bf450d..24393fb4da8c8 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -795,8 +795,9 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) result = E_FAIL; goto done; } - D3D12GetDebugInterfaceFunc(D3D_GUID(SDL_IID_ID3D12Debug), (void **)&data->debugInterface); - D3D_CALL(data->debugInterface, EnableDebugLayer); + if (SUCCEEDED(D3D12GetDebugInterfaceFunc(D3D_GUID(SDL_IID_ID3D12Debug), (void **)&data->debugInterface))) { + D3D_CALL(data->debugInterface, EnableDebugLayer); + } } #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ @@ -1302,7 +1303,7 @@ static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer) } } else { result = D3D12_CreateSwapChain(renderer, w, h); - if (FAILED(result)) { + if (FAILED(result) || !data->swapChain) { goto done; } } From 0f34ca2e7119ea34149d989da6574b400060104a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:42:47 -0800 Subject: [PATCH 512/725] Fixed analyze warnings in SDL_xinputjoystick.c warning C6340: Mismatch on sign: 'int' passed as _Param_(4) when some unsigned type is required in call to 'SDL_snprintf_REAL'. warning C6001: Using uninitialized memory 'devName'. warning C6340: Mismatch on sign: 'unsigned char' passed as _Param_(4) when some signed type is required in call to 'SDL_snprintf_REAL'. warning C6221: Implicit cast between semantically different integer types: comparing HRESULT to an integer. Consider using SUCCEEDED or FAILED macros instead. --- src/joystick/windows/SDL_xinputjoystick.c | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 2c5668d7ec0d6..7fbf1b6ffb8b7 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -77,37 +77,37 @@ static const char *GetXInputName(const Uint8 userid, BYTE SubType) static char name[32]; if (SDL_XInputUseOldJoystickMapping()) { - (void)SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "X360 Controller #%d", 1 + userid); } else { switch (SubType) { case XINPUT_DEVSUBTYPE_GAMEPAD: - (void)SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput Controller #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_WHEEL: - (void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_ARCADE_STICK: - (void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_FLIGHT_STICK: - (void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_DANCE_PAD: - (void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_GUITAR: case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE: case XINPUT_DEVSUBTYPE_GUITAR_BASS: - (void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_DRUM_KIT: - (void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%d", 1 + userid); break; case XINPUT_DEVSUBTYPE_ARCADE_PAD: - (void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%d", 1 + userid); break; default: - (void)SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid); + (void)SDL_snprintf(name, sizeof(name), "XInput Device #%d", 1 + userid); break; } } @@ -142,7 +142,7 @@ static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 * if (s_arrXInputDevicePath[userid]) { for (i = 0; i < device_count; i++) { RID_DEVICE_INFO rdi; - char devName[128]; + char devName[128] = { 0 }; UINT rdiSize = sizeof(rdi); UINT nameSize = SDL_arraysize(devName); @@ -163,7 +163,7 @@ static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 * for (i = 0; i < device_count; i++) { RID_DEVICE_INFO rdi; - char devName[MAX_PATH]; + char devName[MAX_PATH] = { 0 }; UINT rdiSize = sizeof(rdi); UINT nameSize = SDL_arraysize(devName); @@ -285,7 +285,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC SDL_free(pNewJoystick); return; /* better luck next time? */ } - (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid); + (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%u", userid); if (!SDL_XInputUseOldJoystickMapping()) { GuessXInputDevice(userid, &vendor, &product, &version); @@ -512,7 +512,7 @@ Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick) { - HRESULT result; + DWORD result; XINPUT_STATE XInputState; XINPUT_BATTERY_INFORMATION_EX XBatteryInformation; From e29393e40700ba45f66fd36f298f8ad91ee24f9f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:44:26 -0800 Subject: [PATCH 513/725] Fixed warning C6001: Using uninitialized memory 'devName'. --- src/joystick/windows/SDL_windows_gaming_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index db946a0f909ad..ca86f707c760b 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -143,7 +143,7 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) for (i = 0; i < raw_device_count; i++) { RID_DEVICE_INFO rdi; - char devName[MAX_PATH]; + char devName[MAX_PATH] = { 0 }; UINT rdiSize = sizeof(rdi); UINT nameSize = SDL_arraysize(devName); DEVINST devNode; From 163de8e697bb9353c56bb8f43248bfa73ffa417c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:45:39 -0800 Subject: [PATCH 514/725] Fixed warning C6001: Using uninitialized memory 'rdi'. --- src/joystick/windows/SDL_rawinputjoystick.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 3302e873eb19b..f4e68b7bc813e 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -852,7 +852,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) SDL_RAWINPUT_Device *curr, *last; RID_DEVICE_INFO rdi; UINT size; - char dev_name[MAX_PATH]; + char dev_name[MAX_PATH] = { 0 }; HANDLE hFile = INVALID_HANDLE_VALUE; /* Make sure we're not trying to add the same device twice */ @@ -862,6 +862,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) /* Figure out what kind of device it is */ size = sizeof(rdi); + SDL_zero(rdi); CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICEINFO, &rdi, &size) != (UINT)-1); CHECK(rdi.dwType == RIM_TYPEHID); From 7f2e16db8b5c833f57d66b5d6b28ca38646eacb9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:46:17 -0800 Subject: [PATCH 515/725] Fixed warning C6340: Mismatch on sign: 'const unsigned short' passed as _Param_(2) when some signed type is required in call to 'SDL_SetError_REAL'. --- src/joystick/virtual/SDL_virtualjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 23519e53b827a..f32c76fd27db6 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -119,7 +119,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des } if (desc->version != SDL_VIRTUAL_JOYSTICK_DESC_VERSION) { /* Is this an old version that we can support? */ - return SDL_SetError("Unsupported virtual joystick description version %d", desc->version); + return SDL_SetError("Unsupported virtual joystick description version %u", desc->version); } hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); From 1fcc75ba8131acb5fa25ecb17a6ff5c77a666b8b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:47:10 -0800 Subject: [PATCH 516/725] Fixed warning C6340: Mismatch on sign: 'unsigned char' passed as _Param_(4) when some signed type is required in call to 'SDL_snprintf_REAL'. --- src/joystick/SDL_gamepad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index fd07774849e27..66b74cd0027de 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1695,10 +1695,10 @@ static void SDL_PrivateAppendToMappingString(char *mapping_string, SDL_strlcat(mapping_string, ":", mapping_string_len); switch (mapping->kind) { case EMappingKind_Button: - (void)SDL_snprintf(buffer, sizeof(buffer), "b%i", mapping->target); + (void)SDL_snprintf(buffer, sizeof(buffer), "b%u", mapping->target); break; case EMappingKind_Axis: - (void)SDL_snprintf(buffer, sizeof(buffer), "%sa%i%s", + (void)SDL_snprintf(buffer, sizeof(buffer), "%sa%u%s", mapping->half_axis_positive ? "+" : mapping->half_axis_negative ? "-" : "", mapping->target, From 6a736d7766f66040fd4402af8443d742105250b9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:47:59 -0800 Subject: [PATCH 517/725] Fixed warning C6340: Mismatch on sign: 'unsigned char' passed as _Param_(2) when some signed type is required in call to 'SDL_SetError_REAL'. --- src/joystick/hidapi/SDL_hidapi_wii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 423835e623c39..ee8b8ce9868c9 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -272,7 +272,7 @@ static SDL_bool WriteRegister(SDL_DriverWii_Context *ctx, Uint32 address, const return SDL_FALSE; } if (ctx->m_rgucReadBuffer[4]) { - SDL_SetError("Write memory failed: %d", ctx->m_rgucReadBuffer[4]); + SDL_SetError("Write memory failed: %u", ctx->m_rgucReadBuffer[4]); return SDL_FALSE; } } @@ -335,7 +335,7 @@ static SDL_bool ParseExtensionIdentifyResponse(SDL_DriverWii_Context *ctx, Uint1 } if (error) { - SDL_SetError("Failed to read extension type: %d", error); + SDL_SetError("Failed to read extension type: %u", error); } else { SDL_SetError("Unexpected read length when reading extension type: %d", (ctx->m_rgucReadBuffer[3] >> 4) + 1); } From 8e0d728c67fae5c0b8e97e52bdfbe7d8aabc983b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:49:49 -0800 Subject: [PATCH 518/725] Fixed warning C26451: Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '-' to avoid overflow (io.2). --- src/joystick/hidapi/SDL_hidapi_ps4.c | 2 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 3dc2372137482..e7d76c463724d 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -589,7 +589,7 @@ static SDL_bool HIDAPI_DriverPS4_LoadOfficialCalibrationData(SDL_HIDAPI_Device * SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].scale); #endif /* Some controllers have a bad calibration */ - if (SDL_abs(ctx->calibration[i].bias) > 1024 || SDL_fabs(1.0f - ctx->calibration[i].scale) > 0.5f) { + if (SDL_abs(ctx->calibration[i].bias) > 1024 || SDL_fabsf(1.0f - ctx->calibration[i].scale) > 0.5f) { #ifdef DEBUG_PS4_CALIBRATION SDL_Log("invalid calibration, ignoring\n"); #endif diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index b27f7029ca178..af66d21389995 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -629,7 +629,7 @@ static void HIDAPI_DriverPS5_LoadCalibrationData(SDL_HIDAPI_Device *device) SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].sensitivity); #endif /* Some controllers have a bad calibration */ - if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabs(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) { + if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabsf(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) { #ifdef DEBUG_PS5_CALIBRATION SDL_Log("invalid calibration, ignoring\n"); #endif From b8840801cc83eeeb8c0fd0bb7e805c44b22f35ae Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:53:14 -0800 Subject: [PATCH 519/725] Fixed analyze warnings in SDL_xinputhaptic.c warning C6340: Mismatch on sign: 'int' passed as _Param_(4) when some unsigned type is required in call to 'SDL_snprintf_REAL'. warning C6340: Mismatch on sign: 'const unsigned char' passed as _Param_(4) when some signed type is required in call to 'SDL_snprintf_REAL'. warning C26451: Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2). --- src/haptic/windows/SDL_xinputhaptic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index b84c2eadd00fc..b307b31cf1170 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -86,7 +86,7 @@ int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */ { char buf[64]; - (void)SDL_snprintf(buf, sizeof(buf), "XInput Controller #%u", userid + 1); + (void)SDL_snprintf(buf, sizeof(buf), "XInput Controller #%d", 1 + userid); item->name = SDL_strdup(buf); } @@ -196,7 +196,7 @@ static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 us return SDL_SetError("Couldn't create XInput haptic mutex"); } - (void)SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%d", userid); + (void)SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%u", userid); haptic->hwdata->thread = SDL_CreateThreadInternal(SDL_RunXInputHaptic, threadName, 64 * 1024, haptic->hwdata); if (!haptic->hwdata->thread) { @@ -283,7 +283,7 @@ int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, } else if ((!effect->effect.leftright.length) || (!iterations)) { /* do nothing. Effect runs for zero milliseconds. */ } else { - haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations); + haptic->hwdata->stopTicks = SDL_GetTicks() + ((Uint64)effect->effect.leftright.length * iterations); } SDL_UnlockMutex(haptic->hwdata->mutex); return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1; From 91da942b3330d3d5cdba4e185fb13b630ee49ab5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:54:38 -0800 Subject: [PATCH 520/725] Fixed warning C28251: Inconsistent annotation for 'SDL_RWvprintf_REAL': this instance has no annotations. --- src/file/SDL_rwops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 38aad554fb085..371926794307d 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -822,7 +822,7 @@ size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt return bytes; } -size_t SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap) +size_t SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { int size; char *string; From 02a116217d8dcd0ffc47db50d73b354334cd2b7c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:55:34 -0800 Subject: [PATCH 521/725] Fixed Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '-' to avoid overflow (io.2). --- src/events/SDL_mouse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index eb9a863f60ea4..44c732e0fb563 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -799,8 +799,8 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ Uint64 now = SDL_GetTicks(); if (now >= (clickstate->last_timestamp + mouse->double_click_time) || - SDL_fabs(mouse->x - clickstate->last_x) > mouse->double_click_radius || - SDL_fabs(mouse->y - clickstate->last_y) > mouse->double_click_radius) { + SDL_fabs((double)mouse->x - clickstate->last_x) > mouse->double_click_radius || + SDL_fabs((double)mouse->y - clickstate->last_y) > mouse->double_click_radius) { clickstate->click_count = 0; } clickstate->last_timestamp = now; From c484140f568ea066c9b7b2c38eb403ac8b6ebfc6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 21:57:14 -0800 Subject: [PATCH 522/725] Fixed warning C33010: Unchecked lower bound for enum scancode used as index. --- src/events/SDL_keyboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index f01b90a08cec2..408fafa29ae80 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -754,7 +754,7 @@ void SDL_SetKeymap(int start, const SDL_Keycode *keys, int length, SDL_bool send void SDL_SetScancodeName(SDL_Scancode scancode, const char *name) { - if (scancode >= SDL_NUM_SCANCODES) { + if (scancode < 0 || scancode >= SDL_NUM_SCANCODES) { return; } SDL_scancode_names[scancode] = name; @@ -831,7 +831,7 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, SDL_KeyboardFlags flags Uint8 repeat = SDL_FALSE; const Uint8 source = flags & KEYBOARD_SOURCE_MASK; - if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { + if (scancode < 0 || scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { return 0; } From aab7432f5faa7efd5b056b173c0aa15dfa9c1f6b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2023 22:05:35 -0800 Subject: [PATCH 523/725] Fixed analyze warnings for SDL_dynapi_procs.h --- src/dynapi/SDL_dynapi_procs.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 02d9aebae5be0..ac2c219758d6f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -515,7 +515,7 @@ SDL_DYNAPI_PROC(int,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_LogGetOutputFunction,(SDL_LogOutputFunction *a, void **b),(a,b),) SDL_DYNAPI_PROC(SDL_LogPriority,SDL_LogGetPriority,(int a),(a),return) -SDL_DYNAPI_PROC(void,SDL_LogMessageV,(int a, SDL_LogPriority b, const char *c, va_list d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_LogMessageV,(int a, SDL_LogPriority b, SDL_PRINTF_FORMAT_STRING const char *c, va_list d),(a,b,c,d),) SDL_DYNAPI_PROC(void,SDL_LogResetPriorities,(void),(),) SDL_DYNAPI_PROC(void,SDL_LogSetAllPriority,(SDL_LogPriority a),(a),) SDL_DYNAPI_PROC(void,SDL_LogSetOutputFunction,(SDL_LogOutputFunction a, void *b),(a,b),) @@ -860,10 +860,10 @@ SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_vasprintf,(char **a, const char *b, va_list c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_vsnprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, const char *c, va_list d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_vsscanf,(const char *a, const char *b, va_list c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_vswprintf,(wchar_t *a, size_t b, const wchar_t *c, va_list d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_vasprintf,(char **a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_vsnprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF_FORMAT_STRING const char *c, va_list d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_vsscanf,(const char *a, SDL_SCANF_FORMAT_STRING const char *b, va_list c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_vswprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, const wchar_t *c, va_list d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_wcscasecmp,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_wcscmp,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsdup,(const wchar_t *a),(a),return) @@ -963,7 +963,7 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),r SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return) +SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return) SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) From 7ca43995a1dc045e2afeebf8729f1cf5f412fec6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 5 Dec 2023 10:55:29 -0800 Subject: [PATCH 524/725] Fixed warning C4028: formal parameter 1 different from declaration --- src/events/SDL_pen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index 3f545e56ea545..655d729d56e5f 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -112,7 +112,7 @@ static int SDLCALL pen_header_compare(const void *lhs, const void *rhs) return l->id - r->id; } -SDL_Pen *SDL_GetPenPtr(const Uint32 instance_id) +SDL_Pen *SDL_GetPenPtr(Uint32 instance_id) { unsigned int i; @@ -271,7 +271,7 @@ static void pen_sort(void) pen_handler.sorted = SDL_TRUE; } -SDL_Pen *SDL_PenModifyBegin(const Uint32 instance_id) +SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) { SDL_PenID id = { 0 }; const size_t alloc_growth_constant = 1; /* Expect few pens */ From f00ecf5f190feb6db0727b0c93f7a609f70be76d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 5 Dec 2023 11:00:18 -0800 Subject: [PATCH 525/725] Fixed building with older Windows SDK --- src/video/windows/SDL_windowsevents.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 4c2bb0be1e9b2..751b32246d1e6 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -95,6 +95,14 @@ #define TOUCHEVENTF_PEN 0x0040 #endif +#ifndef MAPVK_VK_TO_VSC_EX +#define MAPVK_VK_TO_VSC_EX 4 +#endif + +#ifndef WC_ERR_INVALID_CHARS +#define WC_ERR_INVALID_CHARS 0x00000080 +#endif + #ifndef IS_HIGH_SURROGATE #define IS_HIGH_SURROGATE(x) (((x) >= 0xd800) && ((x) <= 0xdbff)) #endif From e482f00a170c8032db4043bdeb109521e8c4cb33 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 6 Dec 2023 01:32:00 +0300 Subject: [PATCH 526/725] SDL_string.c (SDL_vsscanf): fix gcc build --- src/stdlib/SDL_string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 1456f3656b6e8..192bd3f99163a 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1255,7 +1255,7 @@ static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len) } /* NOLINTNEXTLINE(readability-non-const-parameter) */ -int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2) +int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) { int retval = 0; From ace385a134b3675164fa1e3229e28855e0922d1b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 5 Dec 2023 14:42:31 -0800 Subject: [PATCH 527/725] Revert "Fixed warning C33010: Unchecked lower bound for enum scancode used as index." This reverts commit c484140f568ea066c9b7b2c38eb403ac8b6ebfc6. Fixes clang warning: comparison of unsigned enum expression < 0 is always false [-Wtautological-compare] --- src/events/SDL_keyboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 408fafa29ae80..f01b90a08cec2 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -754,7 +754,7 @@ void SDL_SetKeymap(int start, const SDL_Keycode *keys, int length, SDL_bool send void SDL_SetScancodeName(SDL_Scancode scancode, const char *name) { - if (scancode < 0 || scancode >= SDL_NUM_SCANCODES) { + if (scancode >= SDL_NUM_SCANCODES) { return; } SDL_scancode_names[scancode] = name; @@ -831,7 +831,7 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, SDL_KeyboardFlags flags Uint8 repeat = SDL_FALSE; const Uint8 source = flags & KEYBOARD_SOURCE_MASK; - if (scancode < 0 || scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { + if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { return 0; } From 4fd778119b85626d06e74dbc38c56881a0cd1508 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 25 Oct 2023 15:09:55 -0400 Subject: [PATCH 528/725] video: Implement asynchronous windowing SDL window size, state, and position functions have been considered immediate, with their effects assuming to have taken effect upon successful return of the function. However, several windowing systems handle these requests asynchronously, resulting in the functions blocking until the changes have taken effect, potentially for long periods of time. Additionally, some windowing systems treat these as requests, and can potentially deny or fulfill the request in a manner differently than the application expects, such as not allowing a window to be positioned or sized beyond desktop borders, prohibiting fullscreen, and so on. With these changes, applications can make requests of the window manager that do not block, with the understanding that an associated event will be sent if the request is fulfilled. Currently, size, position, maximize, minimize, and fullscreen calls are handled as asynchronous requests, with events being returned if the request is honored. If the application requires that the change take effect immediately, it can call the new SDL_SyncWindow function, which will attempt to block until the request is fulfilled, or some arbitrary timeout period elapses, the duration of which depends not only on the windowing system, but on the operation requested as well (e.g. a 100ms timeout is fine for most X11 events, but maximizing a window can take considerably longer for some reason). There is also a new hint 'SDL_VIDEO_SYNC_ALL_WINDOW_OPS' that will mimic the old behavior by synchronizing after every window operation with, again, the understanding that using this may result in the associated calls blocking for a relatively long period. The deferred model also results in the window size and position getters not reporting false coordinates anymore, as they only forward what the window manager reports vs allowing applications to set arbitrary values, and fullscreen enter/leave events that were initiated via the window manager update the window state appropriately, where they didn't before. Care was taken to ensure that order of operations is maintained, and that requests are not ignored or dropped. This does require some implicit internal synchronization in the various backends if many requests are made in a short period, as some state and behavior depends on other bits of state that need to be known at that particular point in time, but this isn't something that typical applications will hit, unless they are sending a lot of window state in a short time as the tests do. The automated tests developed to test the previous behavior also resulted in previously undefined behavior being defined and normalized across platforms, particularly when it comes to the sizing and positioning of windows when they are in a fixed-size state, such as maximized or fullscreen. Size and position requests made when the window is not in a movable or resizable state will be deferred until it can be applied, so no requests are lost. These changes fix another long-standing issue with renderers recreating maximized windows, where the original non-maximized size was lost, resulting in the window being restored to the wrong size. All automated video tests pass across all platforms. Overall, the "make a request/get an event" model better reflects how most windowing systems work, and some backends avoid spending significant time blocking while waiting for operations to complete. --- docs/README-migration.md | 15 + include/SDL3/SDL_events.h | 2 + include/SDL3/SDL_hints.h | 19 + include/SDL3/SDL_video.h | 141 +++++- src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/events/SDL_events.c | 2 + src/events/SDL_windowevents.c | 22 + src/render/opengl/SDL_render_gl.c | 1 + src/render/opengles2/SDL_render_gles2.c | 1 + src/test/SDL_test_common.c | 9 + src/video/SDL_sysvideo.h | 43 +- src/video/SDL_video.c | 461 +++++++++-------- src/video/android/SDL_androidvideo.c | 2 + src/video/android/SDL_androidwindow.c | 3 +- src/video/android/SDL_androidwindow.h | 2 +- src/video/cocoa/SDL_cocoamodes.m | 4 + src/video/cocoa/SDL_cocoavideo.m | 5 +- src/video/cocoa/SDL_cocoawindow.h | 20 +- src/video/cocoa/SDL_cocoawindow.m | 518 +++++++++++++------- src/video/dummy/SDL_nullvideo.c | 13 + src/video/emscripten/SDL_emscriptenevents.c | 15 +- src/video/emscripten/SDL_emscriptenvideo.c | 30 +- src/video/haiku/SDL_bwindow.cc | 15 +- src/video/haiku/SDL_bwindow.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 4 +- src/video/kmsdrm/SDL_kmsdrmvideo.h | 2 +- src/video/offscreen/SDL_offscreenvideo.c | 1 + src/video/offscreen/SDL_offscreenwindow.c | 5 + src/video/offscreen/SDL_offscreenwindow.h | 1 + src/video/qnx/SDL_qnxvideo.c | 7 +- src/video/uikit/SDL_uikitwindow.h | 2 +- src/video/uikit/SDL_uikitwindow.m | 3 +- src/video/wayland/SDL_waylandvideo.c | 7 +- src/video/wayland/SDL_waylandwindow.c | 495 +++++++++++-------- src/video/wayland/SDL_waylandwindow.h | 27 +- src/video/windows/SDL_windowsevents.c | 53 +- src/video/windows/SDL_windowsvideo.c | 3 +- src/video/windows/SDL_windowswindow.c | 142 ++++-- src/video/windows/SDL_windowswindow.h | 12 +- src/video/winrt/SDL_winrtvideo.cpp | 14 +- src/video/x11/SDL_x11events.c | 104 +++- src/video/x11/SDL_x11modes.c | 11 + src/video/x11/SDL_x11modes.h | 2 + src/video/x11/SDL_x11video.c | 4 +- src/video/x11/SDL_x11window.c | 407 ++++++++------- src/video/x11/SDL_x11window.h | 21 +- test/testautomation_video.c | 514 +++++++++++++++++-- 49 files changed, 2190 insertions(+), 999 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index e6f434701d9f2..3b7a90a2f59a0 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1358,6 +1358,21 @@ The following symbols have been renamed: * SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY * SDL_WINDOW_INPUT_GRABBED => SDL_WINDOW_MOUSE_GRABBED +The following window operations are now considered to be asynchronous requests and should not be assumed to succeed unless +a corresponding event has been received: +* SDL_SetWindowSize() (SDL_EVENT_WINDOW_RESIZED) +* SDL_SetWindowPosition() (SDL_EVENT_WINDOW_MOVED) +* SDL_MinimizeWindow() (SDL_EVENT_WINDOW_MINIMIZED) +* SDL_MaximizeWindow() (SDL_EVENT_WINDOW_MAXIMIZED) +* SDL_RestoreWindow() (SDL_EVENT_WINDOW_RESTORED) +* SDL_SetWindowFullscreen() (SDL_EVENT_WINDOW_ENTER_FULLSCREEN / SDL_EVENT_WINDOW_LEAVE_FULLSCREEN) + +If it is required that operations be applied immediately after one of the preceeding calls, the `SDL_SyncWindow()` function +will attempt to wait until all pending window operations have completed. Be aware that this function can potentially block for +long periods of time, as it may have to wait for window animations to complete. Also note that windowing systems can deny or +not precisely obey these requests (e.g. windows may not be allowed to be larger than the usable desktop space or placed +offscreen), so a corresponding event may never arrive or not contain the expected values. + ## SDL_vulkan.h SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no longer makes the app allocate query/allocate space for the result, instead returning a static const internal string. diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index a49d30cc08ecf..1b9edd2bd8243 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -123,6 +123,8 @@ typedef enum SDL_EVENT_WINDOW_DISPLAY_CHANGED, /**< Window has been moved to display data1 */ SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, /**< Window display scale has been changed */ SDL_EVENT_WINDOW_OCCLUDED, /**< The window has been occluded */ + SDL_EVENT_WINDOW_ENTER_FULLSCREEN, /**< The window has entered fullscreen mode */ + SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, /**< The window has left fullscreen mode */ SDL_EVENT_WINDOW_DESTROYED, /**< The window with the associated ID is being or has been destroyed. If this message is being handled in an event watcher, the window handle is still valid and can still be used to retrieve any userdata associated with the window. Otherwise, the handle has already been destroyed and all resources diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 184dac3fb1e74..f71ed32f80ffa 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1795,6 +1795,25 @@ extern "C" { */ #define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" +/** +* Set whether all window operations will block until complete. +* +* Window systems that run asynchronously may not have the results of window operations that resize or move the window +* applied immediately upon the return of the requesting function. Setting this hint will cause such operations to block +* after every call until the pending operation has completed. Setting this to '1' is the equivalent of calling +* SDL_SyncWindow() after every function call. +* +* Be aware that amount of time spent blocking while waiting for window operations to complete can be quite lengthy, as +* animations may have to complete, which can take upwards of multiple seconds in some cases. +* +* This variable can be set to the following values: +* "0" - Window operations are non-blocking +* "1" - Window operations will block until completed +* +* By default SDL will run in non-blocking mode + */ +#define SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" + /** * A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries * diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 8f9e398bf473b..b6a0e608748cf 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -630,6 +630,15 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * change the window size when the window is not fullscreen, use * SDL_SetWindowSize(). * + * If the window is currently in the fullscreen state, this request is asynchronous + * on some windowing systems and the new mode dimensions may not be applied + * immediately upon the return of this function. If an immediate change is required, + * call SDL_SyncWindow() to block until the changes have taken effect. + * + * When the new mode takes effect, an SDL_EVENT_WINDOW_RESIZED and/or an + * SDL_EVENT_WINDOOW_PIXEL_SIZE_CHANGED event will be emitted with the new + * mode dimensions. + * * \param window the window to affect * \param mode a pointer to the display mode to use, which can be NULL for * desktop mode, or one of the fullscreen modes returned by @@ -641,6 +650,7 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * * \sa SDL_GetWindowFullscreenMode * \sa SDL_SetWindowFullscreen + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreenMode(SDL_Window *window, const SDL_DisplayMode *mode); @@ -1070,7 +1080,27 @@ extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window *window); extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); /** - * Set the position of a window. + * Request that the window's position be set. + * + * If, at the time of this request, the window is in a fixed-size state such as + * maximized, this request may be deferred until the window returns to a resizable + * state. + * + * This can be used to reposition fullscreen-desktop windows onto a different display, + * however, exclusive fullscreen windows are locked to a specific display and can + * only be repositioned programmatically via SDL_SetWindowFullscreenMode(). + * + * On some windowing systems this request is asynchronous and the new coordinates + * may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the changes + * have taken effect. + * + * When the window position changes, an SDL_EVENT_WINDOW_MOVED event will be + * emitted with the window's new coordinates. Note that the new coordinates may + * not match the exact coordinates requested, as some windowing systems can restrict + * the position of the window in certain scenarios (e.g. constraining the position + * so the window is always within desktop bounds). Additionally, as this is just a + * request, it can be denied by the windowing system. * * \param window the window to reposition * \param x the x coordinate of the window, or `SDL_WINDOWPOS_CENTERED` or @@ -1083,12 +1113,16 @@ extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *i * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowPosition + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int y); /** * Get the position of a window. * + * This is the current position of the window as last reported by the windowing + * system. + * * If you do not need the value for one of the positions a NULL may be passed * in the `x` or `y` parameter. * @@ -1105,10 +1139,28 @@ extern DECLSPEC int SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, int *y); /** - * Set the size of a window's client area. + * Request that the size of a window's client area be set. + * + * NULL can safely be passed as the `w` or `h` parameter if the width or + * height value is not desired. * - * This only affects the size of the window when not in fullscreen mode. To - * change the fullscreen mode of a window, use SDL_SetWindowFullscreenMode() + * If, at the time of this request, the window in a fixed-size state, such + * as maximized or fullscreen, the request will be deferred until the window + * exits this state and becomes resizable again. + * + * To change the fullscreen mode of a window, use SDL_SetWindowFullscreenMode() + * + * On some windowing systems, this request is asynchronous and the new window size + * may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the + * changes have taken effect. + * + * When the window size changes, an SDL_EVENT_WINDOW_RESIZED event will be + * emitted with the new window dimensions. Note that the new dimensions may + * not match the exact size requested, as some windowing systems can restrict + * the window size in certain scenarios (e.g. constraining the size of the content + * area to remain within the usable desktop bounds). Additionally, as this is just + * a request, it can be denied by the windowing system. * * \param window the window to change * \param w the width of the window, must be > 0 @@ -1120,6 +1172,7 @@ extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, in * * \sa SDL_GetWindowSize * \sa SDL_SetWindowFullscreenMode + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h); @@ -1363,7 +1416,22 @@ extern DECLSPEC int SDLCALL SDL_HideWindow(SDL_Window *window); extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); /** - * Make a window as large as possible. + * Request that the window be made as large as possible. + * + * Non-resizable windows can't be maximized. The window must have the + * SDL_WINDOW_RESIZABLE flag set, or this will have no effect. + * + * On some windowing systems this request is asynchronous and the new window state + * may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the + * changes have taken effect. + * + * When the window state changes, an SDL_EVENT_WINDOW_MAXIMIZED event will be emitted. + * Note that, as this is just a request, the windowing system can deny the state change. + * + * When maximizing a window, whether the constraints set via SDL_SetWindowMaximumSize() + * are honored depends on the policy of the window manager. Win32 and macOS enforce the + * constraints when maximizing, while X11 and Wayland window managers may vary. * * \param window the window to maximize * \returns 0 on success or a negative error code on failure; call @@ -1373,11 +1441,20 @@ extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); * * \sa SDL_MinimizeWindow * \sa SDL_RestoreWindow + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); /** - * Minimize a window to an iconic representation. + * Request that the window be minimized to an iconic representation. + * + * On some windowing systems this request is asynchronous and the new window state + * may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the + * changes have taken effect. + * + * When the window state changes, an SDL_EVENT_WINDOW_MINIMIZED event will be emitted. + * Note that, as this is just a request, the windowing system can deny the state change. * * \param window the window to minimize * \returns 0 on success or a negative error code on failure; call @@ -1387,11 +1464,20 @@ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); * * \sa SDL_MaximizeWindow * \sa SDL_RestoreWindow + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); /** - * Restore the size and position of a minimized or maximized window. + * Request that the size and position of a minimized or maximized window be restored. + * + * On some windowing systems this request is asynchronous and the new window state + * may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the + * changes have taken effect. + * + * When the window state changes, an SDL_EVENT_WINDOW_RESTORED event will be emitted. + * Note that, as this is just a request, the windowing system can deny the state change. * * \param window the window to restore * \returns 0 on success or a negative error code on failure; call @@ -1401,15 +1487,25 @@ extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); * * \sa SDL_MaximizeWindow * \sa SDL_MinimizeWindow + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); /** - * Set a window's fullscreen state. + * Request that the window's fullscreen state be changed. * * By default a window in fullscreen state uses fullscreen desktop mode, but a * specific display mode can be set using SDL_SetWindowFullscreenMode(). * + * On some windowing systems this request is asynchronous and the new fullscreen + * state may not have have been applied immediately upon the return of this function. + * If an immediate change is required, call SDL_SyncWindow() to block until the + * changes have taken effect. + * + * When the window state changes, an SDL_EVENT_WINDOW_ENTER_FULLSCREEN or + * SDL_EVENT_WINDOW_LEAVE_FULLSCREEN event will be emitted. Note that, as this is + * just a request, it can be denied by the windowing system. + * * \param window the window to change * \param fullscreen SDL_TRUE for fullscreen mode, SDL_FALSE for windowed mode * \returns 0 on success or a negative error code on failure; call @@ -1419,9 +1515,38 @@ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); * * \sa SDL_GetWindowFullscreenMode * \sa SDL_SetWindowFullscreenMode + * \sa SDL_SyncWindow */ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen); +/** + * Block until any pending window state is finalized. + * + * On asynchronous windowing systems, this acts as a synchronization barrier for + * pending window state. It will attempt to wait until any pending window state + * has been applied and is guaranteed to return within finite time. Note that for + * how long it can potentially block depends on the underlying window system, as + * window state changes may involve somewhat lengthy animations that must complete + * before the window is in its final requested state. + * + * On windowing systems where changes are immediate, this does nothing. + * + * \param window the window for which to wait for the pending state to be applied + * \returns 0 on success, a positive value if the operation timed out before the + * window was in the requested state, or a negative error code on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetWindowSize + * \sa SDL_SetWindowPosition + * \sa SDL_SetWindowFullscreen + * \sa SDL_MinimizeWindow + * \sa SDL_MaximizeWindow + * \sa SDL_RestoreWindow + */ +extern DECLSPEC int SDLCALL SDL_SyncWindow(SDL_Window *window); + /** * Return whether the window has a surface associated with it. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 61bf3069149ea..e4747421af624 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -962,6 +962,7 @@ SDL3_0.0.0 { SDL_GetTouchDeviceName; SDL_strnstr; SDL_wcsnstr; + SDL_SyncWindow; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index bc03b31787fd2..25d834ce60362 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -987,3 +987,4 @@ #define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL #define SDL_strnstr SDL_strnstr_REAL #define SDL_wcsnstr SDL_wcsnstr_REAL +#define SDL_SyncWindow SDL_SyncWindow_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index ac2c219758d6f..e6d79cc035bf7 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1012,3 +1012,4 @@ SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 93588772c20ae..ac36e25cc2e77 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -312,6 +312,8 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_CHANGED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_OCCLUDED); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ENTER_FULLSCREEN); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED); #undef SDL_WINDOWEVENT_CASE diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 5a4a235d55d32..268aff882cb66 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -71,6 +71,11 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { window->windowed.x = data1; window->windowed.y = data2; + + if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->state_not_floating) { + window->floating.x = data1; + window->floating.y = data2; + } } if (data1 == window->x && data2 == window->y) { return 0; @@ -82,6 +87,11 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { window->windowed.w = data1; window->windowed.h = data2; + + if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->state_not_floating) { + window->floating.w = data1; + window->floating.h = data2; + } } if (data1 == window->w && data2 == window->h) { SDL_CheckWindowPixelSizeChanged(window); @@ -153,6 +163,18 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, } window->flags |= SDL_WINDOW_OCCLUDED; break; + case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: + if (window->flags & SDL_WINDOW_FULLSCREEN) { + return 0; + } + window->flags |= SDL_WINDOW_FULLSCREEN; + break; + case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + return 0; + } + window->flags &= ~SDL_WINDOW_FULLSCREEN; + break; default: break; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 43c69602b66b8..4d04fa7c816b3 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1777,6 +1777,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); #ifndef SDL_VIDEO_VITA_PVR_OGL + SDL_SyncWindow(window); window_flags = SDL_GetWindowFlags(window); if (!(window_flags & SDL_WINDOW_OPENGL) || profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 2e6d6fb1dce9f..698ec57a486c0 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -2088,6 +2088,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c goto error; } + SDL_SyncWindow(window); window_flags = SDL_GetWindowFlags(window); /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */ diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 966c0c016d336..655a8a86e41b8 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1744,6 +1744,15 @@ static void SDLTest_PrintEvent(const SDL_Event *event) case SDL_EVENT_WINDOW_OCCLUDED: SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " occluded", event->window.windowID); break; + case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: + SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " entered fullscreen", event->window.windowID); + break; + case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: + SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " left fullscreen", event->window.windowID); + break; + case SDL_EVENT_WINDOW_DESTROYED: + SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " destroyed", event->window.windowID); + break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: { char modstr[64]; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index df986bdf87e16..8a8816f8c82e4 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -53,9 +53,27 @@ struct SDL_Window SDL_DisplayID last_fullscreen_exclusive_display; /* The last fullscreen_exclusive display */ SDL_DisplayID last_displayID; - /* Stored position and size for windowed mode */ + /* Stored position and size for the window in the non-fullscreen state, + * including when the window is maximized or tiled. + * + * This is the size and position to which the window should return when + * leaving the fullscreen state. + */ SDL_Rect windowed; + /* Stored position and size for the window in the base 'floating' state; + * when not fullscreen, nor in a state such as maximized or tiled. + * + * This is the size and position to which the window should return when + * it's maximized and SDL_RestoreWindow() is called. + */ + SDL_Rect floating; + + /* Toggle for drivers to indicate that the current window state is + * not floating, but may not have any fixed-size flags (e.g. tiled) + */ + SDL_bool state_not_floating; + /* Whether or not the initial position was defined */ SDL_bool undefined_x; SDL_bool undefined_y; @@ -95,10 +113,9 @@ struct SDL_Window (((W)->flags & SDL_WINDOW_HIDDEN) == 0) && \ (((W)->flags & SDL_WINDOW_MINIMIZED) == 0)) -#define SDL_WINDOW_IS_POPUP(W) \ - ((((W)->flags & SDL_WINDOW_TOOLTIP) != 0) || \ - (((W)->flags & SDL_WINDOW_POPUP_MENU) != 0)) \ - \ +#define SDL_WINDOW_IS_POPUP(W) \ + (((W)->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)) != 0) + /* * Define the SDL display structure. * This corresponds to physical monitors attached to the system. @@ -128,10 +145,10 @@ struct SDL_VideoDisplay /* Video device flags */ typedef enum { - VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED = 0x01, - VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE = 0x02, - VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT = 0x04, -} DeviceQuirkFlags; + VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED = 0x01, + VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT = 0x02, + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS = 0x04 +} DeviceCaps; struct SDL_VideoDevice { @@ -217,7 +234,7 @@ struct SDL_VideoDevice void (*SetWindowBordered)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); void (*SetWindowResizable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); void (*SetWindowAlwaysOnTop)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top); - void (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); + int (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); void *(*GetWindowICCProfile)(SDL_VideoDevice *_this, SDL_Window *window, size_t *size); SDL_DisplayID (*GetDisplayForWindow)(SDL_VideoDevice *_this, SDL_Window *window); void (*SetWindowMouseRect)(SDL_VideoDevice *_this, SDL_Window *window); @@ -230,6 +247,7 @@ struct SDL_VideoDevice void (*OnWindowEnter)(SDL_VideoDevice *_this, SDL_Window *window); int (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); int (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); + int (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window); /* * * */ /* @@ -335,7 +353,7 @@ struct SDL_VideoDevice size_t num_clipboard_mime_types; char *primary_selection_text; SDL_bool setting_display_mode; - Uint32 quirk_flags; + Uint32 device_caps; SDL_SystemTheme system_theme; /* * * */ @@ -469,8 +487,10 @@ extern void SDL_ResetFullscreenDisplayModes(SDL_VideoDisplay *display); extern void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode); extern void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode); extern void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale); +extern int SDL_SetDisplayModeForDisplay(SDL_VideoDisplay *display, SDL_DisplayMode *mode); extern SDL_VideoDisplay *SDL_GetVideoDisplay(SDL_DisplayID display); extern SDL_VideoDisplay *SDL_GetVideoDisplayForWindow(SDL_Window *window); +extern SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window); extern int SDL_GetDisplayIndex(SDL_DisplayID displayID); extern SDL_DisplayData *SDL_GetDisplayDriverData(SDL_DisplayID display); extern SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window); @@ -499,6 +519,7 @@ extern void SDL_OnWindowFocusGained(SDL_Window *window); extern void SDL_OnWindowFocusLost(SDL_Window *window); extern void SDL_OnWindowDisplayChanged(SDL_Window *window); extern void SDL_UpdateWindowGrab(SDL_Window *window); +extern int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen, SDL_bool commit); extern SDL_Window *SDL_GetToplevelForKeyboardFocus(void); extern SDL_bool SDL_ShouldAllowTopmost(void); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 74cd5d50c1c7a..03ad6ffe09291 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -30,6 +30,7 @@ #include "SDL_rect_c.h" #include "SDL_video_c.h" #include "../events/SDL_events_c.h" +#include "../SDL_hints_c.h" #include "../timer/SDL_timer_c.h" #include "SDL_video_capture_c.h" @@ -157,27 +158,39 @@ static VideoBootStrap *bootstrap[] = { #if defined(__MACOS__) && defined(SDL_VIDEO_DRIVER_COCOA) /* Support for macOS fullscreen spaces */ extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window); -extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state); +extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state, SDL_bool blocking); #endif static void SDL_CheckWindowDisplayChanged(SDL_Window *window); static void SDL_CheckWindowDisplayScaleChanged(SDL_Window *window); /* Convenience functions for reading driver flags */ -static SDL_bool ModeSwitchingEmulated(SDL_VideoDevice *_this) +static SDL_bool SDL_ModeSwitchingEmulated(SDL_VideoDevice *_this) { - if (_this->quirk_flags & VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED) { + if (_this->device_caps & VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED) { return SDL_TRUE; } return SDL_FALSE; } -static SDL_bool DisableUnsetFullscreenOnMinimize(SDL_VideoDevice *_this) +static SDL_bool SDL_SendsFullscreenDimensions(SDL_VideoDevice *_this) { - if (_this->quirk_flags & VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE) { - return SDL_TRUE; + return !!(_this->device_caps & VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS); +} + +/* Hint to treat all window ops as synchronous */ +static SDL_bool syncHint; + +static void SDL_SyncHintWatcher(void *userdata, const char *name, const char *oldValue, const char *newValue) +{ + syncHint = SDL_GetStringBoolean(newValue, SDL_FALSE); +} + +static void SDL_SyncIfRequired(SDL_Window *window) +{ + if (syncHint) { + SDL_SyncWindow(window); } - return SDL_FALSE; } /* Support for framebuffer emulation using an accelerated renderer */ @@ -543,6 +556,8 @@ int SDL_VideoInit(const char *driver_name) return SDL_SetError("The video driver did not add any displays"); } + SDL_AddHintCallback(SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS, SDL_SyncHintWatcher, NULL); + /* Disable the screen saver by default. This is a change from <= 2.0.1, but most things using SDL are games or media players; you wouldn't want a screensaver to trigger if you're playing exclusively with a @@ -1203,10 +1218,10 @@ const SDL_DisplayMode *SDL_GetCurrentDisplayMode(SDL_DisplayID displayID) return display->current_mode; } -static int SDL_SetDisplayModeForDisplay(SDL_VideoDisplay *display, SDL_DisplayMode *mode) +int SDL_SetDisplayModeForDisplay(SDL_VideoDisplay *display, SDL_DisplayMode *mode) { /* Mode switching is being emulated per-window; nothing to do and cannot fail. */ - if (ModeSwitchingEmulated(_this)) { + if (SDL_ModeSwitchingEmulated(_this)) { return 0; } @@ -1377,6 +1392,34 @@ static SDL_DisplayID SDL_GetDisplayForWindowPosition(SDL_Window *window) return displayID; } +SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window) +{ + SDL_DisplayID displayID = 0; + + CHECK_WINDOW_MAGIC(window, 0); + + /* An explicit fullscreen display overrides all */ + if (window->current_fullscreen_mode.displayID) { + displayID = window->current_fullscreen_mode.displayID; + } + + /* The floating position is used here as a very common pattern is + * SDL_SetWindowPosition() followed by SDL_SetWindowFullscreen to make the + * window fullscreen desktop on a specific display. If the backend doesn't + * support changing the window position, or the compositor hasn't yet actually + * moved the window, the actual position won't be updated at the time of the + * fullscreen call. + */ + if (!displayID) { + displayID = GetDisplayForRect(window->floating.x, window->floating.y, window->w, window->h); + } + if (!displayID) { + /* Use the primary display for a window if we can't find it anywhere else */ + displayID = SDL_GetPrimaryDisplay(); + } + return SDL_GetVideoDisplay(displayID); +} + SDL_DisplayID SDL_GetDisplayForWindow(SDL_Window *window) { SDL_DisplayID displayID = 0; @@ -1479,7 +1522,7 @@ static void SDL_RestoreMousePosition(SDL_Window *window) } } -static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) +int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen, SDL_bool commit) { SDL_VideoDisplay *display = NULL; SDL_DisplayMode *mode = NULL; @@ -1496,7 +1539,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) /* Get the correct display for this operation */ if (fullscreen) { - display = SDL_GetVideoDisplayForWindow(window); + display = SDL_GetVideoDisplayForFullscreenWindow(window); if (!display) { /* This should never happen, but it did... */ goto done; @@ -1510,7 +1553,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) } if (!display || i == _this->num_displays) { /* Already not fullscreen on any display */ - goto done; + display = NULL; } } @@ -1531,38 +1574,33 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) if (SDL_strcmp(_this->name, "cocoa") == 0) { /* don't do this for X11, etc */ if (window->is_destroying && !window->last_fullscreen_exclusive_display) { window->fullscreen_exclusive = SDL_FALSE; - display->fullscreen_window = NULL; + if (display) { + display->fullscreen_window = NULL; + } goto done; } - - /* If we're switching between a fullscreen Space and exclusive fullscreen, we need to get back to normal first. */ - if (fullscreen && !window->last_fullscreen_exclusive_display && window->fullscreen_exclusive) { - if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE)) { - goto error; - } - } else if (fullscreen && window->last_fullscreen_exclusive_display && !window->fullscreen_exclusive) { - for (i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *last_display = _this->displays[i]; - if (last_display->fullscreen_window == window) { - SDL_SetDisplayModeForDisplay(last_display, NULL); - if (_this->SetWindowFullscreen) { - _this->SetWindowFullscreen(_this, window, last_display, SDL_FALSE); + if (commit) { + /* If we're switching between a fullscreen Space and exclusive fullscreen, we need to get back to normal first. */ + if (fullscreen && Cocoa_IsWindowInFullscreenSpace(window) && !window->last_fullscreen_exclusive_display && window->fullscreen_exclusive) { + if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE, SDL_TRUE)) { + goto error; + } + } else if (fullscreen && window->last_fullscreen_exclusive_display && !window->fullscreen_exclusive) { + for (i = 0; i < _this->num_displays; ++i) { + SDL_VideoDisplay *last_display = _this->displays[i]; + if (last_display->fullscreen_window == window) { + SDL_SetDisplayModeForDisplay(last_display, NULL); + if (_this->SetWindowFullscreen) { + _this->SetWindowFullscreen(_this, window, last_display, SDL_FALSE); + } + last_display->fullscreen_window = NULL; } - last_display->fullscreen_window = NULL; } } - } - if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) { - if (Cocoa_IsWindowInFullscreenSpace(window) != fullscreen) { - goto error; - } - if (fullscreen) { - display->fullscreen_window = window; - } else { - display->fullscreen_window = NULL; + if (Cocoa_SetWindowFullscreenSpace(window, fullscreen, syncHint)) { + goto done; } - goto done; } } #elif defined(__WINRT__) && (NTDDI_VERSION < NTDDI_WIN10) @@ -1596,15 +1634,14 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) } #endif - /* Restore the video mode on other displays if needed */ - for (i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *other = _this->displays[i]; - if (other != display && other->fullscreen_window == window) { - SDL_SetDisplayModeForDisplay(other, NULL); - if (_this->SetWindowFullscreen) { - _this->SetWindowFullscreen(_this, window, other, SDL_FALSE); + if (display) { + /* Restore the video mode on other displays if needed */ + for (i = 0; i < _this->num_displays; ++i) { + SDL_VideoDisplay *other = _this->displays[i]; + if (other != display && other->fullscreen_window == window) { + SDL_SetDisplayModeForDisplay(other, NULL); + other->fullscreen_window = NULL; } - other->fullscreen_window = NULL; } } @@ -1621,75 +1658,109 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen) if (SDL_SetDisplayModeForDisplay(display, mode) < 0) { goto error; } - if (_this->SetWindowFullscreen) { - _this->SetWindowFullscreen(_this, window, display, SDL_TRUE); - } else { - resized = SDL_TRUE; - } - display->fullscreen_window = window; + if (commit) { + int ret = 0; + if (_this->SetWindowFullscreen) { + ret = _this->SetWindowFullscreen(_this, window, display, SDL_TRUE); + } else { + resized = SDL_TRUE; + } - if (mode) { - mode_w = mode->w; - mode_h = mode->h; - } else { - mode_w = display->desktop_mode.w; - mode_h = display->desktop_mode.h; - } -#ifdef __ANDROID__ - /* Android may not resize the window to exactly what our fullscreen mode is, - * especially on windowed Android environments like the Chromebook or Samsung DeX. - * Given this, we shouldn't use the mode size. Android's SetWindowFullscreen - * will generate the window event for us with the proper final size. - */ -#elif defined(__WIN32__) - /* This is also unnecessary on Win32 (WIN_SetWindowFullscreen calls SetWindowPos, - * WM_WINDOWPOSCHANGED will send SDL_EVENT_WINDOW_RESIZED). - */ -#else - if (window->w != mode_w || window->h != mode_h) { - resized = SDL_TRUE; - } -#endif - if (resized) { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode_w, mode_h); - } else { - SDL_OnWindowResized(window); + if (ret == 0) { + /* Window is fullscreen immediately upon return. If the driver hasn't already sent the event, do so now. */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); + } + } else if (ret < 0) { + goto error; + } } - /* Restore the cursor position */ - SDL_RestoreMousePosition(window); + if (window->flags & SDL_WINDOW_FULLSCREEN) { + display->fullscreen_window = window; + + /* Android may not resize the window to exactly what our fullscreen mode is, + * especially on windowed Android environments like the Chromebook or Samsung DeX. + * Given this, we shouldn't use the mode size. Android's SetWindowFullscreen + * will generate the window event for us with the proper final size. + * + * This is also unnecessary on Cocoa, Wayland, Win32, and X11 (will send SDL_EVENT_WINDOW_RESIZED). + */ + if (!SDL_SendsFullscreenDimensions(_this)) { + if (mode) { + mode_w = mode->w; + mode_h = mode->h; + } else { + mode_w = display->desktop_mode.w; + mode_h = display->desktop_mode.h; + } + + if (window->w != mode_w || window->h != mode_h) { + resized = SDL_TRUE; + } + if (resized) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode_w, mode_h); + } else { + SDL_OnWindowResized(window); + } + } + + /* Restore the cursor position */ + SDL_RestoreMousePosition(window); + } } else { SDL_bool resized = SDL_FALSE; /* Restore the desktop mode */ - SDL_SetDisplayModeForDisplay(display, NULL); - if (_this->SetWindowFullscreen) { - _this->SetWindowFullscreen(_this, window, display, SDL_FALSE); - } else { - resized = SDL_TRUE; + if (display) { + SDL_SetDisplayModeForDisplay(display, NULL); } - display->fullscreen_window = NULL; + if (commit) { + int ret = 0; + if (_this->SetWindowFullscreen) { + ret = _this->SetWindowFullscreen(_this, window, display ? display : SDL_GetVideoDisplayForFullscreenWindow(window), SDL_FALSE); + } else { + resized = SDL_TRUE; + } - if (resized) { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->windowed.w, window->windowed.h); - } else { - SDL_OnWindowResized(window); + if (ret == 0) { + /* Window left fullscreen immediately upon return. If the driver hasn't already sent the event, do so now. */ + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + } + } else if (ret < 0) { + goto error; + } } - /* Restore the cursor position */ - SDL_RestoreMousePosition(window); + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + if (display) { + display->fullscreen_window = NULL; + } + + if (!SDL_SendsFullscreenDimensions(_this)) { + if (resized) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->windowed.w, window->windowed.h); + } else { + SDL_OnWindowResized(window); + } + } + + /* Restore the cursor position */ + SDL_RestoreMousePosition(window); + } } done: - window->last_fullscreen_exclusive_display = display && window->fullscreen_exclusive ? display->id : 0; + window->last_fullscreen_exclusive_display = display && (window->flags & SDL_WINDOW_FULLSCREEN) && window->fullscreen_exclusive ? display->id : 0; + SDL_SyncIfRequired(window); return 0; error: if (fullscreen) { /* Something went wrong and the window is no longer fullscreen. */ - window->flags &= ~SDL_WINDOW_FULLSCREEN; - SDL_UpdateFullscreenMode(window, SDL_FALSE); + SDL_UpdateFullscreenMode(window, SDL_FALSE, commit); } return -1; } @@ -1705,16 +1776,18 @@ int SDL_SetWindowFullscreenMode(SDL_Window *window, const SDL_DisplayMode *mode) } /* Save the mode so we can look up the closest match later */ - SDL_memcpy(&window->requested_fullscreen_mode, mode, sizeof(window->requested_fullscreen_mode)); + SDL_copyp(&window->requested_fullscreen_mode, mode); } else { SDL_zero(window->requested_fullscreen_mode); } - if (window->flags & SDL_WINDOW_FULLSCREEN) { - SDL_memcpy(&window->current_fullscreen_mode, &window->requested_fullscreen_mode, sizeof(window->current_fullscreen_mode)); - if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - SDL_UpdateFullscreenMode(window, SDL_TRUE); - } + /* Copy to the current mode now, in case an asynchronous fullscreen window request + * is in progress. It will be overwritten if a new request is made. + */ + SDL_copyp(&window->current_fullscreen_mode, &window->requested_fullscreen_mode); + if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_TRUE); + SDL_SyncIfRequired(window); } return 0; @@ -1790,17 +1863,18 @@ void SDL_ToggleDragAndDropSupport(void) static void ApplyWindowFlags(SDL_Window *window, Uint32 flags) { + if (!(flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) { + SDL_RestoreWindow(window); + } if (flags & SDL_WINDOW_MAXIMIZED) { SDL_MaximizeWindow(window); } + + SDL_SetWindowFullscreen(window, (flags & SDL_WINDOW_FULLSCREEN) != 0); + if (flags & SDL_WINDOW_MINIMIZED) { SDL_MinimizeWindow(window); } - if (!(flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) { - SDL_RestoreWindow(window); - } - - SDL_SetWindowFullscreen(window, (flags & SDL_WINDOW_FULLSCREEN) != 0); if (flags & SDL_WINDOW_MOUSE_GRABBED) { /* We must specifically call SDL_SetWindowGrab() and not @@ -1908,7 +1982,7 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) } if ((flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)) != 0) { - if (!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT)) { + if (!(_this->device_caps & VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT)) { SDL_Unsupported(); return NULL; } @@ -2018,10 +2092,10 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) } window->magic = &_this->window_magic; window->id = SDL_GetNextObjectID(); - window->windowed.x = window->x = x; - window->windowed.y = window->y = y; - window->windowed.w = window->w = w; - window->windowed.h = window->h = h; + window->floating.x = window->windowed.x = window->x = x; + window->floating.y = window->windowed.y = window->y = y; + window->floating.w = window->windowed.w = window->w = w; + window->floating.h = window->windowed.h = window->h = h; window->undefined_x = undefined_x; window->undefined_y = undefined_y; @@ -2089,11 +2163,6 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) } SDL_FinishWindowCreation(window, flags); - /* If the window was created fullscreen, make sure the display mode matches */ - if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - SDL_UpdateFullscreenMode(window, SDL_TRUE); - } - /* Make sure window pixel size is up to date */ SDL_CheckWindowPixelSizeChanged(window); @@ -2238,6 +2307,14 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags) window->is_destroying = SDL_FALSE; if (_this->CreateSDLWindow && !(flags & SDL_WINDOW_EXTERNAL)) { + /* Reset the window size to the original floating value, so the + * recreated window has the proper base size. + */ + window->x = window->windowed.x = window->floating.x; + window->y = window->windowed.y = window->floating.y; + window->w = window->windowed.w = window->floating.w; + window->h = window->windowed.h = window->floating.h; + if (_this->CreateSDLWindow(_this, window, 0) < 0) { if (loaded_opengl) { SDL_GL_UnloadLibrary(); @@ -2320,7 +2397,7 @@ Uint32 SDL_GetWindowFlags(SDL_Window *window) { CHECK_WINDOW_MAGIC(window, 0); - return window->flags; + return window->flags | window->pending_flags; } int SDL_SetWindowTitle(SDL_Window *window, const char *title) @@ -2410,31 +2487,19 @@ int SDL_SetWindowPosition(SDL_Window *window, int x, int y) } } - window->windowed.x = x; - window->windowed.y = y; + window->floating.x = x; + window->floating.y = y; window->undefined_x = SDL_FALSE; window->undefined_y = SDL_FALSE; - if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - if (!window->fullscreen_exclusive) { - /* See if we should move to another display */ - SDL_DisplayID displayID = GetDisplayForRect(x, y, 1, 1); - - if (displayID != original_displayID) { - /* Set the new target display and update the fullscreen mode */ - window->current_fullscreen_mode.displayID = displayID; - return SDL_UpdateFullscreenMode(window, SDL_TRUE); - } - } - } else { - window->x = x; - window->y = y; - window->last_displayID = SDL_GetDisplayForWindow(window); - - if (_this->SetWindowPosition) { - return _this->SetWindowPosition(_this, window); + if (_this->SetWindowPosition) { + const int ret = _this->SetWindowPosition(_this, window); + if (!ret) { + SDL_SyncIfRequired(window); } + return ret; } + return SDL_Unsupported(); } @@ -2511,6 +2576,7 @@ int SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable) window->flags |= SDL_WINDOW_RESIZABLE; } else { window->flags &= ~SDL_WINDOW_RESIZABLE; + SDL_copyp(&window->windowed, &window->floating); } _this->SetWindowResizable(_this, window, want); } @@ -2561,16 +2627,14 @@ int SDL_SetWindowSize(SDL_Window *window, int w, int h) h = window->max_h; } - window->windowed.w = w; - window->windowed.h = h; - - if (!SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - window->w = w; - window->h = h; + window->floating.w = w; + window->floating.h = h; - if (_this->SetWindowSize) { - _this->SetWindowSize(_this, window); - } + if (_this->SetWindowSize) { + _this->SetWindowSize(_this, window); + SDL_SyncIfRequired(window); + } else { + return SDL_Unsupported(); } return 0; } @@ -2677,8 +2741,8 @@ int SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h) } /* Ensure that window is not smaller than minimal size */ - w = window->min_w ? SDL_max(window->w, window->min_w) : window->w; - h = window->min_h ? SDL_max(window->h, window->min_h) : window->h; + w = window->min_w ? SDL_max(window->floating.w, window->min_w) : window->floating.w; + h = window->min_h ? SDL_max(window->floating.h, window->min_h) : window->floating.h; return SDL_SetWindowSize(window, w, h); } return 0; @@ -2721,8 +2785,8 @@ int SDL_SetWindowMaximumSize(SDL_Window *window, int max_w, int max_h) } /* Ensure that window is not larger than maximal size */ - w = window->max_w ? SDL_min(window->w, window->max_w) : window->w; - h = window->max_h ? SDL_min(window->h, window->max_h) : window->h; + w = window->max_w ? SDL_min(window->floating.w, window->max_w) : window->floating.w; + h = window->max_h ? SDL_min(window->floating.h, window->max_h) : window->floating.h; return SDL_SetWindowSize(window, w, h); } return 0; @@ -2763,10 +2827,6 @@ int SDL_ShowWindow(SDL_Window *window) } SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); - /* Set window state if we have pending window flags cached */ - ApplyWindowFlags(window, window->pending_flags); - window->pending_flags = 0; - /* Restore child windows */ for (child = window->first_child; child; child = child->next_sibling) { if (!child->restore_on_show && (child->flags & SDL_WINDOW_HIDDEN)) { @@ -2830,8 +2890,12 @@ int SDL_MaximizeWindow(SDL_Window *window) CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (window->flags & SDL_WINDOW_MAXIMIZED) { - return 0; + if (!_this->MaximizeWindow) { + return SDL_Unsupported(); + } + + if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + return SDL_SetError("A window without the 'SDL_WINDOW_RESIZABLE' flag can't be maximized"); } if (window->flags & SDL_WINDOW_HIDDEN) { @@ -2839,29 +2903,18 @@ int SDL_MaximizeWindow(SDL_Window *window) return 0; } - /* !!! FIXME: should this check if the window is resizable? */ - - if (_this->MaximizeWindow) { - _this->MaximizeWindow(_this, window); - } + _this->MaximizeWindow(_this, window); + SDL_SyncIfRequired(window); return 0; } -static SDL_bool SDL_CanMinimizeWindow(SDL_Window *window) -{ - if (!_this->MinimizeWindow || SDL_WINDOW_IS_POPUP(window)) { - return SDL_FALSE; - } - return SDL_TRUE; -} - int SDL_MinimizeWindow(SDL_Window *window) { CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (window->flags & SDL_WINDOW_MINIMIZED) { - return 0; + if (!_this->MinimizeWindow) { + return SDL_Unsupported(); } if (window->flags & SDL_WINDOW_HIDDEN) { @@ -2869,17 +2922,8 @@ int SDL_MinimizeWindow(SDL_Window *window) return 0; } - if (!SDL_CanMinimizeWindow(window)) { - return 0; - } - - if (!DisableUnsetFullscreenOnMinimize(_this)) { - SDL_UpdateFullscreenMode(window, SDL_FALSE); - } - - if (_this->MinimizeWindow) { - _this->MinimizeWindow(_this, window); - } + _this->MinimizeWindow(_this, window); + SDL_SyncIfRequired(window); return 0; } @@ -2888,8 +2932,8 @@ int SDL_RestoreWindow(SDL_Window *window) CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { - return 0; + if (!_this->RestoreWindow) { + return SDL_Unsupported(); } if (window->flags & SDL_WINDOW_HIDDEN) { @@ -2897,16 +2941,14 @@ int SDL_RestoreWindow(SDL_Window *window) return 0; } - if (_this->RestoreWindow) { - _this->RestoreWindow(_this, window); - } + _this->RestoreWindow(_this, window); + SDL_SyncIfRequired(window); return 0; } int SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) { int ret = 0; - Uint32 flags = fullscreen ? SDL_WINDOW_FULLSCREEN : 0; CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); @@ -2920,19 +2962,12 @@ int SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) return 0; } - if (flags == (window->flags & SDL_WINDOW_FULLSCREEN)) { - return 0; - } - - /* Clear the previous flags and OR in the new ones */ - window->flags = (window->flags & ~SDL_WINDOW_FULLSCREEN) | flags; - if (fullscreen) { /* Set the current fullscreen mode to the desired mode */ - SDL_memcpy(&window->current_fullscreen_mode, &window->requested_fullscreen_mode, sizeof(window->current_fullscreen_mode)); + SDL_copyp(&window->current_fullscreen_mode, &window->requested_fullscreen_mode); } - ret = SDL_UpdateFullscreenMode(window, SDL_WINDOW_FULLSCREEN_VISIBLE(window)); + ret = SDL_UpdateFullscreenMode(window, fullscreen, SDL_TRUE); if (!fullscreen || ret != 0) { /* Clear the current fullscreen mode. */ @@ -2942,6 +2977,17 @@ int SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) return ret; } +int SDL_SyncWindow(SDL_Window *window) +{ + CHECK_WINDOW_MAGIC(window, -1) + + if (_this->SyncWindow) { + return _this->SyncWindow(_this, window); + } + + return 0; +} + static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window) { Uint32 format = 0; @@ -3346,12 +3392,15 @@ int SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation) void SDL_OnWindowShown(SDL_Window *window) { - SDL_OnWindowRestored(window); + /* Set window state if we have pending window flags cached */ + ApplyWindowFlags(window, window->pending_flags); + window->pending_flags = 0; } void SDL_OnWindowHidden(SDL_Window *window) { - SDL_UpdateFullscreenMode(window, SDL_FALSE); + /* The window is already hidden at this point, so just change the mode back if necessary. */ + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_FALSE); } void SDL_OnWindowDisplayChanged(SDL_Window *window) @@ -3370,13 +3419,13 @@ void SDL_OnWindowDisplayChanged(SDL_Window *window) } if (new_mode) { - SDL_memcpy(&window->current_fullscreen_mode, new_mode, sizeof(window->current_fullscreen_mode)); + SDL_copyp(&window->current_fullscreen_mode, new_mode); } else { SDL_zero(window->current_fullscreen_mode); } if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - SDL_UpdateFullscreenMode(window, SDL_TRUE); + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_TRUE); } } @@ -3411,8 +3460,8 @@ void SDL_OnWindowPixelSizeChanged(SDL_Window *window) void SDL_OnWindowMinimized(SDL_Window *window) { - if (!DisableUnsetFullscreenOnMinimize(_this)) { - SDL_UpdateFullscreenMode(window, SDL_FALSE); + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_FALSE); } } @@ -3430,8 +3479,8 @@ void SDL_OnWindowRestored(SDL_Window *window) */ /*SDL_RaiseWindow(window);*/ - if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) { - SDL_UpdateFullscreenMode(window, SDL_TRUE); + if (window->flags & SDL_WINDOW_FULLSCREEN) { + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_FALSE); } } @@ -3488,7 +3537,7 @@ static SDL_bool SDL_ShouldMinimizeOnFocusLoss(SDL_Window *window) /* Real fullscreen windows should minimize on focus loss so the desktop video mode is restored */ hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS); if (!hint || !*hint || SDL_strcasecmp(hint, "auto") == 0) { - if (window->fullscreen_exclusive && !ModeSwitchingEmulated(_this)) { + if (window->fullscreen_exclusive && !SDL_ModeSwitchingEmulated(_this)) { return SDL_TRUE; } else { return SDL_FALSE; @@ -3548,7 +3597,7 @@ void SDL_DestroyWindow(SDL_Window *window) } /* Restore video mode, etc. */ - SDL_UpdateFullscreenMode(window, SDL_FALSE); + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_TRUE); if (!(window->flags & SDL_WINDOW_EXTERNAL)) { SDL_HideWindow(window); } diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index e9b42a64dd240..f5f31d739b1a4 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -155,6 +155,8 @@ static SDL_VideoDevice *Android_CreateDevice(void) device->GetClipboardText = Android_GetClipboardText; device->HasClipboardText = Android_HasClipboardText; + device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; + return device; } diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index c33a5ceef04c5..0ad5acf2ebf43 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -105,7 +105,7 @@ void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) Android_JNI_SetActivityTitle(window->title); } -void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { SDL_LockMutex(Android_ActivityMutex); @@ -154,6 +154,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL endfunction: SDL_UnlockMutex(Android_ActivityMutex); + return 0; } void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) diff --git a/src/video/android/SDL_androidwindow.h b/src/video/android/SDL_androidwindow.h index bbe2e4f1da249..5336f912a1c1e 100644 --- a/src/video/android/SDL_androidwindow.h +++ b/src/video/android/SDL_androidwindow.h @@ -28,7 +28,7 @@ extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); -extern void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); diff --git a/src/video/cocoa/SDL_cocoamodes.m b/src/video/cocoa/SDL_cocoamodes.m index 34e9c2d5b0c6f..fd58f8ef6f2a8 100644 --- a/src/video/cocoa/SDL_cocoamodes.m +++ b/src/video/cocoa/SDL_cocoamodes.m @@ -489,6 +489,8 @@ int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_ CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; CGError result = kCGErrorSuccess; + b_inModeTransition = SDL_TRUE; + /* Fade to black to hide resolution-switching flicker */ if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) { CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); @@ -508,6 +510,8 @@ int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_ CGReleaseDisplayFadeReservation(fade_token); } + b_inModeTransition = SDL_FALSE; + if (result != kCGErrorSuccess) { CG_SetError("CGDisplaySwitchToMode()", result); return -1; diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 588d9e8c7b359..e115724e90d7c 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -116,6 +116,7 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop; device->FlashWindow = Cocoa_FlashWindow; device->SetWindowFocusable = Cocoa_SetWindowFocusable; + device->SyncWindow = Cocoa_SyncWindow; #ifdef SDL_VIDEO_OPENGL_CGL device->GL_LoadLibrary = Cocoa_GL_LoadLibrary; @@ -171,8 +172,8 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device) device->free = Cocoa_DeleteDevice; - device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT; - + device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; return device; } } diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index d422f52c3de74..1adf6d657784a 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -35,10 +35,10 @@ typedef enum { - PENDING_OPERATION_NONE, - PENDING_OPERATION_ENTER_FULLSCREEN, - PENDING_OPERATION_LEAVE_FULLSCREEN, - PENDING_OPERATION_MINIMIZE + PENDING_OPERATION_NONE = 0x00, + PENDING_OPERATION_ENTER_FULLSCREEN = 0x01, + PENDING_OPERATION_LEAVE_FULLSCREEN = 0x02, + PENDING_OPERATION_MINIMIZE = 0x04 } PendingWindowOperation; @interface Cocoa_WindowListener : NSResponder @@ -54,6 +54,7 @@ typedef enum BOOL inFullscreenTransition; PendingWindowOperation pendingWindowOperation; BOOL isMoving; + BOOL isMiniaturizing; NSInteger focusClickPending; float pendingWindowWarpX, pendingWindowWarpY; BOOL isDragAreaRunning; @@ -130,17 +131,23 @@ typedef enum @property(nonatomic) NSView *sdlContentView; @property(nonatomic) NSMutableArray *nscontexts; @property(nonatomic) SDL_bool created; -@property(nonatomic) SDL_bool inWindowFullscreenTransition; +@property(nonatomic) BOOL in_blocking_transition; +@property(nonatomic) BOOL was_zoomed; @property(nonatomic) NSInteger window_number; @property(nonatomic) NSInteger flash_request; @property(nonatomic) SDL_Window *keyboard_focus; @property(nonatomic) Cocoa_WindowListener *listener; @property(nonatomic) SDL_CocoaVideoData *videodata; +@property(nonatomic) SDL_bool send_floating_size; +@property(nonatomic) SDL_bool send_floating_position; +@property(nonatomic) BOOL checking_zoom; #ifdef SDL_VIDEO_OPENGL_EGL @property(nonatomic) EGLSurface egl_surface; #endif @end +extern SDL_bool b_inModeTransition; + extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern int Cocoa_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); @@ -159,7 +166,7 @@ extern void Cocoa_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); extern void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); extern void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top); -extern void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void *Cocoa_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size); extern SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); @@ -169,5 +176,6 @@ extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept); extern int Cocoa_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); extern int Cocoa_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); +extern int Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_cocoawindow_h_ */ diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index debb76fdc3c66..7c49a69de0f2d 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -26,20 +26,19 @@ #error SDL for macOS must be built with a 10.9 SDK or above. #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1090 */ -#include /* For FLT_MAX */ +#include /* For FLT_MAX */ -#include "../SDL_sysvideo.h" +#include "../../events/SDL_dropevents_c.h" #include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_touch_c.h" #include "../../events/SDL_windowevents_c.h" -#include "../../events/SDL_dropevents_c.h" +#include "../SDL_sysvideo.h" -#include "SDL_cocoavideo.h" #include "SDL_cocoamouse.h" #include "SDL_cocoaopengl.h" #include "SDL_cocoaopengles.h" - +#include "SDL_cocoavideo.h" /* #define DEBUG_COCOAWINDOW */ @@ -275,7 +274,7 @@ - (SDL_Window *)findSDLWindow @end -static Uint64 s_moveHack; +SDL_bool b_inModeTransition; static CGFloat SqDistanceToRect(const NSPoint *point, const NSRect *rect) { @@ -300,7 +299,8 @@ static CGFloat SqDistanceToRect(const NSPoint *point, const NSRect *rect) return delta.x * delta.x + delta.y * delta.y; } -static NSScreen *ScreenForPoint(const NSPoint *point) { +static NSScreen *ScreenForPoint(const NSPoint *point) +{ NSScreen *screen; /* Do a quick check first to see if the point lies on a specific screen*/ @@ -328,7 +328,8 @@ static CGFloat SqDistanceToRect(const NSPoint *point, const NSRect *rect) return screen; } -static NSScreen *ScreenForRect(const NSRect *rect) { +static NSScreen *ScreenForRect(const NSRect *rect) +{ NSPoint center = NSMakePoint(NSMidX(*rect), NSMidY(*rect)); return ScreenForPoint(¢er); } @@ -548,7 +549,7 @@ static void Cocoa_UpdateClipCursor(SDL_Window *window) static void Cocoa_SetKeyboardFocus(SDL_Window *window) { SDL_Window *topmost = window; - SDL_CocoaWindowData* topmost_data; + SDL_CocoaWindowData *topmost_data; /* Find the topmost parent */ while (topmost->parent != NULL) { @@ -562,12 +563,37 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window) static void Cocoa_SendExposedEventIfVisible(SDL_Window *window) { - NSWindow *nswindow = ((__bridge SDL_CocoaWindowData*)window->driverdata).nswindow; + NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; if ([nswindow occlusionState] & NSWindowOcclusionStateVisible) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); } } +static void Cocoa_WaitForMiniaturizable(SDL_Window *window) +{ + NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; + NSButton *button = [nswindow standardWindowButton:NSWindowMiniaturizeButton]; + if (button) { + int iterations = 0; + while (![button isEnabled] && (iterations < 100)) { + SDL_Delay(10); + SDL_PumpEvents(); + iterations++; + } + } +} + +static SDL_bool Cocoa_IsZoomed(SDL_Window *window) +{ + SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; + + data.checking_zoom = YES; + const SDL_bool ret = [data.nswindow isZoomed]; + data.checking_zoom = NO; + + return ret; +} + @implementation Cocoa_WindowListener - (void)listen:(SDL_CocoaWindowData *)data @@ -584,6 +610,7 @@ - (void)listen:(SDL_CocoaWindowData *)data inFullscreenTransition = NO; pendingWindowOperation = PENDING_OPERATION_NONE; isMoving = NO; + isMiniaturizing = NO; isDragAreaRunning = NO; pendingWindowWarpX = pendingWindowWarpY = FLT_MAX; @@ -591,8 +618,10 @@ - (void)listen:(SDL_CocoaWindowData *)data if ([window delegate] != nil) { [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window]; + [center addObserver:self selector:@selector(windowWillMove:) name:NSWindowWillMoveNotification object:window]; [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window]; [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window]; + [center addObserver:self selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification object:window]; [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window]; [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window]; [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window]; @@ -710,9 +739,25 @@ - (BOOL)isInFullscreenSpaceTransition return inFullscreenTransition; } +- (void)clearPendingWindowOperation:(PendingWindowOperation)operation +{ + pendingWindowOperation &= ~operation; +} + - (void)addPendingWindowOperation:(PendingWindowOperation)operation { - pendingWindowOperation = operation; + pendingWindowOperation |= operation; +} + +- (BOOL)windowOperationIsPending:(PendingWindowOperation)operation +{ + return !!(pendingWindowOperation & operation); +} + +- (BOOL)hasPendingWindowOperation +{ + return pendingWindowOperation != PENDING_OPERATION_NONE || + isMiniaturizing || inFullscreenTransition; } - (void)close @@ -725,8 +770,10 @@ - (void)close if ([window delegate] != self) { [center removeObserver:self name:NSWindowDidExposeNotification object:window]; + [center removeObserver:self name:NSWindowWillMoveNotification object:window]; [center removeObserver:self name:NSWindowDidMoveNotification object:window]; [center removeObserver:self name:NSWindowDidResizeNotification object:window]; + [center removeObserver:self name:NSWindowWillMiniaturizeNotification object:window]; [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window]; [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window]; [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window]; @@ -862,27 +909,11 @@ - (void)windowDidMove:(NSNotification *)aNotification NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]]; ConvertNSRect(fullscreen, &rect); - if (inFullscreenTransition) { + if (inFullscreenTransition || b_inModeTransition) { /* We'll take care of this at the end of the transition */ return; } - if (s_moveHack) { - SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500); - - s_moveHack = 0; - - if (blockMove) { - /* Cocoa is adjusting the window in response to a mode change */ - SDL_RelativeToGlobalForWindow(window, window->x, window->y, &x, &y ); - rect.origin.x = x; - rect.origin.y = y; - ConvertNSRect(fullscreen, &rect); - [nswindow setFrameOrigin:rect.origin]; - return; - } - } - x = (int)rect.origin.x; y = (int)rect.origin.y; @@ -893,6 +924,34 @@ - (void)windowDidMove:(NSNotification *)aNotification SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); } +- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize +{ + SDL_Window *window = _data.window; + + /* XXX: Calling [isZoomed] calls this function, and calling [isZoomed] + * from within this function will recurse until the stack overflows, + * so a recursion guard is required. + */ + if (!_data.checking_zoom) { + _data.checking_zoom = YES; + if ([_data.nswindow isZoomed] && !_data.was_zoomed && _data.send_floating_size) { + NSRect rect; + + _data.send_floating_size = NO; + rect.origin.x = window->floating.x; + rect.origin.y = window->floating.y; + rect.size.width = window->floating.w; + rect.size.height = window->floating.h; + ConvertNSRect(SDL_FALSE, &rect); + + frameSize = rect.size; + } + _data.checking_zoom = NO; + } + + return frameSize; +} + - (void)windowDidResize:(NSNotification *)aNotification { SDL_Window *window; @@ -901,7 +960,8 @@ - (void)windowDidResize:(NSNotification *)aNotification int x, y, w, h; BOOL zoomed; BOOL fullscreen; - if (inFullscreenTransition) { + + if (inFullscreenTransition || b_inModeTransition) { /* We'll take care of this at the end of the transition */ return; } @@ -910,7 +970,6 @@ - (void)windowDidResize:(NSNotification *)aNotification focusClickPending = 0; [self onMovingOrFocusClickPendingStateCleared]; } - window = _data.window; nswindow = _data.nswindow; rect = [nswindow contentRectForFrameRect:[nswindow frame]]; @@ -923,14 +982,11 @@ - (void)windowDidResize:(NSNotification *)aNotification ScheduleContextUpdates(_data); - /* The window can move during a resize event, such as when maximizing - or resizing from a corner */ - SDL_GlobalToRelativeForWindow(window, x, y, &x, &y); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, w, h); - - /* isZoomed always returns true if the window is not resizable */ - if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) { + /* isZoomed always returns true if the window is not resizable + * and fullscreen windows are considered zoomed. + */ + if ((window->flags & SDL_WINDOW_RESIZABLE) && Cocoa_IsZoomed(window) && + !(window->flags & SDL_WINDOW_FULLSCREEN) && ![self isInFullscreenSpace]) { zoomed = YES; } else { zoomed = NO; @@ -939,7 +995,22 @@ - (void)windowDidResize:(NSNotification *)aNotification SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); } else if (zoomed) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); + if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) { + [nswindow miniaturize:nil]; + } } + + /* The window can move during a resize event, such as when maximizing + or resizing from a corner */ + SDL_GlobalToRelativeForWindow(window, x, y, &x, &y); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, w, h); +} + +- (void)windowWillMiniaturize:(NSNotification *)aNotification +{ + isMiniaturizing = YES; + Cocoa_WaitForMiniaturizable(_data.window); } - (void)windowDidMiniaturize:(NSNotification *)aNotification @@ -948,16 +1019,23 @@ - (void)windowDidMiniaturize:(NSNotification *)aNotification focusClickPending = 0; [self onMovingOrFocusClickPendingStateCleared]; } + isMiniaturizing = NO; + [self clearPendingWindowOperation:PENDING_OPERATION_MINIMIZE]; SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } - (void)windowDidDeminiaturize:(NSNotification *)aNotification { - /* isZoomed always returns true if the window is not resizable */ - if ((_data.window->flags & SDL_WINDOW_RESIZABLE) && [_data.nswindow isZoomed]) { + /* Always send restored before maximized. */ + SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + + /* isZoomed always returns true if the window is not resizable. */ + if ((_data.window->flags & SDL_WINDOW_RESIZABLE) && Cocoa_IsZoomed(_data.window)) { SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } else { - SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + } + + if ([self windowOperationIsPending:PENDING_OPERATION_ENTER_FULLSCREEN]) { + SDL_UpdateFullscreenMode(_data.window, SDL_TRUE, SDL_TRUE); } } @@ -1065,6 +1143,8 @@ - (void)windowWillEnterFullScreen:(NSNotification *)aNotification SetWindowStyle(window, (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable)); + _data.was_zoomed = !!(window->flags & SDL_WINDOW_MAXIMIZED); + isFullscreenSpace = YES; inFullscreenTransition = YES; } @@ -1079,6 +1159,7 @@ - (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification SetWindowStyle(window, GetWindowStyle(window)); + [self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN]; isFullscreenSpace = NO; inFullscreenTransition = NO; @@ -1090,16 +1171,24 @@ - (void)windowDidEnterFullScreen:(NSNotification *)aNotification SDL_Window *window = _data.window; inFullscreenTransition = NO; + [self clearPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN]; - if (pendingWindowOperation == PENDING_OPERATION_LEAVE_FULLSCREEN) { - pendingWindowOperation = PENDING_OPERATION_NONE; + if ([self windowOperationIsPending:PENDING_OPERATION_LEAVE_FULLSCREEN]) { [self setFullscreenSpace:NO]; } else { if (window->fullscreen_exclusive) { [NSMenu setMenuBarVisible:NO]; } - pendingWindowOperation = PENDING_OPERATION_NONE; + /* Don't recurse back into UpdateFullscreenMode() if this was hit in + * a blocking transition, as the caller is already waiting in + * UpdateFullscreenMode(). + */ + if (!_data.in_blocking_transition) { + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_FALSE); + } + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); + /* Force the size change event in case it was delivered earlier while the window was still animating into place. */ @@ -1148,7 +1237,6 @@ - (void)windowDidExitFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data.window; NSWindow *nswindow = _data.nswindow; - NSButton *button = nil; inFullscreenTransition = NO; @@ -1160,17 +1248,35 @@ when returning to windowed mode from a space (instead of using a pending */ SetWindowStyle(window, GetWindowWindowedStyle(window)); + /* Don't recurse back into UpdateFullscreenMode() if this was hit in + * a blocking transition, as the caller is already waiting in + * UpdateFullscreenMode(). + */ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + if (!_data.in_blocking_transition) { + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_FALSE); + } + if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) { [nswindow setLevel:NSFloatingWindowLevel]; } else { [nswindow setLevel:kCGNormalWindowLevel]; } - if (pendingWindowOperation == PENDING_OPERATION_ENTER_FULLSCREEN) { - pendingWindowOperation = PENDING_OPERATION_NONE; + [self clearPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN]; + + if ([self windowOperationIsPending:PENDING_OPERATION_ENTER_FULLSCREEN]) { [self setFullscreenSpace:YES]; - } else if (pendingWindowOperation == PENDING_OPERATION_MINIMIZE) { - pendingWindowOperation = PENDING_OPERATION_NONE; + } else if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) { + /* There's some state that isn't quite back to normal when + * windowDidExitFullScreen triggers. For example, the minimize button on + * the title bar doesn't actually enable for another 200 milliseconds or + * so on this MacBook. Camp here and wait for that to happen before + * going on, in case we're exiting fullscreen to minimize, which need + * that window state to be normal before it will work. + */ + Cocoa_WaitForMiniaturizable(_data.window); + [self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN]; [nswindow miniaturize:nil]; } else { /* Adjust the fullscreen toggle button and readd menu now that we're here. */ @@ -1182,62 +1288,34 @@ when returning to windowed mode from a space (instead of using a pending } [NSMenu setMenuBarVisible:YES]; - pendingWindowOperation = PENDING_OPERATION_NONE; - -#if 0 -/* This fixed bug 3719, which is that changing window size while fullscreen - doesn't take effect when leaving fullscreen, but introduces bug 3809, - which is that a maximized window doesn't go back to normal size when - restored, so this code is disabled until we can properly handle the - beginning and end of maximize and restore. - */ /* Restore windowed size and position in case it changed while fullscreen */ - { - int x, y; - NSRect rect; - SDL_RelativeToGlobalForWindow(window, window->windowed.x, window->windowed.y, x, y); - rect.origin.x = x; - rect.origin.y = y; - rect.size.width = window->windowed.w; - rect.size.height = window->windowed.h; - ConvertNSRect(NO, &rect); - - s_moveHack = 0; - [nswindow setContentSize:rect.size]; - [nswindow setFrameOrigin:rect.origin]; - s_moveHack = SDL_GetTicks(); - } -#endif /* 0 */ + NSRect rect; + rect.origin.x = _data.was_zoomed ? window->windowed.x : window->floating.x; + rect.origin.y = _data.was_zoomed ? window->windowed.y : window->floating.y; + rect.size.width = _data.was_zoomed ? window->windowed.w : window->floating.w; + rect.size.height = _data.was_zoomed ? window->windowed.h : window->floating.h; + ConvertNSRect(NO, &rect); + + _data.send_floating_position = NO; + _data.send_floating_size = NO; + [nswindow setContentSize:rect.size]; + [nswindow setFrameOrigin:rect.origin]; /* Force the size change event in case it was delivered earlier - while the window was still animating into place. + * while the window was still animating into place. */ window->w = 0; window->h = 0; [self windowDidMove:aNotification]; [self windowDidResize:aNotification]; + _data.was_zoomed = SDL_FALSE; + /* FIXME: Why does the window get hidden? */ if (!(window->flags & SDL_WINDOW_HIDDEN)) { Cocoa_ShowWindow(SDL_GetVideoDevice(), window); } } - - /* There's some state that isn't quite back to normal when - windowDidExitFullScreen triggers. For example, the minimize button on - the titlebar doesn't actually enable for another 200 milliseconds or - so on this MacBook. Camp here and wait for that to happen before - going on, in case we're exiting fullscreen to minimize, which need - that window state to be normal before it will work. */ - button = [nswindow standardWindowButton:NSWindowMiniaturizeButton]; - if (button) { - int iterations = 0; - while (![button isEnabled] && (iterations < 100)) { - SDL_Delay(10); - SDL_PumpEvents(); - iterations++; - } - } } - (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions @@ -1813,7 +1891,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow } /* isZoomed always returns true if the window is not resizable */ - if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) { + if ((window->flags & SDL_WINDOW_RESIZABLE) && Cocoa_IsZoomed(window)) { window->flags |= SDL_WINDOW_MAXIMIZED; } else { window->flags &= ~SDL_WINDOW_MAXIMIZED; @@ -2069,36 +2147,49 @@ int Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata; NSWindow *nswindow = windata.nswindow; NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]]; - BOOL fullscreen; - Uint64 moveHack; + BOOL fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN) ? YES : NO; int x, y; - SDL_RelativeToGlobalForWindow(window, window->x, window->y, &x, &y); - rect.origin.x = x; - rect.origin.y = y; - fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN) ? YES : NO; - ConvertNSRect(fullscreen, &rect); + if ([windata.listener windowOperationIsPending:(PENDING_OPERATION_ENTER_FULLSCREEN | PENDING_OPERATION_LEAVE_FULLSCREEN)] || + [windata.listener isInFullscreenSpaceTransition]) { + Cocoa_SyncWindow(_this, window); + } - /* Position and constrain the popup */ - if (SDL_WINDOW_IS_POPUP(window)) { - NSRect screenRect = [ScreenForRect(&rect) frame]; + if (!(window->flags & SDL_WINDOW_MAXIMIZED)) { + if (fullscreen) { + SDL_VideoDisplay *display = SDL_GetVideoDisplayForFullscreenWindow(window); + SDL_Rect r; + SDL_GetDisplayBounds(display->id, &r); - if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) { - rect.origin.x -= (rect.origin.x + rect.size.width) - (screenRect.origin.x + screenRect.size.width); + rect.origin.x = r.x; + rect.origin.y = r.y; + } else { + SDL_RelativeToGlobalForWindow(window, window->floating.x, window->floating.y, &x, &y); + rect.origin.x = x; + rect.origin.y = y; } - if (rect.origin.y + rect.size.height > screenRect.origin.y + screenRect.size.height) { - rect.origin.y -= (rect.origin.y + rect.size.height) - (screenRect.origin.y + screenRect.size.height); + ConvertNSRect(fullscreen, &rect); + + /* Position and constrain the popup */ + if (SDL_WINDOW_IS_POPUP(window)) { + NSRect screenRect = [ScreenForRect(&rect) frame]; + + if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) { + rect.origin.x -= (rect.origin.x + rect.size.width) - (screenRect.origin.x + screenRect.size.width); + } + if (rect.origin.y + rect.size.height > screenRect.origin.y + screenRect.size.height) { + rect.origin.y -= (rect.origin.y + rect.size.height) - (screenRect.origin.y + screenRect.size.height); + } + rect.origin.x = SDL_max(rect.origin.x, screenRect.origin.x); + rect.origin.y = SDL_max(rect.origin.y, screenRect.origin.y); } - rect.origin.x = SDL_max(rect.origin.x, screenRect.origin.x); - rect.origin.y = SDL_max(rect.origin.y, screenRect.origin.y); - } - moveHack = s_moveHack; - s_moveHack = 0; - [nswindow setFrameOrigin:rect.origin]; - s_moveHack = moveHack; + [nswindow setFrameOrigin:rect.origin]; - ScheduleContextUpdates(windata); + ScheduleContextUpdates(windata); + } else { + windata.send_floating_position = SDL_TRUE; + } } return 0; } @@ -2109,17 +2200,25 @@ void Cocoa_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata; NSWindow *nswindow = windata.nswindow; NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]]; - Uint64 moveHack; - rect.size.width = window->w; - rect.size.height = window->h; + rect.size.width = window->floating.w; + rect.size.height = window->floating.h; - moveHack = s_moveHack; - s_moveHack = 0; - [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES]; - s_moveHack = moveHack; + if ([windata.listener windowOperationIsPending:(PENDING_OPERATION_ENTER_FULLSCREEN | PENDING_OPERATION_LEAVE_FULLSCREEN)] || + [windata.listener isInFullscreenSpaceTransition]) { + Cocoa_SyncWindow(_this, window); + } - ScheduleContextUpdates(windata); + if (!Cocoa_IsZoomed(window)) { + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES]; + ScheduleContextUpdates(windata); + } else if (windata.was_zoomed) { + windata.send_floating_size = SDL_TRUE; + } + } else { + windata.send_floating_size = SDL_TRUE; + } } } @@ -2262,9 +2361,17 @@ void Cocoa_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata; NSWindow *nswindow = windata.nswindow; - [nswindow zoom:nil]; + if ([windata.listener windowOperationIsPending:(PENDING_OPERATION_ENTER_FULLSCREEN | PENDING_OPERATION_LEAVE_FULLSCREEN)] || + [windata.listener isInFullscreenSpaceTransition]) { + Cocoa_SyncWindow(_this, window); + } - ScheduleContextUpdates(windata); + if (!(window->flags & SDL_WINDOW_FULLSCREEN) && + ![windata.listener isInFullscreenSpaceTransition] && + ![windata.listener isInFullscreenSpace]) { + [nswindow zoom:nil]; + ScheduleContextUpdates(windata); + } } } @@ -2273,8 +2380,13 @@ void Cocoa_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) @autoreleasepool { SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; NSWindow *nswindow = data.nswindow; - if ([data.listener isInFullscreenSpaceTransition]) { - [data.listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE]; + + [data.listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE]; + if ([data.listener isInFullscreenSpace] || (window->flags & SDL_WINDOW_FULLSCREEN)) { + [data.listener addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN]; + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_TRUE); + } else if ([data.listener isInFullscreenSpaceTransition]) { + [data.listener addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN]; } else { [nswindow miniaturize:nil]; } @@ -2284,12 +2396,42 @@ void Cocoa_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) void Cocoa_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { @autoreleasepool { - NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; + SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; + NSWindow *nswindow = data.nswindow; - if ([nswindow isMiniaturized]) { - [nswindow deminiaturize:nil]; - } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) { - [nswindow zoom:nil]; + if ([data.listener windowOperationIsPending:(PENDING_OPERATION_ENTER_FULLSCREEN | PENDING_OPERATION_LEAVE_FULLSCREEN)] || + [data.listener isInFullscreenSpaceTransition]) { + Cocoa_SyncWindow(_this, window); + } + + [data.listener clearPendingWindowOperation:(PENDING_OPERATION_MINIMIZE)]; + + if (!(window->flags & SDL_WINDOW_FULLSCREEN) && + ![data.listener isInFullscreenSpaceTransition] && + ![data.listener isInFullscreenSpace]) { + if ([nswindow isMiniaturized]) { + [nswindow deminiaturize:nil]; + } else if ((window->flags & SDL_WINDOW_RESIZABLE) && Cocoa_IsZoomed(window)) { + NSRect rect; + + /* Update the floating coordinates */ + rect.origin.x = window->floating.x; + rect.origin.y = window->floating.y; + + /* The floating size will be set in windowWillResize */ + [nswindow zoom:nil]; + + rect.size.width = window->floating.w; + rect.size.height = window->floating.h; + + ConvertNSRect(SDL_FALSE, &rect); + + if (data.send_floating_position) { + data.send_floating_position = SDL_FALSE; + [nswindow setFrameOrigin:rect.origin]; + ScheduleContextUpdates(data); + } + } } } } @@ -2342,7 +2484,7 @@ void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_ } } -void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +int Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { @autoreleasepool { SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; @@ -2357,6 +2499,11 @@ void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V if (fullscreen) { SDL_Rect bounds; + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + data.was_zoomed = !!(window->flags & SDL_WINDOW_MAXIMIZED); + } + + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); Cocoa_GetDisplayBounds(_this, display, &bounds); rect.origin.x = bounds.x; rect.origin.y = bounds.y; @@ -2377,10 +2524,14 @@ void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V [nswindow setStyleMask:NSWindowStyleMaskBorderless]; } else { NSRect frameRect; - rect.origin.x = window->windowed.x; - rect.origin.y = window->windowed.y; - rect.size.width = window->windowed.w; - rect.size.height = window->windowed.h; + + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + + rect.origin.x = data.was_zoomed ? window->windowed.x : window->floating.x; + rect.origin.y = data.was_zoomed ? window->windowed.y : window->floating.y; + rect.size.width = data.was_zoomed ? window->windowed.w : window->floating.w; + rect.size.height = data.was_zoomed ? window->windowed.h : window->floating.h; + ConvertNSRect(fullscreen, &rect); /* The window is not meant to be fullscreen, but its flags might have a @@ -2402,14 +2553,20 @@ void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V [data.sdlContentView setNextResponder:data.listener]; } - s_moveHack = 0; [nswindow setContentSize:rect.size]; [nswindow setFrameOrigin:rect.origin]; - s_moveHack = SDL_GetTicks(); /* When the window style changes the title is cleared */ if (!fullscreen) { Cocoa_SetWindowTitle(_this, window); + + data.was_zoomed = NO; + + if ([data.listener windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) { + Cocoa_WaitForMiniaturizable(window); + [data.listener addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN]; + [nswindow miniaturize:nil]; + } } if (SDL_ShouldAllowTopmost() && fullscreen) { @@ -2429,6 +2586,8 @@ void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V ScheduleContextUpdates(data); } + + return 0; } void *Cocoa_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size) @@ -2579,47 +2738,46 @@ SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window) } } -SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state) +SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state, SDL_bool blocking) { @autoreleasepool { SDL_bool succeeded = SDL_FALSE; SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; - if (data.inWindowFullscreenTransition) { - return SDL_FALSE; - } - - data.inWindowFullscreenTransition = SDL_TRUE; + data.in_blocking_transition = blocking; if ([data.listener setFullscreenSpace:(state ? YES : NO)]) { - const int maxattempts = 3; - int attempt = 0; - while (++attempt <= maxattempts) { - /* Wait for the transition to complete, so application changes - take effect properly (e.g. setting the window size, etc.) - */ - const int limit = 10000; - int count = 0; - while ([data.listener isInFullscreenSpaceTransition]) { - if (++count == limit) { - /* Uh oh, transition isn't completing. Should we assert? */ + if (blocking) { + const int maxattempts = 3; + int attempt = 0; + while (++attempt <= maxattempts) { + /* Wait for the transition to complete, so application changes + take effect properly (e.g. setting the window size, etc.) + */ + const int limit = 10000; + int count = 0; + while ([data.listener isInFullscreenSpaceTransition]) { + if (++count == limit) { + /* Uh oh, transition isn't completing. Should we assert? */ + break; + } + SDL_Delay(1); + SDL_PumpEvents(); + } + if ([data.listener isInFullscreenSpace] == (state ? YES : NO)) { break; } - SDL_Delay(1); - SDL_PumpEvents(); - } - if ([data.listener isInFullscreenSpace] == (state ? YES : NO)) { - break; - } - /* Try again, the last attempt was interrupted by user gestures */ - if (![data.listener setFullscreenSpace:(state ? YES : NO)]) { - break; /* ??? */ + /* Try again, the last attempt was interrupted by user gestures */ + if (![data.listener setFullscreenSpace:(state ? YES : NO)]) { + break; /* ??? */ + } } } + /* Return TRUE to prevent non-space fullscreen logic from running */ succeeded = SDL_TRUE; } - data.inWindowFullscreenTransition = SDL_FALSE; + data.in_blocking_transition = NO; return succeeded; } } @@ -2683,4 +2841,32 @@ int Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opa } } +int Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + int ret = 0; + + @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); + SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; + while (SDL_TRUE) { + SDL_PumpEvents(); + + if (SDL_GetTicksNS() >= timeout) { + ret = 1; + break; + } + if (![data.listener hasPendingWindowOperation]) { + break; + } + + SDL_Delay(10); + } + } + + return ret; +} + #endif /* SDL_VIDEO_DRIVER_COCOA */ diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index 64dad5afd7c18..07f3dfd4bce42 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -55,6 +55,17 @@ static int DUMMY_VideoInit(SDL_VideoDevice *_this); static void DUMMY_VideoQuit(SDL_VideoDevice *_this); +static int DUMMY_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, window->floating.x, window->floating.y); + return 0; +} + +static void DUMMY_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->floating.w, window->floating.h); +} + /* DUMMY driver bootstrap functions */ static int DUMMY_Available(const char *enable_hint) @@ -92,6 +103,8 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint) device->VideoInit = DUMMY_VideoInit; device->VideoQuit = DUMMY_VideoQuit; device->PumpEvents = DUMMY_PumpEvents; + device->SetWindowSize = DUMMY_SetWindowSize; + device->SetWindowPosition = DUMMY_SetWindowPosition; device->CreateWindowFramebuffer = SDL_DUMMY_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = SDL_DUMMY_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = SDL_DUMMY_DestroyWindowFramebuffer; diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 18b36a79462cd..006cc21319751 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -843,23 +843,16 @@ static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboard static EM_BOOL Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData) { SDL_WindowData *window_data = userData; - SDL_VideoDisplay *display; if (fullscreenChangeEvent->isFullscreen) { - window_data->window->flags |= window_data->fullscreen_mode_flags; - + SDL_SendWindowEvent(window_data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); window_data->fullscreen_mode_flags = 0; } else { - window_data->window->flags &= ~SDL_WINDOW_FULLSCREEN; - - /* reset fullscreen window if the browser left fullscreen */ - display = SDL_GetVideoDisplayForWindow(window_data->window); - - if (display->fullscreen_window == window_data->window) { - display->fullscreen_window = NULL; - } + SDL_SendWindowEvent(window_data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); } + SDL_UpdateFullscreenMode(window_data->window, fullscreenChangeEvent->isFullscreen, SDL_FALSE); + return 0; } diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index 000dc192d4290..b28dbd96acfc4 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -44,7 +44,7 @@ static int Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, S static void Emscripten_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); static void Emscripten_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h); static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -static void Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +static int Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); static void Emscripten_PumpEvents(SDL_VideoDevice *_this); static void Emscripten_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); @@ -247,12 +247,14 @@ static void Emscripten_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) { data->pixel_ratio = emscripten_get_device_pixel_ratio(); } - emscripten_set_canvas_element_size(data->canvas_id, window->w * data->pixel_ratio, window->h * data->pixel_ratio); + emscripten_set_canvas_element_size(data->canvas_id, window->floating.w * data->pixel_ratio, window->floating.h * data->pixel_ratio); /*scale canvas down*/ if (!data->external_size && data->pixel_ratio != 1.0f) { - emscripten_set_element_css_size(data->canvas_id, window->w, window->h); + emscripten_set_element_css_size(data->canvas_id, window->floating.w, window->floating.h); } + + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->floating.w, window->floating.h); } } @@ -284,16 +286,17 @@ static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } } -static void Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +static int Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { SDL_WindowData *data; + int res = -1; + if (window->driverdata) { data = window->driverdata; if (fullscreen) { EmscriptenFullscreenStrategy strategy; SDL_bool is_fullscreen_desktop = !window->fullscreen_exclusive; - int res; strategy.scaleMode = is_fullscreen_desktop ? EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH : EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT; @@ -314,12 +317,17 @@ static void Emscripten_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *w data->fullscreen_resize = is_fullscreen_desktop; res = emscripten_request_fullscreen_strategy(data->canvas_id, 1, &strategy); - if (res != EMSCRIPTEN_RESULT_SUCCESS && res != EMSCRIPTEN_RESULT_DEFERRED) { - /* unset flags, fullscreen failed */ - window->flags &= ~SDL_WINDOW_FULLSCREEN; - } - } else - emscripten_exit_fullscreen(); + } else { + res = emscripten_exit_fullscreen(); + } + } + + if (res == EMSCRIPTEN_RESULT_SUCCESS) { + return 0; + } else if (res == EMSCRIPTEN_RESULT_DEFERRED) { + return 1; + } else { + return -1; } } diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index c5eb22995b710..f74b8dd6dfbe4 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -92,17 +92,18 @@ void HAIKU_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window * window) { _ToBeWin(window)->PostMessage(&msg); } -void HAIKU_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window * window) { +int HAIKU_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window * window) { BMessage msg(BWIN_MOVE_WINDOW); - msg.AddInt32("window-x", window->x); - msg.AddInt32("window-y", window->y); + msg.AddInt32("window-x", window->floating.x); + msg.AddInt32("window-y", window->floating.y); _ToBeWin(window)->PostMessage(&msg); + return 0; } void HAIKU_SetWindowSize(SDL_VideoDevice *_this, SDL_Window * window) { BMessage msg(BWIN_RESIZE_WINDOW); - msg.AddInt32("window-w", window->w - 1); - msg.AddInt32("window-h", window->h - 1); + msg.AddInt32("window-w", window->floating.w - 1); + msg.AddInt32("window-h", window->floating.h - 1); _ToBeWin(window)->PostMessage(&msg); } @@ -148,13 +149,13 @@ void HAIKU_RestoreWindow(SDL_VideoDevice *_this, SDL_Window * window) { _ToBeWin(window)->PostMessage(&msg); } -void HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window * window, +int HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { /* Haiku tracks all video display information */ BMessage msg(BWIN_FULLSCREEN); msg.AddBool("fullscreen", fullscreen); _ToBeWin(window)->PostMessage(&msg); - + return 0; } diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index 0f4fc48640eb0..24d5c4f4cb96e 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -37,7 +37,7 @@ extern void HAIKU_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void HAIKU_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void HAIKU_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); extern void HAIKU_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); -extern void HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int HAIKU_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void HAIKU_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void HAIKU_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 4ec049d677b4a..3023f67d29521 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1596,13 +1596,13 @@ void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) KMSDRM_DirtySurfaces(window); } } -void KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) - +int KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { SDL_VideoData *viddata = _this->driverdata; if (!viddata->vulkan_mode) { KMSDRM_DirtySurfaces(window); } + return 0; } void KMSDRM_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) { diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index ee11dd5941312..cea1663459321 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -125,7 +125,7 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); int KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); -void KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen); +int KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen); void KMSDRM_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); void KMSDRM_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/offscreen/SDL_offscreenvideo.c b/src/video/offscreen/SDL_offscreenvideo.c index 2b66260bda060..8c24aa215d19b 100644 --- a/src/video/offscreen/SDL_offscreenvideo.c +++ b/src/video/offscreen/SDL_offscreenvideo.c @@ -86,6 +86,7 @@ static SDL_VideoDevice *OFFSCREEN_CreateDevice(void) /* "Window" */ device->CreateSDLWindow = OFFSCREEN_CreateWindow; device->DestroyWindow = OFFSCREEN_DestroyWindow; + device->SetWindowSize = OFFSCREEN_SetWindowSize; return device; } diff --git a/src/video/offscreen/SDL_offscreenwindow.c b/src/video/offscreen/SDL_offscreenwindow.c index a51f8fd364de2..2c67d17ccc8ec 100644 --- a/src/video/offscreen/SDL_offscreenwindow.c +++ b/src/video/offscreen/SDL_offscreenwindow.c @@ -23,6 +23,7 @@ #ifdef SDL_VIDEO_DRIVER_OFFSCREEN #include "../SDL_sysvideo.h" +#include "../../events/SDL_windowevents_c.h" #include "../SDL_egl_c.h" #include "SDL_offscreenwindow.h" @@ -82,4 +83,8 @@ void OFFSCREEN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) window->driverdata = NULL; } +void OFFSCREEN_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->floating.w, window->floating.h); +} #endif /* SDL_VIDEO_DRIVER_OFFSCREEN */ diff --git a/src/video/offscreen/SDL_offscreenwindow.h b/src/video/offscreen/SDL_offscreenwindow.h index 2e360d418ae03..488d514a44505 100644 --- a/src/video/offscreen/SDL_offscreenwindow.h +++ b/src/video/offscreen/SDL_offscreenwindow.h @@ -35,5 +35,6 @@ struct SDL_WindowData extern int OFFSCREEN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void OFFSCREEN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern void OFFSCREEN_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_offscreenwindow_h */ diff --git a/src/video/qnx/SDL_qnxvideo.c b/src/video/qnx/SDL_qnxvideo.c index ea32e7d5e6aa8..cf8c5b917a547 100644 --- a/src/video/qnx/SDL_qnxvideo.c +++ b/src/video/qnx/SDL_qnxvideo.c @@ -241,12 +241,11 @@ static void setWindowSize(SDL_VideoDevice *_this, SDL_Window *window) window_impl_t *impl = (window_impl_t *)window->driverdata; int size[2]; - size[0] = window->w; - size[1] = window->h; + size[0] = window->floating.w; + size[1] = window->floating.h; screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size); - screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, - size); + screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, size); } /** diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index 8635bef4ca849..d6998498ce28e 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -32,7 +32,7 @@ extern void UIKit_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); -extern void UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void UIKit_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void UIKit_UpdatePointerLock(SDL_VideoDevice *_this, SDL_Window *window); extern void UIKit_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index dd7a36dd239ae..efc21da164b14 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -309,11 +309,12 @@ void UIKit_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_boo } } -void UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +int UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { @autoreleasepool { UIKit_UpdateWindowBorder(_this, window); } + return 0; } void UIKit_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 55b403aecc067..81e48fbb707a2 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -216,6 +216,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) device->FlashWindow = Wayland_FlashWindow; device->HasScreenKeyboardSupport = Wayland_HasScreenKeyboardSupport; device->ShowWindowSystemMenu = Wayland_ShowWindowSystemMenu; + device->SyncWindow = Wayland_SyncWindow; #ifdef SDL_USE_LIBDBUS if (SDL_SystemTheme_Init()) @@ -239,9 +240,9 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) device->free = Wayland_DeleteDevice; - device->quirk_flags = VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED | - VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE | - VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT; + device->device_caps = VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED | + VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; return device; } diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index ce7a383ea46ea..84bf2fb4fec49 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -182,7 +182,7 @@ static void SetMinMaxDimensions(SDL_Window *window) SDL_VideoData *viddata = wind->waylandData; int min_width, min_height, max_width, max_height; - if (window->flags & SDL_WINDOW_FULLSCREEN) { + if ((window->flags & SDL_WINDOW_FULLSCREEN) || wind->fullscreen_deadline_count) { min_width = 0; min_height = 0; max_width = 0; @@ -230,7 +230,7 @@ static void SetMinMaxDimensions(SDL_Window *window) } } -static void EnsurePopupPositionIsValid(SDL_Window *window) +static void EnsurePopupPositionIsValid(SDL_Window *window, int *x, int *y) { int adj_count = 0; @@ -241,20 +241,20 @@ static void EnsurePopupPositionIsValid(SDL_Window *window) * can result in behavior ranging from the window being spuriously closed * to a protocol violation. */ - if (window->x + window->driverdata->wl_window_width < 0) { - window->x = -window->w; + if (*x + window->driverdata->wl_window_width < 0) { + *x = -window->w; ++adj_count; } - if (window->y + window->driverdata->wl_window_height < 0) { - window->y = -window->h; + if (*y + window->driverdata->wl_window_height < 0) { + *y = -window->h; ++adj_count; } - if (window->x > window->parent->driverdata->wl_window_width) { - window->x = window->parent->driverdata->wl_window_width; + if (*x > window->parent->driverdata->wl_window_width) { + *x = window->parent->driverdata->wl_window_width; ++adj_count; } - if (window->y > window->parent->driverdata->wl_window_height) { - window->y = window->parent->driverdata->wl_window_height; + if (*y > window->parent->driverdata->wl_window_height) { + *y = window->parent->driverdata->wl_window_height; ++adj_count; } @@ -263,7 +263,7 @@ static void EnsurePopupPositionIsValid(SDL_Window *window) * must be nudged by 1 to be considered adjacent. */ if (adj_count > 1) { - window->x += window->x < 0 ? 1 : -1; + *x += *x < 0 ? 1 : -1; } } @@ -282,17 +282,19 @@ static void GetPopupPosition(SDL_Window *popup, int x, int y, int *adj_x, int *a } } -static void RepositionPopup(SDL_Window *window) +static void RepositionPopup(SDL_Window *window, SDL_bool use_current_position) { SDL_WindowData *wind = window->driverdata; if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP && wind->shell_surface.xdg.roleobj.popup.positioner && xdg_popup_get_version(wind->shell_surface.xdg.roleobj.popup.popup) >= XDG_POPUP_REPOSITION_SINCE_VERSION) { + int orig_x = use_current_position ? window->x : window->floating.x; + int orig_y = use_current_position ? window->y : window->floating.y; int x, y; - EnsurePopupPositionIsValid(window); - GetPopupPosition(window, window->x, window->y, &x, &y); + EnsurePopupPositionIsValid(window, &orig_x, &orig_y); + GetPopupPosition(window, orig_x, orig_y, &x, &y); xdg_positioner_set_anchor_rect(wind->shell_surface.xdg.roleobj.popup.positioner, 0, 0, window->parent->driverdata->wl_window_width, window->parent->driverdata->wl_window_height); xdg_positioner_set_size(wind->shell_surface.xdg.roleobj.popup.positioner, wind->wl_window_width, wind->wl_window_height); xdg_positioner_set_offset(wind->shell_surface.xdg.roleobj.popup.positioner, x, y); @@ -431,7 +433,7 @@ static void ConfigureWindowGeometry(SDL_Window *window) /* Ensure that child popup windows are still in bounds. */ for (SDL_Window *child = window->first_child; child; child = child->next_sibling) { - RepositionPopup(child); + RepositionPopup(child, SDL_TRUE); } if (data->confined_pointer) { @@ -479,6 +481,31 @@ static void CommitLibdecorFrame(SDL_Window *window) #endif } +static void fullscreen_deadline_handler(void *data, struct wl_callback *callback, uint32_t callback_data) +{ + /* Get the window from the ID as it may have been destroyed */ + SDL_WindowID windowID = (SDL_WindowID)((uintptr_t)data); + SDL_Window *window = SDL_GetWindowFromID(windowID); + + if (window && window->driverdata) { + window->driverdata->fullscreen_deadline_count--; + SetMinMaxDimensions(window); + } + + wl_callback_destroy(callback); +} + +static struct wl_callback_listener fullscreen_deadline_listener = { + fullscreen_deadline_handler +}; + +static void FlushFullscreenEvents(SDL_Window *window) +{ + while (window->driverdata->fullscreen_deadline_count) { + WAYLAND_wl_display_roundtrip(window->driverdata->waylandData->display); + } +} + static void SetFullscreen(SDL_Window *window, struct wl_output *output) { SDL_WindowData *wind = window->driverdata; @@ -489,6 +516,8 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output) if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } + + ++wind->fullscreen_deadline_count; if (output) { Wayland_SetWindowResizable(SDL_GetVideoDevice(), window, SDL_TRUE); wl_surface_commit(wind->surface); @@ -504,6 +533,7 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output) return; /* Can't do anything yet, wait for ShowWindow */ } + ++wind->fullscreen_deadline_count; if (output) { Wayland_SetWindowResizable(SDL_GetVideoDevice(), window, SDL_TRUE); wl_surface_commit(wind->surface); @@ -514,8 +544,9 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output) } } - /* Roundtrip to apply the new state. */ - WAYLAND_wl_display_roundtrip(viddata->display); + /* Queue a deadline event */ + struct wl_callback *cb = wl_display_sync(viddata->display); + wl_callback_add_listener(cb, &fullscreen_deadline_listener, (void *)((uintptr_t)window->id)); } static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) @@ -524,26 +555,30 @@ static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) wind->is_fullscreen = fullscreen; - /* If this configure event is coming from a roundtrip after explicitly - * changing the fullscreen state, don't call back into the - * SDL_SetWindowFullscreen() function. - */ - if (wind->in_fullscreen_transition) { - return; - } - if (fullscreen) { if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - wind->in_fullscreen_transition = SDL_TRUE; - SDL_SetWindowFullscreen(window, SDL_TRUE); - wind->in_fullscreen_transition = SDL_FALSE; + SDL_copyp(&window->current_fullscreen_mode, &window->requested_fullscreen_mode); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_FALSE); + + /* Unconditionally set the output for exclusive fullscreen windows when entering + * fullscreen from a compositor event, as where the compositor will actually + * place the fullscreen window is unknown. + */ + if (window->fullscreen_exclusive && !wind->fullscreen_was_positioned) { + SDL_VideoDisplay *disp = SDL_GetVideoDisplay(window->current_fullscreen_mode.displayID); + if (disp) { + wind->fullscreen_was_positioned = SDL_TRUE; + SetFullscreen(window, disp->driverdata->output); + } + } } } else { /* Don't change the fullscreen flags if the window is hidden or being hidden. */ if ((window->flags & SDL_WINDOW_FULLSCREEN) && !window->is_hiding && !(window->flags & SDL_WINDOW_HIDDEN)) { - wind->in_fullscreen_transition = SDL_TRUE; - SDL_SetWindowFullscreen(window, SDL_FALSE); - wind->in_fullscreen_transition = SDL_FALSE; + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + SDL_UpdateFullscreenMode(window, SDL_FALSE, SDL_FALSE); + wind->fullscreen_was_positioned = SDL_FALSE; } } } @@ -638,6 +673,7 @@ static void handle_configure_xdg_toplevel(void *data, SDL_bool fullscreen = SDL_FALSE; SDL_bool maximized = SDL_FALSE; SDL_bool floating = SDL_TRUE; + SDL_bool tiled = SDL_FALSE; SDL_bool active = SDL_FALSE; SDL_bool suspended = SDL_FALSE; wl_array_for_each (state, states) { @@ -657,6 +693,7 @@ static void handle_configure_xdg_toplevel(void *data, case XDG_TOPLEVEL_STATE_TILED_RIGHT: case XDG_TOPLEVEL_STATE_TILED_TOP: case XDG_TOPLEVEL_STATE_TILED_BOTTOM: + tiled = SDL_TRUE; floating = SDL_FALSE; break; case XDG_TOPLEVEL_STATE_SUSPENDED: @@ -669,17 +706,36 @@ static void handle_configure_xdg_toplevel(void *data, UpdateWindowFullscreen(window, fullscreen); + /* Always send a maximized/restore event; if the event is redundant it will + * automatically be discarded (see src/events/SDL_windowevents.c) + * + * No, we do not get minimize events from xdg-shell, however, the minimized + * state can be programmatically set. The meaning of 'minimized' is compositor + * dependent, but in general, we can assume that the flag should remain set until + * the next focused configure event occurs. + */ + if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) { + if (window->flags & SDL_WINDOW_MINIMIZED) { + /* If we were minimized, send a restored event before possibly sending maximized. */ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + } + SDL_SendWindowEvent(window, + (maximized && !fullscreen) ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED, + 0, 0); + } + if (!fullscreen) { /* xdg_toplevel spec states that this is a suggestion. * Ignore if less than or greater than max/min size. */ if (window->flags & SDL_WINDOW_RESIZABLE) { - if ((floating && !wind->floating) || width == 0 || height == 0) { + if ((floating && !wind->floating) || + width == 0 || height == 0) { /* This happens when we're being restored from a * non-floating state, so use the cached floating size here. */ - width = wind->floating_width; - height = wind->floating_height; + width = window->floating.w; + height = window->floating.h; } } else { /* If we're a fixed-size window, we know our size for sure. @@ -706,50 +762,28 @@ static void handle_configure_xdg_toplevel(void *data, } height = SDL_max(height, window->min_h); } - - /* Always send a maximized/restore event; if the event is redundant it will - * automatically be discarded (see src/events/SDL_windowevents.c) - * - * No, we do not get minimize events from xdg-shell, however, the minimized - * state can be programmatically set. The meaning of 'minimized' is compositor - * dependent, but in general, we can assume that the flag should remain set until - * the next focused configure event occurs. - */ - if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) { - SDL_SendWindowEvent(window, - maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED, - 0, 0); - } - - /* Store current floating dimensions for restoring */ - if (floating) { - wind->floating_width = width; - wind->floating_height = height; - } } else { - /* Unconditionally set the output for exclusive fullscreen windows when entering - * fullscreen from a compositor event, as where the compositor will actually - * place the fullscreen window is unknown. - */ - if (window->fullscreen_exclusive && !wind->fullscreen_was_positioned) { - SDL_VideoDisplay *disp = SDL_GetVideoDisplay(window->current_fullscreen_mode.displayID); - if (disp) { - wind->fullscreen_was_positioned = SDL_TRUE; - xdg_toplevel_set_fullscreen(xdg_toplevel, disp->driverdata->output); - } - } - if (width == 0 || height == 0) { width = wind->requested_window_width; height = wind->requested_window_height; } } - wind->requested_window_width = width; - wind->requested_window_height = height; + /* Don't update the dimensions if they haven't changed, or they could overwrite + * a new size set programmatically with old dimensions. + */ + if (width != wind->last_configure_width || height != wind->last_configure_height) { + wind->requested_window_width = width; + wind->requested_window_height = height; + } + + wind->last_configure_width = width; + wind->last_configure_height = height; wind->floating = floating; wind->suspended = suspended; wind->active = active; + window->state_not_floating = tiled; + if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) { wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME; } @@ -940,38 +974,28 @@ static void decoration_frame_configure(struct libdecor_frame *frame, UpdateWindowFullscreen(window, fullscreen); - if (!fullscreen) { - /* Always send a maximized/restore event; if the event is redundant it will - * automatically be discarded (see src/events/SDL_windowevents.c) - * - * No, we do not get minimize events from libdecor, however, the minimized - * state can be programmatically set. The meaning of 'minimized' is compositor - * dependent, but in general, we can assume that the flag should remain set until - * the next focused configure event occurs. - */ - if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) { - SDL_SendWindowEvent(window, - maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED, - 0, 0); + /* Always send a maximized/restore event; if the event is redundant it will + * automatically be discarded (see src/events/SDL_windowevents.c) + * + * No, we do not get minimize events from libdecor, however, the minimized + * state can be programmatically set. The meaning of 'minimized' is compositor + * dependent, but in general, we can assume that the flag should remain set until + * the next focused configure event occurs. + */ + if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) { + if (window->flags & SDL_WINDOW_MINIMIZED) { + /* If we were minimized, send a restored event before possibly sending maximized. */ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); } + SDL_SendWindowEvent(window, + (maximized && !fullscreen) ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED, + 0, 0); } /* For fullscreen or fixed-size windows we know our size. * Always assume the configure is wrong. */ if (fullscreen) { - /* Unconditionally set the output for exclusive fullscreen windows when entering - * fullscreen from a compositor event, as where the compositor will actually - * place the fullscreen window is unknown. - */ - if (window->fullscreen_exclusive && !wind->fullscreen_was_positioned) { - SDL_VideoDisplay *disp = SDL_GetVideoDisplay(window->current_fullscreen_mode.displayID); - if (disp) { - wind->fullscreen_was_positioned = SDL_TRUE; - libdecor_frame_set_fullscreen(frame, disp->driverdata->output); - } - } - /* FIXME: We have been explicitly told to respect the fullscreen size * parameters here, even though they are known to be wrong on GNOME at * bare minimum. If this is wrong, don't blame us, we were explicitly @@ -1008,11 +1032,11 @@ static void decoration_frame_configure(struct libdecor_frame *frame, /* This usually happens when we're being restored from a * non-floating state, so use the cached floating size here. */ - width = wind->floating_width; - height = wind->floating_height; + width = window->floating.w; + height = window->floating.h; } else { - width = window->w; - height = window->h; + width = window->windowed.w; + height = window->windowed.h; } } } @@ -1036,16 +1060,21 @@ static void decoration_frame_configure(struct libdecor_frame *frame, } } - /* Store current floating dimensions for restoring */ - if (floating) { - wind->floating_width = width; - wind->floating_height = height; + /* Don't update the dimensions if they haven't changed, or they could overwrite + * a new size set programmatically with old dimensions. + */ + if (width != wind->last_configure_width || height != wind->last_configure_height) { + wind->requested_window_width = width; + wind->requested_window_height = height; } /* Store the new state. */ + wind->last_configure_width = width; + wind->last_configure_height = height; wind->floating = floating; wind->suspended = suspended; wind->active = active; + window->state_not_floating = tiled; /* Calculate the new window geometry */ wind->requested_window_width = width; @@ -1178,10 +1207,16 @@ static void Wayland_move_window(SDL_Window *window, SDL_DisplayData *driverdata) * -flibit */ SDL_Rect bounds; - SDL_GetDisplayBounds(displays[i], &bounds); wind->last_displayID = displays[i]; if (wind->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP) { + /* Need to catch up on fullscreen state here, as the video core may try to update + * the fullscreen window, which on Wayland involves a set fullscreen call, which + * can overwrite older pending state. + */ + FlushFullscreenEvents(window); + + SDL_GetDisplayBounds(wind->last_displayID, &bounds); SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, bounds.x, bounds.y); } break; @@ -1347,10 +1382,27 @@ int Wayland_SetWindowModalFor(SDL_VideoDevice *_this, SDL_Window *modal_window, return SDL_Unsupported(); } - WAYLAND_wl_display_flush(viddata->display); return 0; } +static void show_hide_sync_handler(void *data, struct wl_callback *callback, uint32_t callback_data) +{ + /* Get the window from the ID as it may have been destroyed */ + SDL_WindowID windowID = (SDL_WindowID)((uintptr_t)data); + SDL_Window *window = SDL_GetWindowFromID(windowID); + + if (window && window->driverdata) { + SDL_WindowData *wind = window->driverdata; + wind->show_hide_sync_required = SDL_FALSE; + } + + wl_callback_destroy(callback); +} + +static struct wl_callback_listener show_hide_sync_listener = { + show_hide_sync_handler +}; + void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *c = _this->driverdata; @@ -1372,6 +1424,13 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } + /* The window was hidden, but the sync point hasn't yet been reached. + * Pump events to avoid a possible protocol violation. + */ + if (data->show_hide_sync_required) { + WAYLAND_wl_display_roundtrip(c->display); + } + data->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE; /* Detach any previous buffers before resetting everything, otherwise when @@ -1442,7 +1501,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) xdg_positioner_set_size(data->shell_surface.xdg.roleobj.popup.positioner, window->w, window->h); /* Set the popup initial position */ - EnsurePopupPositionIsValid(window); + EnsurePopupPositionIsValid(window, &window->x, &window->y); GetPopupPosition(window, window->x, window->y, &position_x, &position_y); xdg_positioner_set_offset(data->shell_surface.xdg.roleobj.popup.positioner, position_x, position_y); @@ -1561,11 +1620,9 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - /* - * Roundtrip required to avoid a possible protocol violation when - * HideWindow was called immediately before ShowWindow. - */ - WAYLAND_wl_display_roundtrip(c->display); + data->show_hide_sync_required = SDL_TRUE; + struct wl_callback *cb = wl_display_sync(_this->driverdata->display); + wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id)); /* Send an exposure event to signal that the client should draw. */ if (data->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME) { @@ -1620,6 +1677,13 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_WindowData *wind = window->driverdata; SDL_PropertiesID props = SDL_GetWindowProperties(window); + /* The window was shown, but the sync point hasn't yet been reached. + * Pump events to avoid a possible protocol violation. + */ + if (wind->show_hide_sync_required) { + WAYLAND_wl_display_roundtrip(data->display); + } + wind->surface_status = WAYLAND_SURFACE_STATUS_HIDDEN; if (wind->server_decoration) { @@ -1659,11 +1723,9 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - /* - * Roundtrip required to avoid a possible protocol violation when - * ShowWindow is called immediately after HideWindow. - */ - WAYLAND_wl_display_roundtrip(data->display); + wind->show_hide_sync_required = SDL_TRUE; + struct wl_callback *cb = wl_display_sync(_this->driverdata->display); + wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id)); } static void handle_xdg_activation_done(void *data, @@ -1753,29 +1815,45 @@ int Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOpe return 0; } -void Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, +static void fullscreen_configure_handler(void *data, struct wl_callback *callback, uint32_t callback_data) +{ + /* Get the window from the ID as it may have been destroyed */ + SDL_WindowID windowID = (SDL_WindowID)((uintptr_t)data); + SDL_Window *window = SDL_GetWindowFromID(windowID); + + if (window && window->driverdata && window->driverdata->is_fullscreen) { + ConfigureWindowGeometry(window); + CommitLibdecorFrame(window); + } + + wl_callback_destroy(callback); +} + +static struct wl_callback_listener fullscreen_configure_listener = { + fullscreen_configure_handler +}; + +int Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { SDL_WindowData *wind = window->driverdata; struct wl_output *output = display->driverdata->output; - /* Called from within a configure event or the window is a popup, drop it. */ - if (wind->in_fullscreen_transition || wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - if (!fullscreen) { - /* Clear the fullscreen positioned flag. */ - wind->fullscreen_was_positioned = SDL_FALSE; - } - return; + if (wind->show_hide_sync_required) { + WAYLAND_wl_display_roundtrip(_this->driverdata->display); } - /* If we're here, this was called from a higher-level video subsystem function. - * Set the flag to avoid recursively re-entering these functions while changing the - * fullscreen state. - */ - wind->in_fullscreen_transition = SDL_TRUE; + /* Flushing old events pending a new one, ignore this request. */ + if (wind->drop_fullscreen_requests) { + return 0; + } + + wind->drop_fullscreen_requests = SDL_TRUE; + FlushFullscreenEvents(window); + wind->drop_fullscreen_requests = SDL_FALSE; /* Don't send redundant fullscreen set/unset events. */ - if (wind->is_fullscreen != fullscreen) { + if (fullscreen != wind->is_fullscreen) { wind->fullscreen_was_positioned = fullscreen; SetFullscreen(window, fullscreen ? output : NULL); } else if (wind->is_fullscreen) { @@ -1790,12 +1868,13 @@ void Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, wind->fullscreen_was_positioned = SDL_TRUE; SetFullscreen(window, output); } else { - ConfigureWindowGeometry(window); - CommitLibdecorFrame(window); + /* Queue a configure event */ + struct wl_callback *cb = wl_display_sync(_this->driverdata->display); + wl_callback_add_listener(cb, &fullscreen_configure_listener, (void *)((uintptr_t)window->id)); } } - wind->in_fullscreen_transition = SDL_FALSE; + return 1; } void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1803,10 +1882,6 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - return; - } - #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (!wind->shell_surface.libdecor.frame) { @@ -1822,8 +1897,6 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) } xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel); } - - WAYLAND_wl_display_roundtrip(viddata->display); } void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered) @@ -1831,10 +1904,6 @@ void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_b SDL_WindowData *wind = window->driverdata; const SDL_VideoData *viddata = (const SDL_VideoData *)_this->driverdata; - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - return; - } - #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (wind->shell_surface.libdecor.frame) { @@ -1879,12 +1948,8 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - return; - } - - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - return; + if (wind->show_hide_sync_required) { + WAYLAND_wl_display_roundtrip(_this->driverdata->display); } #ifdef HAVE_LIBDECOR_H @@ -1901,12 +1966,6 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) } xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel); } - - /* Don't roundtrip if this is being called to set the initial state during window creation. */ - if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME || - wind->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) { - WAYLAND_wl_display_roundtrip(viddata->display); - } } void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1914,16 +1973,14 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; - /* Maximized and minimized flags are mutually exclusive */ - window->flags &= ~SDL_WINDOW_MAXIMIZED; - window->flags |= SDL_WINDOW_MINIMIZED; - + /* TODO: Check compositor capabilities to see if minimizing is supported */ #ifdef HAVE_LIBDECOR_H if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { if (!wind->shell_surface.libdecor.frame) { return; /* Can't do anything yet, wait for ShowWindow */ } libdecor_frame_set_minimized(wind->shell_surface.libdecor.frame); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } else #endif if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && viddata->shell.xdg) { @@ -1931,12 +1988,7 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) return; /* Can't do anything yet, wait for ShowWindow */ } xdg_toplevel_set_minimized(wind->shell_surface.xdg.roleobj.toplevel); - } - - /* Don't roundtrip if this is being called to set the initial state during window creation. */ - if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME || - wind->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) { - WAYLAND_wl_display_roundtrip(viddata->display); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } } @@ -2002,7 +2054,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } if (SDL_WINDOW_IS_POPUP(window)) { - EnsurePopupPositionIsValid(window); + EnsurePopupPositionIsValid(window, &window->x, &window->y); } data->waylandData = c; @@ -2026,11 +2078,8 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert data->requested_window_width = window->w; data->requested_window_height = window->h; - data->floating_width = window->windowed.w; - data->floating_height = window->windowed.h; - data->surface = - wl_compositor_create_surface(c->compositor); + data->surface = wl_compositor_create_surface(c->compositor); wl_surface_add_listener(data->surface, &surface_listener, data); SDL_WAYLAND_register_surface(data->surface); @@ -2084,9 +2133,6 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert &fractional_scale_listener, data); } - /* Moved this call to ShowWindow: wl_surface_commit(data->surface); */ - WAYLAND_wl_display_flush(c->display); - /* We may need to create an idle inhibitor for this new window */ Wayland_SuspendScreenSaver(_this); @@ -2137,35 +2183,85 @@ int Wayland_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) return SDL_Unsupported(); } - RepositionPopup(window); + RepositionPopup(window, SDL_FALSE); return 0; + } else if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR || wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { + const int x = window->floating.x; + const int y = window->floating.y; + + /* Catch up on any pending state before attempting to change the fullscreen window + * display via a set fullscreen call to make sure the window doesn't have a pending + * leave fullscreen event that it might override. + */ + FlushFullscreenEvents(window); + + /* XXX: Need to restore this after the roundtrip, as the requested coordinates might + * have been overwritten by the 'real' coordinates if a display enter/leave event + * occurred. + * + * The common pattern: + * + * SDL_SetWindowPosition(); + * SDL_SetWindowFullscreen(); + * + * for positioning a desktop fullscreen window won't work without this. + */ + window->floating.x = x; + window->floating.y = y; + + if (wind->is_fullscreen) { + SDL_VideoDisplay *display = SDL_GetVideoDisplayForFullscreenWindow(window); + if (display && wind->last_displayID != display->id) { + struct wl_output *output = display->driverdata->output; + SetFullscreen(window, output); + + return 0; + } + } } return SDL_SetError("wayland cannot position non-popup windows"); } -void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) +static void size_event_handler(void *data, struct wl_callback *callback, uint32_t callback_data) { - SDL_WindowData *wind = window->driverdata; + /* Get the window from the ID as it may have been destroyed */ + SDL_WindowID windowID = (SDL_WindowID)((uintptr_t)data); + SDL_Window *window = SDL_GetWindowFromID(windowID); - /* - * Unconditionally store the floating size, as it will need - * to be applied when returning from a non-floating state. - */ - wind->floating_width = window->windowed.w; - wind->floating_height = window->windowed.h; + if (window && window->driverdata) { + SDL_WindowData *wind = window->driverdata; - /* Fullscreen windows do not get explicitly resized, and not strictly - * obeying the size of maximized windows is a protocol violation. - */ - if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) { - wind->requested_window_width = window->windowed.w; - wind->requested_window_height = window->windowed.h; + /* Fullscreen windows do not get explicitly resized, and not strictly + * obeying the size of maximized windows is a protocol violation. + */ + if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) { + wind->requested_window_width = wind->pending_size_event.width; + wind->requested_window_height = wind->pending_size_event.height; - ConfigureWindowGeometry(window); + ConfigureWindowGeometry(window); + } + + /* Always commit, as this may be in response to a min/max limit change. */ + CommitLibdecorFrame(window); } - /* Always commit, as this may be in response to a min/max limit change. */ - CommitLibdecorFrame(window); + wl_callback_destroy(callback); +} + +static struct wl_callback_listener size_event_listener = { + size_event_handler +}; + +void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_WindowData *wind = window->driverdata; + + /* Queue an event to send the window size. */ + struct wl_callback *cb = wl_display_sync(_this->driverdata->display); + + wind->pending_size_event.width = window->floating.w; + wind->pending_size_event.height = window->floating.h; + wl_callback_add_listener(cb, &size_event_listener, (void*)((uintptr_t)window->id)); } void Wayland_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h) @@ -2181,29 +2277,22 @@ void Wayland_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, i void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *wind = window->driverdata; - SDL_VideoData *viddata = _this->driverdata; const char *title = window->title ? window->title : ""; - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - return; - } - #ifdef HAVE_LIBDECOR_H - if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) { - if (!wind->shell_surface.libdecor.frame) { - return; /* Can't do anything yet, wait for ShowWindow */ - } + if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) { libdecor_frame_set_title(wind->shell_surface.libdecor.frame, title); } else #endif - if (viddata->shell.xdg) { - if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { - return; /* Can't do anything yet, wait for ShowWindow */ - } + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && wind->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, title); } +} - WAYLAND_wl_display_flush(viddata->display); +int Wayland_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + WAYLAND_wl_display_roundtrip(_this->driverdata->display); + return 0; } void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y) diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index 0821cd6163901..c1c8a3986ba59 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -95,9 +95,6 @@ struct SDL_WindowData struct wp_viewport *draw_viewport; struct wp_fractional_scale_v1 *fractional_scale; - /* floating dimensions for restoring from maximized and fullscreen */ - int floating_width, floating_height; - SDL_AtomicInt swap_interval_ready; SDL_DisplayData **outputs; @@ -109,18 +106,27 @@ struct SDL_WindowData float windowed_scale_factor; float pointer_scale_x; float pointer_scale_y; + + struct + { + int width, height; + } pending_size_event; + + int last_configure_width, last_configure_height; int requested_window_width, requested_window_height; int drawable_width, drawable_height; int wl_window_width, wl_window_height; int system_min_required_width; int system_min_required_height; SDL_DisplayID last_displayID; - SDL_bool floating; - SDL_bool suspended; - SDL_bool active; - SDL_bool is_fullscreen; - SDL_bool in_fullscreen_transition; - SDL_bool fullscreen_was_positioned; + int fullscreen_deadline_count; + SDL_bool floating : 1; + SDL_bool suspended : 1; + SDL_bool active : 1; + SDL_bool is_fullscreen : 1; + SDL_bool drop_fullscreen_requests : 1; + SDL_bool fullscreen_was_positioned : 1; + SDL_bool show_hide_sync_required : 1; SDL_HitTestResult hit_test_result; }; @@ -128,7 +134,7 @@ struct SDL_WindowData extern void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void Wayland_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, +extern int Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen); extern void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window); @@ -153,5 +159,6 @@ extern int Wayland_SuspendScreenSaver(SDL_VideoDevice *_this); extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern int Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); +extern int Wayland_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_waylandwindow_h_ */ diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 751b32246d1e6..c4e9cf86cfba0 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1009,11 +1009,38 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) #endif /* WM_GETMINMAXINFO */ case WM_WINDOWPOSCHANGING: + { + WINDOWPOS *windowpos = (WINDOWPOS*)lParam; if (data->expected_resize) { returnCode = 0; } - break; + + if (IsIconic(hwnd)) { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); + } else if (IsZoomed(hwnd)) { + if (data->window->flags & SDL_WINDOW_MINIMIZED) { + /* If going from minimized to maximized, send the restored event first. */ + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + } + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); + } else { + SDL_bool was_fixed_size = !!(data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + + /* Send the stored floating size if moving from a fixed-size to floating state. */ + if (was_fixed_size && !(data->window->flags & SDL_WINDOW_FULLSCREEN)) { + int fx, fy, fw, fh; + + WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING); + windowpos->x = fx; + windowpos->y = fy; + windowpos->cx = fw; + windowpos->cy = fh; + windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE); + } + } + } break; case WM_WINDOWPOSCHANGED: { @@ -1082,7 +1109,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) for (win = data->window->first_child; win; win = win->next_sibling) { /* Don't update hidden child windows, their relative position doesn't change */ if (!(win->flags & SDL_WINDOW_HIDDEN)) { - WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE); + WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT); } } } break; @@ -1112,28 +1139,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) KillTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks); } break; - case WM_SIZE: - { - switch (wParam) { - case SIZE_MAXIMIZED: - SDL_SendWindowEvent(data->window, - SDL_EVENT_WINDOW_RESTORED, 0, 0); - SDL_SendWindowEvent(data->window, - SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - break; - case SIZE_MINIMIZED: - SDL_SendWindowEvent(data->window, - SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - break; - case SIZE_RESTORED: - SDL_SendWindowEvent(data->window, - SDL_EVENT_WINDOW_RESTORED, 0, 0); - break; - default: - break; - } - } break; - case WM_SETCURSOR: { Uint16 hittest; diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 9d6330f7a46c4..793eb4ba404ea 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -277,7 +277,8 @@ static SDL_VideoDevice *WIN_CreateDevice(void) device->free = WIN_DeleteDevice; - device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT; + device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; return device; } diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 43dc5a717bc1b..b59d2495b34a3 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -154,7 +154,7 @@ static DWORD GetWindowStyleEx(SDL_Window *window) * Returns arguments to pass to SetWindowPos - the window rect, including frame, in Windows coordinates. * Can be called before we have a HWND. */ -static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current) +static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) { SDL_VideoData *videodata = SDL_GetVideoDevice() ? SDL_GetVideoDevice()->driverdata : NULL; RECT rect; @@ -163,12 +163,26 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m #endif /* Client rect, in points */ - SDL_RelativeToGlobalForWindow(window, - (use_current ? window->x : window->windowed.x), - (use_current ? window->y : window->windowed.y), - x, y); - *width = (use_current ? window->w : window->windowed.w); - *height = (use_current ? window->h : window->windowed.h); + switch (rect_type) { + case SDL_WINDOWRECT_CURRENT: + SDL_RelativeToGlobalForWindow(window,window->x, window->y, x, y); + *width = window->w; + *height = window->h; + break; + case SDL_WINDOWRECT_WINDOWED: + SDL_RelativeToGlobalForWindow(window,window->windowed.x, window->windowed.y, x, y); + *width = window->windowed.w; + *height = window->windowed.h; + break; + case SDL_WINDOWRECT_FLOATING: + SDL_RelativeToGlobalForWindow(window,window->floating.x, window->floating.y, x, y); + *width = window->floating.w; + *height = window->floating.h; + break; + default: + /* Should never be here */ + SDL_assert_release(SDL_FALSE); + } /* Copy the client size in pixels into this rect structure, which we'll then adjust with AdjustWindowRectEx */ @@ -210,16 +224,16 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m #ifdef HIGHDPI_DEBUG SDL_Log("WIN_AdjustWindowRectWithStyle: in: %d, %d, %dx%d, returning: %d, %d, %dx%d, used dpi %d for frame calculation", - (use_current ? window->x : window->windowed.x), - (use_current ? window->y : window->windowed.y), - (use_current ? window->w : window->windowed.w), - (use_current ? window->h : window->windowed.h), + (use_current ? window->requested.x : window->windowed.x), + (use_current ? window->requested.y : window->windowed.y), + (use_current ? window->requested.w : window->windowed.w), + (use_current ? window->requested.h : window->windowed.h), *x, *y, *width, *height, frame_dpi); #endif return 0; } -static void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current) +void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) { SDL_WindowData *data = window->driverdata; HWND hwnd = data->hwnd; @@ -232,10 +246,10 @@ static void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, #else menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); #endif - WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current); + WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, rect_type); } -int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags) +int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type) { SDL_Window *child_window; SDL_WindowData *data = window->driverdata; @@ -252,7 +266,7 @@ int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags) top = HWND_NOTOPMOST; } - WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE); + WIN_AdjustWindowRect(window, &x, &y, &w, &h, rect_type); data->expected_resize = SDL_TRUE; if (SetWindowPos(hwnd, top, x, y, w, h, flags) == 0) { @@ -262,7 +276,7 @@ int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags) /* Update any child windows */ for (child_window = window->first_child; child_window; child_window = child_window->next_sibling) { - if (WIN_SetWindowPositionInternal(child_window, flags) < 0) { + if (WIN_SetWindowPositionInternal(child_window, flags, SDL_WINDOWRECT_CURRENT) < 0) { result = -1; } } @@ -353,7 +367,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */ int x, y; /* Figure out what the window area will be */ - WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE); + WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_WINDOWRECT_FLOATING); data->expected_resize = SDL_TRUE; SetWindowPos(hwnd, NULL, x, y, w, h, data->copybits_flag | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); data->expected_resize = SDL_FALSE; @@ -518,8 +532,8 @@ static void WIN_ConstrainPopup(SDL_Window *window) SDL_Window *w; SDL_DisplayID displayID; SDL_Rect rect; - int abs_x = window->x; - int abs_y = window->y; + int abs_x = window->floating.x; + int abs_y = window->floating.y; int offset_x = 0, offset_y = 0; /* Calculate the total offset from the parents */ @@ -536,17 +550,17 @@ static void WIN_ConstrainPopup(SDL_Window *window) /* Constrain the popup window to the display of the toplevel parent */ displayID = SDL_GetDisplayForWindow(w); SDL_GetDisplayBounds(displayID, &rect); - if (abs_x + window->w > rect.x + rect.w) { - abs_x -= (abs_x + window->w) - (rect.x + rect.w); + if (abs_x + window->floating.w > rect.x + rect.w) { + abs_x -= (abs_x + window->floating.w) - (rect.x + rect.w); } - if (abs_y + window->h > rect.y + rect.h) { - abs_y -= (abs_y + window->h) - (rect.y + rect.h); + if (abs_y + window->floating.h > rect.y + rect.h) { + abs_y -= (abs_y + window->floating.h) - (rect.y + rect.h); } abs_x = SDL_max(abs_x, rect.x); abs_y = SDL_max(abs_y, rect.y); - window->x = window->windowed.x = abs_x - offset_x; - window->y = window->windowed.y = abs_y - offset_y; + window->floating.x = abs_x - offset_x; + window->floating.y = abs_y - offset_y; } } @@ -590,7 +604,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI /* Figure out what the window area will be */ WIN_ConstrainPopup(window); - WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE); + WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_WINDOWRECT_FLOATING); hwnd = CreateWindowEx(styleEx, SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL, SDL_Instance, NULL); @@ -774,13 +788,25 @@ int WIN_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) /* HighDPI support: removed SWP_NOSIZE. If the move results in a DPI change, we need to allow * the window to resize (e.g. AdjustWindowRectExForDpi frame sizes are different). */ - WIN_ConstrainPopup(window); - return WIN_SetWindowPositionInternal(window, window->driverdata->copybits_flag | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { + WIN_ConstrainPopup(window); + return WIN_SetWindowPositionInternal(window, + window->driverdata->copybits_flag | SWP_NOZORDER | SWP_NOOWNERZORDER | + SWP_NOACTIVATE, SDL_WINDOWRECT_FLOATING); + } + } else { + return SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_TRUE); + } + + return 0; } void WIN_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) { - WIN_SetWindowPositionInternal(window, window->driverdata->copybits_flag | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); + if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) { + WIN_SetWindowPositionInternal(window, window->driverdata->copybits_flag | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE, SDL_WINDOWRECT_FLOATING); + } } int WIN_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right) @@ -967,14 +993,24 @@ void WIN_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) void WIN_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) { - /* Other platforms refuse to maximize a non-resizable window, and with win32, - the OS resizes the window weirdly (covering the taskbar) if you don't have - the STYLE_RESIZABLE flag set. So just forbid it for now. */ - if (window->flags & SDL_WINDOW_RESIZABLE) { - SDL_WindowData *data = window->driverdata; - HWND hwnd = data->hwnd; + SDL_WindowData *data = window->driverdata; + HWND hwnd = data->hwnd; + data->expected_resize = SDL_TRUE; + ShowWindow(hwnd, SW_MAXIMIZE); + data->expected_resize = SDL_FALSE; + + /* Clamp the maximized window size to the max window size. + * This is automatic if maximizing from the window controls. + */ + if (window->max_w || window->max_h) { + int fx, fy, fw, fh; + + window->windowed.w = window->max_w ? SDL_min(window->w, window->max_w) : window->windowed.w; + window->windowed.h = window->max_h ? SDL_min(window->h, window->max_h) : window->windowed.h; + WIN_AdjustWindowRect(window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_WINDOWED); + data->expected_resize = SDL_TRUE; - ShowWindow(hwnd, SW_MAXIMIZE); + SetWindowPos(hwnd, HWND_TOP, fx, fy, fw, fh, data->copybits_flag | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOACTIVATE); data->expected_resize = SDL_FALSE; } } @@ -997,7 +1033,7 @@ void WIN_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool data->in_border_change = SDL_TRUE; SetWindowLong(hwnd, GWL_STYLE, style); - WIN_SetWindowPositionInternal(window, data->copybits_flag | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); + WIN_SetWindowPositionInternal(window, data->copybits_flag | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT); data->in_border_change = SDL_FALSE; } @@ -1016,7 +1052,7 @@ void WIN_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool void WIN_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top) { - WIN_SetWindowPositionInternal(window, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + WIN_SetWindowPositionInternal(window, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT); } void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1031,7 +1067,7 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) /** * Reconfigures the window to fill the given display, if fullscreen is true, otherwise restores the window. */ -void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) SDL_DisplayData *displaydata = display->driverdata; @@ -1043,13 +1079,6 @@ void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vid int x, y; int w, h; - if (!fullscreen && (window->flags & SDL_WINDOW_FULLSCREEN)) { - /* Resizing the window on hide causes problems restoring it in Wine, and it's unnecessary. - * Also, Windows would preview the minimized window with the wrong size. - */ - return; - } - #ifdef HIGHDPI_DEBUG SDL_Log("WIN_SetWindowFullscreen: %d", (int)fullscreen); #endif @@ -1060,19 +1089,20 @@ void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vid top = HWND_NOTOPMOST; } - style = GetWindowLong(hwnd, GWL_STYLE); - style &= ~STYLE_MASK; - style |= GetWindowStyle(window); - /* Use GetMonitorInfo instead of WIN_GetDisplayBounds because we want the monitor bounds in Windows coordinates (pixels) rather than SDL coordinates (points). */ SDL_zero(minfo); minfo.cbSize = sizeof(MONITORINFO); if (!GetMonitorInfo(displaydata->MonitorHandle, &minfo)) { SDL_SetError("GetMonitorInfo failed"); - return; + return -1; } + SDL_SendWindowEvent(window, fullscreen ? SDL_EVENT_WINDOW_ENTER_FULLSCREEN : SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + style = GetWindowLong(hwnd, GWL_STYLE); + style &= ~STYLE_MASK; + style |= GetWindowStyle(window); + if (fullscreen) { x = minfo.rcMonitor.left; y = minfo.rcMonitor.top; @@ -1097,11 +1127,14 @@ void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vid */ if (data->windowed_mode_was_maximized && !data->in_window_deactivation) { style |= WS_MAXIMIZE; - data->windowed_mode_was_maximized = SDL_FALSE; } menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); - WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE); + WIN_AdjustWindowRectWithStyle(window, style, menu, + &x, &y, + &w, &h, + data->windowed_mode_was_maximized ? SDL_WINDOWRECT_WINDOWED : SDL_WINDOWRECT_FLOATING); + data->windowed_mode_was_maximized = SDL_FALSE; } SetWindowLong(hwnd, GWL_STYLE, style); data->expected_resize = SDL_TRUE; @@ -1113,6 +1146,7 @@ void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vid #endif #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ + return 0; } #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) @@ -1307,7 +1341,7 @@ void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window) } if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) { - WIN_SetWindowPositionInternal(window, data->copybits_flag | SWP_NOSIZE | SWP_NOACTIVATE); + WIN_SetWindowPositionInternal(window, data->copybits_flag | SWP_NOSIZE | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT); } } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 65e1c03d1060e..0b6ceb92da755 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -34,6 +34,13 @@ extern "C" { #endif +typedef enum SDL_WindowRect +{ + SDL_WINDOWRECT_CURRENT, + SDL_WINDOWRECT_WINDOWED, + SDL_WINDOWRECT_FLOATING +} SDL_WindowRect; + struct SDL_WindowData { SDL_Window *window; @@ -91,7 +98,7 @@ extern void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void WIN_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); extern void WIN_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); extern void WIN_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top); -extern void WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void WIN_UpdateWindowICCProfile(SDL_Window *window, SDL_bool send_event); extern void *WIN_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size); extern void WIN_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); @@ -104,9 +111,10 @@ extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void WIN_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept); extern int WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); extern void WIN_UpdateDarkModeForHWND(HWND hwnd); -extern int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags); +extern int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type); extern void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y); extern int WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); +extern void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 8f6572c8926cc..a48359e48766d 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -76,7 +76,7 @@ static void WINRT_VideoQuit(SDL_VideoDevice *_this); /* Window functions */ static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); static void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); -static void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +static int WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); static void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); /* Misc functions */ @@ -734,12 +734,14 @@ void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) { #if NTDDI_VERSION >= NTDDI_WIN10 SDL_WindowData *data = window->driverdata; - const Windows::Foundation::Size size((float)window->w, (float)window->h); - data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView() + const Windows::Foundation::Size size((float)window->floating.w, (float)window->floating.h); + if (data->appView->TryResizeView(size)) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->floating.w, window->floating.h); + } #endif } -void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) +int WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { #if NTDDI_VERSION >= NTDDI_WIN10 SDL_WindowData *data = window->driverdata; @@ -747,7 +749,7 @@ void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V if (isWindowActive) { if (fullscreen) { if (!data->appView->IsFullScreenMode) { - data->appView->TryEnterFullScreenMode(); // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode() + return data->appView->TryEnterFullScreenMode() ? 0 : -1; } } else { if (data->appView->IsFullScreenMode) { @@ -756,6 +758,8 @@ void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_V } } #endif + + return 0; } void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 512b69a272251..72f6caf1c07a0 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -39,6 +39,7 @@ #include "../../events/SDL_touch_c.h" #include "../../core/linux/SDL_system_theme.h" #include "../../SDL_utils_c.h" +#include "../SDL_sysvideo.h" #include @@ -1330,8 +1331,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) int y = xevent->xconfigure.y; SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, - x, y); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); #ifdef SDL_USE_IME if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { @@ -1342,16 +1342,21 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) for (w = data->window->first_child; w; w = w->next_sibling) { /* Don't update hidden child windows, their relative position doesn't change */ if (!(w->flags & SDL_WINDOW_HIDDEN)) { - X11_UpdateWindowPosition(w); + X11_UpdateWindowPosition(w, SDL_TRUE); } } } if (xevent->xconfigure.width != data->last_xconfigure.width || xevent->xconfigure.height != data->last_xconfigure.height) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, - xevent->xconfigure.width, - xevent->xconfigure.height); + if (!data->skip_size_count) { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, + xevent->xconfigure.width, + xevent->xconfigure.height); + } else { + data->skip_size_count--; + } } + data->last_xconfigure = xevent->xconfigure; } break; @@ -1621,17 +1626,60 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } } - if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } - if ((changed & SDL_WINDOW_MINIMIZED) && (flags & SDL_WINDOW_MINIMIZED)) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - } - if (((changed & SDL_WINDOW_MAXIMIZED) || (changed & SDL_WINDOW_MINIMIZED)) && - (!(flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - } + if (!SDL_WINDOW_IS_POPUP(data->window)) { + if (changed & SDL_WINDOW_FULLSCREEN) { + data->pending_operation &= ~X11_PENDING_OP_FULLSCREEN; + + if (flags & SDL_WINDOW_FULLSCREEN) { + if (!(flags & SDL_WINDOW_MINIMIZED)) { + const SDL_bool commit = data->requested_fullscreen_mode.displayID == 0 || + SDL_memcmp(&data->window->current_fullscreen_mode, &data->requested_fullscreen_mode, sizeof(SDL_DisplayMode)) != 0; + + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); + if (commit) { + /* This was initiated by the compositor, or the mode was changed between the request and the window + * becoming fullscreen. Switch to the application requested mode if necessary. + */ + SDL_copyp(&data->window->current_fullscreen_mode, &data->window->requested_fullscreen_mode); + SDL_UpdateFullscreenMode(data->window, SDL_TRUE, SDL_TRUE); + } else { + SDL_UpdateFullscreenMode(data->window, SDL_TRUE, SDL_FALSE); + } + } + } else { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); + SDL_UpdateFullscreenMode(data->window, SDL_FALSE, SDL_TRUE); + } + if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { + /* Skip the first resize event if the borders are being turned on/off. */ + data->skip_size_count = 1; + } + } + if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { + data->pending_operation &= ~X11_PENDING_OP_MAXIMIZE; + if ((changed & SDL_WINDOW_MINIMIZED)) { + data->pending_operation &= ~X11_PENDING_OP_RESTORE; + /* If coming out of minimized, send a restore event before sending maximized. */ + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + } + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); + } + if ((changed & SDL_WINDOW_MINIMIZED) && (flags & SDL_WINDOW_MINIMIZED)) { + data->pending_operation &= ~X11_PENDING_OP_MINIMIZE; + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); + } + if (!(flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { + data->pending_operation &= ~X11_PENDING_OP_RESTORE; + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + + /* Restore the last known floating state if leaving maximized mode */ + if (!(flags & SDL_WINDOW_FULLSCREEN)) { + X11_XMoveWindow(display, data->xwindow, data->window->floating.x, data->window->floating.y); + X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); + } + } + } if (changed & SDL_WINDOW_OCCLUDED) { SDL_SendWindowEvent(data->window, (flags & SDL_WINDOW_OCCLUDED) ? SDL_EVENT_WINDOW_OCCLUDED : SDL_EVENT_WINDOW_EXPOSED, 0, 0); } @@ -1645,6 +1693,14 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) X11_UpdateKeymap(_this, SDL_TRUE); } else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) { X11_GetBorderValues(data); + if (data->border_top != 0 || data->border_left != 0 || data->border_right != 0 || data->border_bottom != 0) { + /* Adjust if the window size changed to accommodate the borders. */ + if (data->window->flags & SDL_WINDOW_MAXIMIZED) { + X11_XResizeWindow(display, data->xwindow, data->window->windowed.w, data->window->windowed.h); + } else { + X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); + } + } } } break; @@ -1824,6 +1880,22 @@ void X11_PumpEvents(SDL_VideoDevice *_this) XEvent xevent; int i; + /* Check if a display had the mode changed and is waiting for a window to asynchronously become + * fullscreen. If there is no fullscreen window past the elapsed timeout, revert the mode switch. + */ + for (i = 0; i < _this->num_displays; ++i) { + if (_this->displays[i]->driverdata->mode_switch_deadline_ns && + SDL_GetTicksNS() >= _this->displays[i]->driverdata->mode_switch_deadline_ns) { + if (_this->displays[i]->fullscreen_window) { + _this->displays[i]->driverdata->mode_switch_deadline_ns = 0; + } else { + 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); + } + } + } + if (data->last_mode_change_deadline) { if (SDL_GetTicks() >= data->last_mode_change_deadline) { data->last_mode_change_deadline = 0; /* assume we're done. */ diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 15e681766bd7a..0c2812831333e 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -27,6 +27,11 @@ /* #define X11MODES_DEBUG */ +/* Timeout and revert mode switches if the timespan has elapsed without the window becoming fullscreen. + * 5 seconds seems good from testing. + */ +#define MODE_SWITCH_TIMEOUT_NS SDL_NS_PER_SECOND * 5 + /* I'm becoming more and more convinced that the application should never * use XRandR, and it's the window manager's responsibility to track and * manage display modes for fullscreen windows. Right now XRandR is completely @@ -903,6 +908,12 @@ int X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SD viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2); + if (mode != &sdl_display->desktop_mode) { + data->mode_switch_deadline_ns = SDL_GetTicksNS() + MODE_SWITCH_TIMEOUT_NS; + } else { + data->mode_switch_deadline_ns = 0; + } + #ifdef SDL_VIDEO_DRIVER_X11_XRANDR if (data->use_xrandr) { Display *display = viddata->display; diff --git a/src/video/x11/SDL_x11modes.h b/src/video/x11/SDL_x11modes.h index 9d78cb1e103e6..8d0e341fb11ff 100644 --- a/src/video/x11/SDL_x11modes.h +++ b/src/video/x11/SDL_x11modes.h @@ -32,6 +32,8 @@ struct SDL_DisplayData int x; int y; + Uint64 mode_switch_deadline_ns; + SDL_bool use_xrandr; #ifdef SDL_VIDEO_DRIVER_X11_XRANDR diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 6bb5f5c638955..c985427deba82 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -209,6 +209,7 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->FlashWindow = X11_FlashWindow; device->ShowWindowSystemMenu = X11_ShowWindowSystemMenu; device->SetWindowFocusable = X11_SetWindowFocusable; + device->SyncWindow = X11_SyncWindow; #ifdef SDL_VIDEO_DRIVER_X11_XFIXES device->SetWindowMouseRect = X11_SetWindowMouseRect; @@ -274,7 +275,8 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->system_theme = SDL_SystemTheme_Get(); #endif - device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT; + device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; return device; } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 8459d861958da..67a0c877c2a5f 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -169,8 +169,8 @@ static void X11_ConstrainPopup(SDL_Window *window) SDL_Window *w; SDL_DisplayID displayID; SDL_Rect rect; - int abs_x = window->x; - int abs_y = window->y; + int abs_x = window->floating.x; + int abs_y = window->floating.y; int offset_x = 0, offset_y = 0; /* Calculate the total offset from the parents */ @@ -196,8 +196,8 @@ static void X11_ConstrainPopup(SDL_Window *window) abs_x = SDL_max(abs_x, rect.x); abs_y = SDL_max(abs_y, rect.y); - window->x = window->windowed.x = abs_x - offset_x; - window->y = window->windowed.y = abs_y - offset_y; + window->floating.x = window->windowed.x = abs_x - offset_x; + window->floating.y = window->windowed.y = abs_y - offset_y; } } @@ -352,11 +352,11 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) X11_XGetWindowAttributes(data->videodata->display, w, &attrib); if (!SDL_WINDOW_IS_POPUP(window)) { - window->x = attrib.x; - window->y = attrib.y; + window->x = data->expected.x = attrib.x; + window->y = data->expected.y = attrib.y - data->border_top; } - window->w = attrib.width; - window->h = attrib.height; + window->w = data->expected.w = attrib.width; + window->h = data->expected.h = attrib.height; if (attrib.map_state != IsUnmapped) { window->flags &= ~SDL_WINDOW_HIDDEN; } else { @@ -611,7 +611,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI X11_ConstrainPopup(window); } SDL_RelativeToGlobalForWindow(window, - window->windowed.x, window->windowed.y, + window->floating.x, window->floating.y, &win_x, &win_y); /* Always create this with the window->windowed.* fields; if we're @@ -621,7 +621,7 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI migration to fullscreen after CreateSDLWindow returns, which will put all the SDL_Window fields and system state as expected. */ w = X11_XCreateWindow(display, RootWindow(display, screen), - win_x, win_y, window->windowed.w, window->windowed.h, + win_x, win_y, window->floating.w, window->floating.h, 0, depth, InputOutput, visual, (CWOverrideRedirect | CWBackPixmap | CWBorderPixel | CWBackingStore | CWColormap), @@ -847,90 +847,44 @@ static int X11_CatchAnyError(Display *d, XErrorEvent *e) return 0; } -enum check_method -{ - COMPARE_POSITION = 1, - COMPARE_SIZE = 2, - COMPARE_DOUBLE_ATTEMPT = 3, - COMPARE_ORIG = 4, - COMPARE_NO_WAIT = 5 -}; /* Wait a brief time, or not, to see if the window manager decided to move/resize the window. * Send MOVED and RESIZED window events */ -static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, enum check_method method, - int orig_x, int orig_y, int dest_x, int dest_y, - int orig_w, int orig_h, int dest_w, int dest_h) +static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int param_timeout) { SDL_WindowData *data = window->driverdata; Display *display = data->videodata->display; - Window xwindow = data->xwindow; int (*prev_handler)(Display *, XErrorEvent *); - int x, y; - XWindowAttributes attrs; Uint64 timeout = 0; - Window childReturn, root, parent; - Window *children; - unsigned int childCount; - SDL_bool window_size_changed = SDL_FALSE; - int window_position_changed = 0; + int ret = 0; X11_XSync(display, False); prev_handler = X11_XSetErrorHandler(X11_CatchAnyError); - if (method != COMPARE_NO_WAIT) { + if (param_timeout) { timeout = SDL_GetTicks() + param_timeout; } - /* Get the parent */ - X11_XQueryTree(display, xwindow, &root, &parent, &children, &childCount); - while (SDL_TRUE) { - caught_x11_error = SDL_FALSE; X11_XSync(display, False); - X11_XGetWindowAttributes(display, xwindow, &attrs); - X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display), - attrs.x, attrs.y, &x, &y, &childReturn); + X11_PumpEvents(_this); - if (method == COMPARE_NO_WAIT) { + if (window->x == data->expected.x && window->y == data->expected.y && + window->w == data->expected.w && window->h == data->expected.h && + data->pending_operation == X11_PENDING_OP_NONE) { + /* The window is where it is wanted and nothing is pending. Done. */ break; } - if (!caught_x11_error) { - if (method == COMPARE_POSITION) { - if (x != orig_x || y != orig_y) { - break; /* window moved, time to go. */ - } else if (x == dest_x && y == dest_y) { - break; /* we're at the place we wanted to be anyhow, drop out. */ - } - } else if (method == COMPARE_SIZE) { - if (attrs.width != orig_w || attrs.height != orig_h) { - break; /* window changed, time to go. */ - } else if (attrs.width == window->w && attrs.height == window->h) { - break; /* we've size we wanted anyhow, drop out. */ - } - } else if (method == COMPARE_ORIG) { - if (x != orig_x || y != orig_y || attrs.width != orig_w || attrs.height != orig_h) { - break; /* window moved or resized, time to go. */ - } - } else if (method == COMPARE_DOUBLE_ATTEMPT) { - if (x != orig_x || y != orig_y) { - orig_x = x; - orig_y = y; - window_position_changed += 1; - } - if (attrs.width != orig_w || attrs.height != orig_h) { - orig_w = attrs.width; - orig_h = attrs.height; - window_size_changed = SDL_TRUE; - } - /* Wait for at least 2 moves + 1 size changed to have valid values */ - if (window_position_changed >= 2 && window_size_changed) { - break; /* window changed, time to go. */ - } - } - } - if (SDL_GetTicks() >= timeout) { + /* Timed out without the expected values. Update the requested data so future sync calls won't block. */ + data->expected.x = window->x; + data->expected.y = window->y; + data->expected.w = window->w; + data->expected.h = window->h; + + data->pending_operation = X11_PENDING_OP_NONE; + + ret = 1; break; } @@ -938,16 +892,15 @@ static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, e } if (!caught_x11_error) { - if (SDL_WINDOW_IS_POPUP(window)) { - SDL_GlobalToRelativeForWindow(window, x, y, &x, &y); - } - - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); + X11_PumpEvents(_this); + } else { + ret = -1; } X11_XSetErrorHandler(prev_handler); caught_x11_error = SDL_FALSE; + + return ret; } int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon) @@ -1008,45 +961,41 @@ int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i return rc; } -void X11_UpdateWindowPosition(SDL_Window *window) +void X11_UpdateWindowPosition(SDL_Window *window, SDL_bool use_current_position) { - SDL_Window *w; SDL_WindowData *data = window->driverdata; Display *display = data->videodata->display; - unsigned int childCount; - Window childReturn, root, parent; - Window *children; - XWindowAttributes attrs; - int dest_x, dest_y; - int orig_x, orig_y; - - X11_XSync(display, False); - X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount); - X11_XGetWindowAttributes(display, data->xwindow, &attrs); - X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display), - attrs.x, attrs.y, &orig_x, &orig_y, &childReturn); + const int rel_x = use_current_position ? window->x : window->floating.x; + const int rel_y = use_current_position ? window->y : window->floating.y; SDL_RelativeToGlobalForWindow(window, - window->x - data->border_left, window->y - data->border_top, - &dest_x, &dest_y); + rel_x - data->border_left, rel_y - data->border_top, + &data->expected.x, &data->expected.y); /* Attempt to move the window */ - X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); - - /* Send MOVED/RESIZED event, if needed. Compare with initial/expected position. Timeout 100 */ - X11_WaitAndSendWindowEvents(window, 100, COMPARE_POSITION, orig_x, orig_y, dest_x, dest_y, 0, 0, 0, 0); - - for (w = window->first_child; w; w = w->next_sibling) { - X11_UpdateWindowPosition(w); - } + X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); } int X11_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) { - if (SDL_WINDOW_IS_POPUP(window)) { - X11_ConstrainPopup(window); + /* Sync any pending fullscreen or maximize events. */ + if (window->driverdata->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE)) { + X11_SyncWindow(_this, window); + } + + /* Position will be set when window is de-maximized */ + if (window->flags & SDL_WINDOW_MAXIMIZED) { + return 0; + } + + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + if (SDL_WINDOW_IS_POPUP(window)) { + X11_ConstrainPopup(window); + } + X11_UpdateWindowPosition(window, SDL_FALSE); + } else { + SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_TRUE); } - X11_UpdateWindowPosition(window); return 0; } @@ -1074,10 +1023,10 @@ static void X11_SetWMNormalHints(SDL_VideoDevice *_this, SDL_Window *window, XSi hide/show, because there are supposedly subtle problems with doing so and transitioning from windowed to fullscreen in Unity. */ - X11_XResizeWindow(display, data->xwindow, window->w, window->h); + X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); SDL_RelativeToGlobalForWindow(window, - window->x - data->border_left, - window->y - data->border_top, + window->floating.x - data->border_left, + window->floating.y - data->border_top, &dest_x, &dest_y); X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); X11_XRaiseWindow(display, data->xwindow); @@ -1133,45 +1082,42 @@ void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->driverdata; Display *display = data->videodata->display; - XWindowAttributes attrs; - int orig_w, orig_h; - X11_XSync(display, False); - X11_XGetWindowAttributes(display, data->xwindow, &attrs); - orig_w = attrs.width; - orig_h = attrs.height; + /* Wait for pending maximize operations to complete, or the window can end up in a weird, + * partially-maximized state. + */ + if (data->pending_operation & (X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_FULLSCREEN)) { + X11_SyncWindow(_this, window); + } + + /* Don't try to resize a maximized or fullscreen window, it will be done on restore. */ + if (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN)) { + return; + } if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus - we must set the size hints to adjust the window size. */ - XSizeHints *sizehints = X11_XAllocSizeHints(); - long userhints; + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus + * we must set the size hints to adjust the window size. + */ + XSizeHints *sizehints = X11_XAllocSizeHints(); + long userhints; - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); + X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); - sizehints->min_width = sizehints->max_width = window->w; - sizehints->min_height = sizehints->max_height = window->h; - sizehints->flags |= PMinSize | PMaxSize; + sizehints->min_width = sizehints->max_width = window->floating.w; + sizehints->min_height = sizehints->max_height = window->floating.h; + sizehints->flags |= PMinSize | PMaxSize; - X11_SetWMNormalHints(_this, window, sizehints); + X11_SetWMNormalHints(_this, window, sizehints); - X11_XFree(sizehints); + X11_XFree(sizehints); + } } else { - X11_XResizeWindow(display, data->xwindow, window->w, window->h); + data->expected.w = window->floating.w; + data->expected.h = window->floating.h; + X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); } - - /* Timeout occurred and window size didn't change - * window manager likely denied the resize, - * or the new size is the same as the existing: - * - current width: is 'full width'. - * - try to set new width at 'full width + 1', which get truncated to 'full width'. - * - new width is/remains 'full width' - * So, even if we break here as a timeout, we can send an event, since the requested size isn't the same - * as the final size. (even if final size is same as original size). - */ - - /* Send MOVED/RESIZED event, if needed. Compare with initial/expected size. Timeout 100 */ - X11_WaitAndSendWindowEvents(window, 100, COMPARE_SIZE, 0, 0, 0, 0, orig_w, orig_h, window->w, window->h); } int X11_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right) @@ -1256,7 +1202,7 @@ void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); /* Make sure the window manager didn't resize our window for the difference. */ - X11_XResizeWindow(display, data->xwindow, window->w, window->h); + X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); X11_XSync(display, False); } @@ -1330,7 +1276,7 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) if (window->parent) { /* Update our position in case our parent moved while we were hidden */ - X11_UpdateWindowPosition(window); + X11_UpdateWindowPosition(window, SDL_TRUE); } /* Whether XMapRaised focuses the window is based on the window type and it is @@ -1365,6 +1311,12 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) /* Get some valid border values, if we haven't them yet */ if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) { X11_GetBorderValues(data); + + if (!data->initial_border_adjustment) { + data->expected.x += data->border_left; + data->expected.y += data->border_top; + data->initial_border_adjustment = SDL_TRUE; + } } } @@ -1398,8 +1350,8 @@ void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - /* Send MOVED/RESIZED event, if needed. Immediate, no timeout */ - X11_WaitAndSendWindowEvents(window, 0, COMPARE_NO_WAIT, 0, 0, 0, 0, 0, 0, 0, 0); + X11_XSync(display, False); + X11_PumpEvents(_this); } static void X11_SetWindowActive(SDL_VideoDevice *_this, SDL_Window *window) @@ -1452,36 +1404,17 @@ static void X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, S Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT; Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ; - if (maximized) { - window->flags |= SDL_WINDOW_MAXIMIZED; - } else { - window->flags &= ~SDL_WINDOW_MAXIMIZED; - - if (window->flags & SDL_WINDOW_FULLSCREEN) { - /* Fullscreen windows are maximized on some window managers, - and this is functional behavior, so don't remove that state - now, we'll take care of it when we leave fullscreen mode. - */ - return; - } + if (!maximized && window->flags & SDL_WINDOW_FULLSCREEN) { + /* Fullscreen windows are maximized on some window managers, + and this is functional behavior, so don't remove that state + now, we'll take care of it when we leave fullscreen mode. + */ + return; } if (X11_IsWindowMapped(_this, window)) { - XWindowAttributes attrs; - Window childReturn, root, parent; - Window *children; - unsigned int childCount; - int orig_w, orig_h, orig_x, orig_y; XEvent e; - X11_XSync(display, False); - X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount); - X11_XGetWindowAttributes(display, data->xwindow, &attrs); - X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display), - attrs.x, attrs.y, &orig_x, &orig_y, &childReturn); - orig_w = attrs.width; - orig_h = attrs.height; - SDL_zero(e); e.xany.type = ClientMessage; e.xclient.message_type = _NET_WM_STATE; @@ -1493,12 +1426,26 @@ static void X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, S e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ; e.xclient.data.l[3] = 0l; - X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, - SubstructureNotifyMask | SubstructureRedirectMask, &e); + if (maximized) { + SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); + SDL_Rect bounds; - /* Send MOVED/RESIZED event, if needed. Compare with initial position and size. Timeout 1000 */ - X11_WaitAndSendWindowEvents(window, 1000, COMPARE_ORIG, orig_x, orig_y, 0, 0, orig_w, orig_h, 0, 0); + SDL_zero(bounds); + SDL_GetDisplayUsableBounds(displayID, &bounds); + data->expected.x = bounds.x + data->border_left; + data->expected.y = bounds.y + data->border_top; + data->expected.w = bounds.w - (data->border_left + data->border_right); + data->expected.h = bounds.h - (data->border_top + data->border_bottom); + } else { + data->expected.x = window->floating.x; + data->expected.y = window->floating.y; + data->expected.w = window->floating.w; + data->expected.h = window->floating.h; + } + + X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, + SubstructureNotifyMask | SubstructureRedirectMask, &e); } else { X11_SetNetWMState(_this, data->xwindow, window->flags); } @@ -1507,7 +1454,14 @@ static void X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, S void X11_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) { - X11_SetWindowMaximized(_this, window, SDL_TRUE); + if (window->driverdata->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MINIMIZE)) { + SDL_SyncWindow(window); + } + + if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MINIMIZED))) { + window->driverdata->pending_operation |= X11_PENDING_OP_MAXIMIZE; + X11_SetWindowMaximized(_this, window, SDL_TRUE); + } } void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1516,19 +1470,33 @@ void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); Display *display = data->videodata->display; + data->pending_operation |= X11_PENDING_OP_MINIMIZE; + data->window_was_maximized = !!(window->flags & SDL_WINDOW_MAXIMIZED); X11_XIconifyWindow(display, data->xwindow, displaydata->screen); X11_XFlush(display); } void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { - X11_SetWindowMaximized(_this, window, SDL_FALSE); + if (window->driverdata->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MINIMIZE)) { + SDL_SyncWindow(window); + } + + if (window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED) || + (window->driverdata->pending_operation & X11_PENDING_OP_MINIMIZE)) { + window->driverdata->pending_operation |= X11_PENDING_OP_RESTORE; + } + + /* If the window was minimized while maximized, restore as maximized. */ + const SDL_bool maximize = !!(window->flags & SDL_WINDOW_MINIMIZED) && window->driverdata->window_was_maximized; + window->driverdata->window_was_maximized = SDL_FALSE; + X11_SetWindowMaximized(_this, window, maximize); X11_ShowWindow(_this, window); X11_SetWindowActive(_this, window); } /* This asks the Window Manager to handle fullscreen for us. This is the modern way. */ -static void X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen) +static int X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen) { SDL_WindowData *data = window->driverdata; SDL_DisplayData *displaydata = _display->driverdata; @@ -1538,19 +1506,16 @@ static void X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *win if (X11_IsWindowMapped(_this, window)) { XEvent e; - unsigned int childCount; - Window childReturn, root, parent; - Window *children; - XWindowAttributes attrs; - int orig_w, orig_h, orig_x, orig_y; - X11_XSync(display, False); - X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount); - X11_XGetWindowAttributes(display, data->xwindow, &attrs); - X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display), - attrs.x, attrs.y, &orig_x, &orig_y, &childReturn); - orig_w = attrs.width; - orig_h = attrs.height; + /* Flush any pending fullscreen events. */ + if (data->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE)) { + X11_SyncWindow(_this, window); + } + + /* Nothing to do */ + if (!fullscreen && !(window->flags & SDL_WINDOW_FULLSCREEN)) { + return 0; + } if (!(window->flags & SDL_WINDOW_RESIZABLE)) { /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we @@ -1585,20 +1550,36 @@ static void X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *win X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); + if (!!(window->flags & SDL_WINDOW_FULLSCREEN) != fullscreen) { + data->pending_operation |= X11_PENDING_OP_FULLSCREEN; + } + /* Set the position so the window will be on the target display */ if (fullscreen) { + SDL_copyp(&data->requested_fullscreen_mode, &window->current_fullscreen_mode); + if (data->requested_fullscreen_mode.displayID == 0) { + data->requested_fullscreen_mode.displayID = _display->id; + } + if (fullscreen != !!(window->flags & SDL_WINDOW_FULLSCREEN)) { + data->window_was_maximized = !!(window->flags & SDL_WINDOW_MAXIMIZED); + } + data->expected.x = displaydata->x; + data->expected.y = displaydata->y; + data->expected.w = _display->current_mode->w; + data->expected.h = _display->current_mode->h; X11_XMoveWindow(display, data->xwindow, displaydata->x, displaydata->y); - } + } else { + SDL_zero(data->requested_fullscreen_mode); - /* Fullscreen windows sometimes end up being marked maximized by - window managers. Force it back to how we expect it to be. */ - if (!fullscreen) { + /* Fullscreen windows sometimes end up being marked maximized by + * window managers. Force it back to how we expect it to be. + */ SDL_zero(e); e.xany.type = ClientMessage; e.xclient.message_type = _NET_WM_STATE; e.xclient.format = 32; e.xclient.window = data->xwindow; - if (window->flags & SDL_WINDOW_MAXIMIZED) { + if (data->window_was_maximized) { e.xclient.data.l[0] = _NET_WM_STATE_ADD; } else { e.xclient.data.l[0] = _NET_WM_STATE_REMOVE; @@ -1608,22 +1589,23 @@ static void X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *win e.xclient.data.l[3] = 0l; X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); - } - if (!fullscreen) { - int dest_x = 0, dest_y = 0; - SDL_RelativeToGlobalForWindow(window, - window->windowed.x - data->border_left, window->windowed.y - data->border_top, - &dest_x, &dest_y); + if (!data->window_was_maximized) { + /* Attempt to move the window back to where it was. */ + SDL_RelativeToGlobalForWindow(window, + window->floating.x - data->border_left, window->floating.y - data->border_top, + &data->expected.x, &data->expected.y); - /* Attempt to move the window */ - X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); - } - - /* Send MOVED/RESIZED event, if needed. Compare with initial position and size. Timeout 100 */ - /* Wait for at least 2 moves + 1 size changed to have valid values */ - X11_WaitAndSendWindowEvents(window, 100, COMPARE_DOUBLE_ATTEMPT, orig_x, orig_y, 0, 0, orig_w, orig_h, 0, 0); + data->expected.w = window->floating.w; + data->expected.h = window->floating.h; + X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); + /* If the window is bordered, the size will be set when the borders turn themselves back on. */ + if (window->flags & SDL_WINDOW_BORDERLESS) { + X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); + } + } + } } else { Uint32 flags; @@ -1644,12 +1626,12 @@ static void X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *win } } - X11_XFlush(display); + return 1; } -void X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen) +int X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen) { - X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen); + return X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen); } typedef struct @@ -1980,6 +1962,15 @@ void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y) X11_XFlush(display); } +int X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + /* 100ms is fine for most cases, but, for some reason, maximizing + * a window can take a very long time. + */ + const int timeout = window->driverdata->pending_operation & SDL_WINDOW_MAXIMIZED ? 1000 : 100; + return X11_SyncWindowTimeout(_this, window, timeout); +} + int X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable) { SDL_WindowData *data = window->driverdata; diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index d1f5b8b67a099..32130f2298412 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -78,6 +78,22 @@ struct SDL_WindowData SDL_bool pointer_barrier_active; PointerBarrier barrier[4]; SDL_Rect barrier_rect; + + SDL_Rect expected; + SDL_DisplayMode requested_fullscreen_mode; + + enum + { + X11_PENDING_OP_NONE = 0x00, + X11_PENDING_OP_RESTORE = 0x01, + X11_PENDING_OP_MINIMIZE = 0x02, + X11_PENDING_OP_MAXIMIZE = 0x04, + X11_PENDING_OP_FULLSCREEN = 0x08 + } pending_operation; + + SDL_bool initial_border_adjustment; + SDL_bool window_was_maximized; + int skip_size_count; #endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ SDL_HitTestResult hit_test_result; }; @@ -106,7 +122,7 @@ extern void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); extern void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered); extern void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable); extern void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top); -extern void X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); +extern int X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen); extern void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size); extern void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); extern void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); @@ -115,9 +131,10 @@ extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void X11_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept); extern int X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); extern void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y); +extern int X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window); extern int X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); int SDL_X11_SetWindowTitle(Display *display, Window xwindow, char *title); -void X11_UpdateWindowPosition(SDL_Window *window); +void X11_UpdateWindowPosition(SDL_Window *window, SDL_bool use_current_position); #endif /* SDL_x11window_h_ */ diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 50b88cdceed86..46ba4e37433c9 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -13,9 +13,11 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) { SDL_Window *window; + SDL_Event event; int w, h; SDL_WindowFlags flags; SDL_bool needs_renderer = SDL_FALSE; + SDL_bool needs_events_pumped = SDL_FALSE; /* Standard window */ w = SDLTest_RandomIntegerInRange(320, 1024); @@ -37,6 +39,9 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) { needs_renderer = SDL_TRUE; } + + /* X11 needs the initial events pumped, or it can erroneously deliver old configuration events at a later time. */ + needs_events_pumped = SDL_TRUE; } if (needs_renderer) { @@ -55,6 +60,12 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) } } + if (needs_events_pumped) { + /* Pump out the event queue */ + while (SDL_PollEvent(&event)) { + } + } + return window; } @@ -551,14 +562,19 @@ static int video_getSetWindowGrab(void *arg) * so that it can be "grabbed" */ SDL_RaiseWindow(window); - { + if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)) { + int count = 0; SDL_Event evt; SDL_zero(evt); - while (SDL_PollEvent(&evt)) { - if (evt.type == SDL_EVENT_WINDOW_FOCUS_GAINED) { - hasFocusGained = SDL_TRUE; + while (!hasFocusGained && count++ < 3) { + while (SDL_PollEvent(&evt)) { + if (evt.type == SDL_EVENT_WINDOW_FOCUS_GAINED) { + hasFocusGained = SDL_TRUE; + } } } + } else { + hasFocusGained = SDL_TRUE; } SDLTest_AssertCheck(hasFocusGained == SDL_TRUE, "Expectded window with focus"); @@ -821,10 +837,13 @@ static int video_getSetWindowPosition(void *arg) { const char *title = "video_getSetWindowPosition Test Window"; SDL_Window *window; + int result; + int maxxVariation, maxyVariation; int xVariation, yVariation; int referenceX, referenceY; int currentX, currentY; int desiredX, desiredY; + SDL_Rect display_bounds; /* Call against new test window */ window = createVideoSuiteTestWindow(title); @@ -832,17 +851,47 @@ static int video_getSetWindowPosition(void *arg) return TEST_ABORTED; } - for (xVariation = 0; xVariation < 4; xVariation++) { - for (yVariation = 0; yVariation < 4; yVariation++) { + /* Sanity check */ + SDL_GetWindowPosition(window, ¤tX, ¤tY); + if (SDL_SetWindowPosition(window, currentX, currentY) < 0) { + SDLTest_Log("Skipping window positioning tests: %s reports window positioning as unsupported", SDL_GetCurrentVideoDriver()); + goto null_tests; + } + + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + /* The X11 server allows arbitrary window placement, but compositing + * window managers such as GNOME and KDE force windows to be within + * desktop bounds. + */ + maxxVariation = 2; + maxyVariation = 2; + + SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &display_bounds); + } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "cocoa") == 0) { + /* Platform doesn't allow windows with negative Y desktop bounds */ + maxxVariation = 4; + maxyVariation = 3; + + SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &display_bounds); + } else { + /* Platform allows windows to be placed out of bounds */ + maxxVariation = 4; + maxyVariation = 4; + + SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &display_bounds); + } + + for (xVariation = 0; xVariation < maxxVariation; xVariation++) { + for (yVariation = 0; yVariation < maxyVariation; yVariation++) { switch (xVariation) { default: case 0: /* Zero X Position */ - desiredX = 0; + desiredX = display_bounds.x > 0 ? display_bounds.x : 0; break; case 1: /* Random X position inside screen */ - desiredX = SDLTest_RandomIntegerInRange(1, 100); + desiredX = SDLTest_RandomIntegerInRange(display_bounds.x + 1, display_bounds.x + 100); break; case 2: /* Random X position outside screen (positive) */ @@ -857,15 +906,15 @@ static int video_getSetWindowPosition(void *arg) switch (yVariation) { default: case 0: - /* Zero X Position */ - desiredY = 0; + /* Zero Y Position */ + desiredY = display_bounds.y > 0 ? display_bounds.y : 0; break; case 1: - /* Random X position inside screen */ - desiredY = SDLTest_RandomIntegerInRange(1, 100); + /* Random Y position inside screen */ + desiredY = SDLTest_RandomIntegerInRange(display_bounds.y + 1, display_bounds.y + 100); break; case 2: - /* Random X position outside screen (positive) */ + /* Random Y position outside screen (positive) */ desiredY = SDLTest_RandomIntegerInRange(10000, 11000); break; case 3: @@ -878,6 +927,10 @@ static int video_getSetWindowPosition(void *arg) SDL_SetWindowPosition(window, desiredX, desiredY); SDLTest_AssertPass("Call to SDL_SetWindowPosition(...,%d,%d)", desiredX, desiredY); + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + /* Get position */ currentX = desiredX + 1; currentY = desiredY + 1; @@ -891,9 +944,9 @@ static int video_getSetWindowPosition(void *arg) SDL_bool hasEvent; /* SDL_SetWindowPosition() and SDL_SetWindowSize() will make requests of the window manager and set the internal position and size, * and then we get events signaling what actually happened, and they get passed on to the application if they're not what we expect. */ - desiredX = currentX + 1; - desiredY = currentY + 1; - hasEvent = getPositionFromEvent(&desiredX, &desiredY); + currentX = desiredX + 1; + currentY = desiredY + 1; + hasEvent = getPositionFromEvent(¤tX, ¤tY); SDLTest_AssertCheck(hasEvent == SDL_TRUE, "Changing position was not honored by WM, checking present of SDL_EVENT_WINDOW_MOVED"); if (hasEvent) { SDLTest_AssertCheck(desiredX == currentX, "Verify returned X position is the position from SDL event; expected: %d, got: %d", desiredX, currentX); @@ -915,6 +968,8 @@ static int video_getSetWindowPosition(void *arg) } } +null_tests: + /* Dummy call with both pointers NULL */ SDL_GetWindowPosition(window, NULL, NULL); SDLTest_AssertPass("Call to SDL_GetWindowPosition(&x=NULL,&y=NULL)"); @@ -989,9 +1044,13 @@ static int video_getSetWindowSize(void *arg) int referenceW, referenceH; int currentW, currentH; int desiredW, desiredH; + const SDL_bool restoreHint = SDL_GetHintBoolean("SDL_BORDERLESS_RESIZABLE_STYLE", SDL_TRUE); + + /* Win32 borderless windows are not resizable by default and need this undocumented hint */ + SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1"); /* Get display bounds for size range */ - result = SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &display); + result = SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &display); SDLTest_AssertPass("SDL_GetDisplayBounds()"); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); if (result != 0) { @@ -1004,15 +1063,22 @@ static int video_getSetWindowSize(void *arg) return TEST_ABORTED; } -#ifdef __WIN32__ - /* Platform clips window size to screen size */ - maxwVariation = 4; - maxhVariation = 4; -#else - /* Platform allows window size >= screen size */ - maxwVariation = 5; - maxhVariation = 5; -#endif + SDL_GetWindowSize(window, ¤tW, ¤tH); + if (SDL_SetWindowSize(window, currentW, currentH)) { + SDLTest_Log("Skipping window resize tests: %s reports window resizing as unsupported", SDL_GetCurrentVideoDriver()); + goto null_tests; + } + + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "windows") == 0 || + SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + /* Platform clips window size to screen size */ + maxwVariation = 4; + maxhVariation = 4; + } else { + /* Platform allows window size >= screen size */ + maxwVariation = 5; + maxhVariation = 5; + } for (wVariation = 0; wVariation < maxwVariation; wVariation++) { for (hVariation = 0; hVariation < maxhVariation; hVariation++) { @@ -1068,6 +1134,11 @@ static int video_getSetWindowSize(void *arg) SDL_SetWindowSize(window, desiredW, desiredH); SDLTest_AssertPass("Call to SDL_SetWindowSize(...,%d,%d)", desiredW, desiredH); + /* The sync may time out if changing the size changes the window position. */ + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result >= 0, "Verify return value; expected: >=0, got: %d", result); + /* Get size */ currentW = desiredW + 1; currentH = desiredH + 1; @@ -1081,9 +1152,9 @@ static int video_getSetWindowSize(void *arg) SDL_bool hasEvent; /* SDL_SetWindowPosition() and SDL_SetWindowSize() will make requests of the window manager and set the internal position and size, * and then we get events signaling what actually happened, and they get passed on to the application if they're not what we expect. */ - desiredW = currentW + 1; - desiredH = currentH + 1; - hasEvent = getSizeFromEvent(&desiredW, &desiredH); + currentW = desiredW + 1; + currentH = desiredH + 1; + hasEvent = getSizeFromEvent(¤tW, ¤tH); SDLTest_AssertCheck(hasEvent == SDL_TRUE, "Changing size was not honored by WM, checking presence of SDL_EVENT_WINDOW_RESIZED"); if (hasEvent) { SDLTest_AssertCheck(desiredW == currentW, "Verify returned width is the one from SDL event; expected: %d, got: %d", desiredW, currentW); @@ -1106,6 +1177,8 @@ static int video_getSetWindowSize(void *arg) } } +null_tests: + /* Dummy call with both pointers NULL */ SDL_GetWindowSize(window, NULL, NULL); SDLTest_AssertPass("Call to SDL_GetWindowSize(&w=NULL,&h=NULL)"); @@ -1154,6 +1227,9 @@ static int video_getSetWindowSize(void *arg) SDLTest_AssertPass("Call to SDL_SetWindowSize(window=NULL)"); checkInvalidWindowError(); + /* Restore the hint to the previous value */ + SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", restoreHint ? "1" : "0"); + return TEST_COMPLETED; } @@ -1694,6 +1770,7 @@ static int video_setWindowCenteredOnDisplay(void *arg) SDL_SetNumberProperty(props, "w", y); SDL_SetNumberProperty(props, "width", w); SDL_SetNumberProperty(props, "height", h); + SDL_SetBooleanProperty(props, "borderless", SDL_TRUE); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); @@ -1741,6 +1818,10 @@ static int video_setWindowCenteredOnDisplay(void *arg) result = SDL_SetWindowFullscreen(window, SDL_TRUE); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + /* Check we are filling the full display */ currentDisplay = SDL_GetDisplayForWindow(window); SDL_GetWindowSize(window, ¤tW, ¤tH); @@ -1764,6 +1845,10 @@ static int video_setWindowCenteredOnDisplay(void *arg) result = SDL_SetWindowFullscreen(window, SDL_FALSE); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + /* Check window was restored correctly */ currentDisplay = SDL_GetDisplayForWindow(window); SDL_GetWindowSize(window, ¤tW, ¤tH); @@ -1793,6 +1878,10 @@ static int video_setWindowCenteredOnDisplay(void *arg) expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2)); SDL_SetWindowPosition(window, x, y); + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + currentDisplay = SDL_GetDisplayForWindow(window); SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); @@ -1822,6 +1911,367 @@ static int video_setWindowCenteredOnDisplay(void *arg) return TEST_COMPLETED; } +/** + * Tests calls to SDL_MaximizeWindow(), SDL_RestoreWindow(), and SDL_SetWindowFullscreen(), + * interspersed with calls to set the window size and position, and verifies the flags, + * sizes, and positions of maximized, fullscreen, and restored windows. + * + * NOTE: This test is good on Mac, Win32, GNOME, and KDE (Wayland and X11). Other *nix + * desktops, particularly tiling desktops, may not support the expected behavior, + * so don't be surprised if this fails. + */ +static int video_getSetWindowState(void *arg) +{ + const char *title = "video_getSetWindowState Test Window"; + SDL_Window *window; + int result; + SDL_Rect display; + Uint32 flags; + int windowedX, windowedY; + int currentX, currentY; + int desiredX = 0, desiredY = 0; + int windowedW, windowedH; + int currentW, currentH; + int desiredW = 0, desiredH = 0; + Uint32 skipFlags = 0; + const SDL_bool restoreHint = SDL_GetHintBoolean("SDL_BORDERLESS_RESIZABLE_STYLE", SDL_TRUE); + const SDL_bool skipPos = SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; + + /* This test is known to be good only on GNOME and KDE. At the time of writing, Weston seems to have maximize related bugs + * that prevent it from running correctly (no configure events are received when unsetting maximize), and tiling window + * managers such as Sway have fundamental behavioral differences that conflict with it. + * + * Other desktops can be enabled in the future as required. + */ + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + const char *desktop = SDL_getenv("XDG_CURRENT_DESKTOP"); + if (SDL_strcmp(desktop, "GNOME") != 0 && SDL_strcmp(desktop, "KDE") != 0) { + SDLTest_Log("Skipping test video_getSetWindowState: desktop environment %s not supported", desktop); + return TEST_SKIPPED; + } + } + + /* Win32 borderless windows are not resizable by default and need this undocumented hint */ + SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1"); + + /* Call against new test window */ + window = createVideoSuiteTestWindow(title); + if (!window) { + return TEST_ABORTED; + } + + SDL_GetWindowSize(window, &windowedW, &windowedH); + SDLTest_AssertPass("SDL_GetWindowSize()"); + + SDL_GetWindowPosition(window, &windowedX, &windowedY); + SDLTest_AssertPass("SDL_GetWindowPosition()"); + + if (skipPos) { + SDLTest_Log("Skipping positioning tests: %s reports window positioning as unsupported", SDL_GetCurrentVideoDriver()); + } + + /* Maximize and check the dimensions */ + result = SDL_MaximizeWindow(window); + SDLTest_AssertPass("SDL_MaximizeWindow()"); + if (result < 0) { + SDLTest_Log("Skipping state transition tests: %s reports window maximizing as unsupported", SDL_GetCurrentVideoDriver()); + skipFlags |= SDL_WINDOW_MAXIMIZED; + goto minimize_test; + } + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(flags & SDL_WINDOW_MAXIMIZED, "Verify the `SDL_WINDOW_MAXIMIZED` flag is set: %s", (flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + /* Check that the maximized window doesn't extend beyond the usable display bounds. + * FIXME: Maximizing Win32 borderless windows is broken, so this always fails. + * Skip it for now. + */ + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "windows") != 0) { + result = SDL_GetDisplayUsableBounds(SDL_GetDisplayForWindow(window), &display); + SDLTest_AssertPass("SDL_GetDisplayUsableBounds()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + desiredW = display.w; + desiredH = display.h; + currentW = windowedW + 1; + currentH = windowedH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(currentW <= desiredW, "Verify returned width; expected: <= %d, got: %d", desiredW, + currentW); + SDLTest_AssertCheck(currentH <= desiredH, "Verify returned height; expected: <= %d, got: %d", desiredH, + currentH); + } + + /* Restore and check the dimensions */ + result = SDL_RestoreWindow(window); + SDLTest_AssertPass("SDL_RestoreWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify that the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + if (!skipPos) { + currentX = windowedX + 1; + currentY = windowedY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(windowedX == currentX, "Verify returned X coordinate; expected: %d, got: %d", windowedX, currentX); + SDLTest_AssertCheck(windowedY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", windowedY, currentY); + } + + currentW = windowedW + 1; + currentH = windowedH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(windowedW == currentW, "Verify returned width; expected: %d, got: %d", windowedW, currentW); + SDLTest_AssertCheck(windowedH == currentH, "Verify returned height; expected: %d, got: %d", windowedH, currentH); + + /* Maximize, then immediately restore */ + result = SDL_MaximizeWindow(window); + SDLTest_AssertPass("SDL_MaximizeWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_RestoreWindow(window); + SDLTest_AssertPass("SDL_RestoreWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify that the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + /* Make sure the restored size and position matches the original windowed size and position. */ + if (!skipPos) { + currentX = windowedX + 1; + currentY = windowedY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(windowedX == currentX, "Verify returned X coordinate; expected: %d, got: %d", windowedX, currentX); + SDLTest_AssertCheck(windowedY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", windowedY, currentY); + } + + currentW = windowedW + 1; + currentH = windowedH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(windowedW == currentW, "Verify returned width; expected: %d, got: %d", windowedW, currentW); + SDLTest_AssertCheck(windowedH == currentH, "Verify returned height; expected: %d, got: %d", windowedH, currentH); + + /* Maximize, then enter fullscreen */ + result = SDL_MaximizeWindow(window); + SDLTest_AssertPass("SDL_MaximizeWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SetWindowFullscreen(window, SDL_TRUE); + SDLTest_AssertPass("SDL_SetWindowFullscreen(SDL_TRUE)"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(flags & SDL_WINDOW_FULLSCREEN, "Verify the `SDL_WINDOW_FULLSCREEN` flag is set: %s", (flags & SDL_WINDOW_FULLSCREEN) ? "true" : "false"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + /* Verify the fullscreen size and position */ + result = SDL_GetDisplayBounds(SDL_GetDisplayForWindow(window), &display); + SDLTest_AssertPass("SDL_GetDisplayBounds()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + if (!skipPos) { + desiredX = display.x; + desiredY = display.y; + currentX = windowedX + 1; + currentY = windowedY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(desiredX == currentX, "Verify returned X coordinate; expected: %d, got: %d", desiredX, currentX); + SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", desiredY, currentY); + } + + desiredW = display.w; + desiredH = display.h; + currentW = windowedW + 1; + currentH = windowedH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(currentW == desiredW, "Verify returned width; expected: %d, got: %d", desiredW, currentW); + SDLTest_AssertCheck(currentH == desiredH, "Verify returned height; expected: %d, got: %d", desiredH, currentH); + + /* Leave fullscreen and restore the window */ + result = SDL_SetWindowFullscreen(window, SDL_FALSE); + SDLTest_AssertPass("SDL_SetWindowFullscreen(SDL_FALSE)"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_RestoreWindow(window); + SDLTest_AssertPass("SDL_RestoreWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify that the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + /* Make sure the restored size and position matches the original windowed size and position. */ + if (!skipPos) { + currentX = windowedX + 1; + currentY = windowedY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(windowedX == currentX, "Verify returned X coordinate; expected: %d, got: %d", windowedX, currentX); + SDLTest_AssertCheck(windowedY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", windowedY, currentY); + } + + currentW = windowedW + 1; + currentH = windowedH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(windowedW == currentW, "Verify returned width; expected: %d, got: %d", windowedW, currentW); + SDLTest_AssertCheck(windowedH == currentH, "Verify returned height; expected: %d, got: %d", windowedH, currentH); + + /* Maximize, change size, and restore */ + result = SDL_MaximizeWindow(window); + SDLTest_AssertPass("SDL_MaximizeWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + desiredW = windowedW + 10; + desiredH = windowedH + 10; + result = SDL_SetWindowSize(window, desiredW, desiredH); + SDLTest_AssertPass("SDL_SetWindowSize()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + if (!skipPos) { + desiredX = windowedX + 10; + desiredY = windowedY + 10; + result = SDL_SetWindowPosition(window, desiredX, desiredY); + SDLTest_AssertPass("SDL_SetWindowPosition()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + } + + result = SDL_RestoreWindow(window); + SDLTest_AssertPass("SDL_RestoreWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify that the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + if (!skipPos) { + currentX = desiredX + 1; + currentY = desiredY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(desiredX == currentX, "Verify returned X coordinate; expected: %d, got: %d", desiredX, currentX); + SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", desiredY, currentY); + } + + currentW = desiredW + 1; + currentH = desiredH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(desiredW == currentW, "Verify returned width; expected: %d, got: %d", desiredW, currentW); + SDLTest_AssertCheck(desiredH == currentH, "Verify returned height; expected: %d, got: %d", desiredH, currentH); + + /* Change size and position, maximize and restore */ + desiredW = windowedW - 5; + desiredH = windowedH - 5; + result = SDL_SetWindowSize(window, desiredW, desiredH); + SDLTest_AssertPass("SDL_SetWindowSize()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + if (!skipPos) { + desiredX = windowedX + 5; + desiredY = windowedY + 5; + result = SDL_SetWindowPosition(window, desiredX, desiredY); + SDLTest_AssertPass("SDL_SetWindowPosition()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + } + + result = SDL_MaximizeWindow(window); + SDLTest_AssertPass("SDL_MaximizeWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_RestoreWindow(window); + SDLTest_AssertPass("SDL_RestoreWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(!(flags & SDL_WINDOW_MAXIMIZED), "Verify that the `SDL_WINDOW_MAXIMIZED` flag is cleared: %s", !(flags & SDL_WINDOW_MAXIMIZED) ? "true" : "false"); + + if (!skipPos) { + currentX = desiredX + 1; + currentY = desiredY + 1; + SDL_GetWindowPosition(window, ¤tX, ¤tY); + SDLTest_AssertPass("Call to SDL_GetWindowPosition()"); + SDLTest_AssertCheck(desiredX == currentX, "Verify returned X coordinate; expected: %d, got: %d", desiredX, currentX); + SDLTest_AssertCheck(desiredY == currentY, "Verify returned Y coordinate; expected: %d, got: %d", desiredY, currentY); + } + + currentW = desiredW + 1; + currentH = desiredH + 1; + SDL_GetWindowSize(window, ¤tW, ¤tH); + SDLTest_AssertPass("Call to SDL_GetWindowSize()"); + SDLTest_AssertCheck(desiredW == currentW, "Verify returned width; expected: %d, got: %d", desiredW, currentW); + SDLTest_AssertCheck(desiredH == currentH, "Verify returned height; expected: %d, got: %d", desiredH, currentH); + +minimize_test: + + /* Minimize */ + result = SDL_MinimizeWindow(window); + if (result == 0) { + SDLTest_AssertPass("SDL_MinimizeWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + result = SDL_SyncWindow(window); + SDLTest_AssertPass("SDL_SyncWindow()"); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); + + flags = SDL_GetWindowFlags(window); + SDLTest_AssertPass("SDL_GetWindowFlags()"); + SDLTest_AssertCheck(flags & SDL_WINDOW_MINIMIZED, "Verify that the `SDL_WINDOW_MINIMIZED` flag is set: %s", (flags & SDL_WINDOW_MINIMIZED) ? "true" : "false"); + } else { + SDLTest_Log("Skipping minimize test: %s reports window minimizing as unsupported", SDL_GetCurrentVideoDriver()); + skipFlags |= SDL_WINDOW_MINIMIZED; + } + + /* Clean up */ + destroyVideoSuiteTestWindow(window); + + /* Restore the hint to the previous value */ + SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", restoreHint ? "1" : "0"); + + return skipFlags != (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED) ? TEST_COMPLETED : TEST_SKIPPED; +} + /* ================= Test References ================== */ /* Video test cases */ @@ -1897,12 +2347,16 @@ static const SDLTest_TestCaseReference videoTest18 = { (SDLTest_TestCaseFp)video_setWindowCenteredOnDisplay, "video_setWindowCenteredOnDisplay", "Checks using SDL_WINDOWPOS_CENTERED_DISPLAY centers the window on a display", TEST_ENABLED }; +static const SDLTest_TestCaseReference videoTest19 = { + (SDLTest_TestCaseFp)video_getSetWindowState, "video_getSetWindowState", "Checks transitioning between windowed, minimized, maximized, and fullscreen states", TEST_ENABLED +}; + /* Sequence of Video test cases */ static const SDLTest_TestCaseReference *videoTests[] = { &videoTest1, &videoTest2, &videoTest3, &videoTest4, &videoTest5, &videoTest6, &videoTest7, &videoTest8, &videoTest9, &videoTest10, &videoTest11, &videoTest12, &videoTest13, &videoTest14, &videoTest15, &videoTest16, &videoTest17, - &videoTest18, NULL + &videoTest18, &videoTest19, NULL }; /* Video test suite (global) */ From 20250aecc5190f0036524b1c04083917fca2e621 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Thu, 7 Dec 2023 18:27:25 +0000 Subject: [PATCH 529/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_video.h | 148 +++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 69 deletions(-) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index b6a0e608748cf..ab7682001b14b 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -630,10 +630,11 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * change the window size when the window is not fullscreen, use * SDL_SetWindowSize(). * - * If the window is currently in the fullscreen state, this request is asynchronous - * on some windowing systems and the new mode dimensions may not be applied - * immediately upon the return of this function. If an immediate change is required, - * call SDL_SyncWindow() to block until the changes have taken effect. + * If the window is currently in the fullscreen state, this request is + * asynchronous on some windowing systems and the new mode dimensions may not + * be applied immediately upon the return of this function. If an immediate + * change is required, call SDL_SyncWindow() to block until the changes have + * taken effect. * * When the new mode takes effect, an SDL_EVENT_WINDOW_RESIZED and/or an * SDL_EVENT_WINDOOW_PIXEL_SIZE_CHANGED event will be emitted with the new @@ -1082,25 +1083,27 @@ extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *i /** * Request that the window's position be set. * - * If, at the time of this request, the window is in a fixed-size state such as - * maximized, this request may be deferred until the window returns to a resizable - * state. + * If, at the time of this request, the window is in a fixed-size state such + * as maximized, this request may be deferred until the window returns to a + * resizable state. * - * This can be used to reposition fullscreen-desktop windows onto a different display, - * however, exclusive fullscreen windows are locked to a specific display and can - * only be repositioned programmatically via SDL_SetWindowFullscreenMode(). + * This can be used to reposition fullscreen-desktop windows onto a different + * display, however, exclusive fullscreen windows are locked to a specific + * display and can only be repositioned programmatically via + * SDL_SetWindowFullscreenMode(). * - * On some windowing systems this request is asynchronous and the new coordinates - * may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the changes - * have taken effect. + * On some windowing systems this request is asynchronous and the new + * coordinates may not have have been applied immediately upon the return of + * this function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. * * When the window position changes, an SDL_EVENT_WINDOW_MOVED event will be - * emitted with the window's new coordinates. Note that the new coordinates may - * not match the exact coordinates requested, as some windowing systems can restrict - * the position of the window in certain scenarios (e.g. constraining the position - * so the window is always within desktop bounds). Additionally, as this is just a - * request, it can be denied by the windowing system. + * emitted with the window's new coordinates. Note that the new coordinates + * may not match the exact coordinates requested, as some windowing systems + * can restrict the position of the window in certain scenarios (e.g. + * constraining the position so the window is always within desktop bounds). + * Additionally, as this is just a request, it can be denied by the windowing + * system. * * \param window the window to reposition * \param x the x coordinate of the window, or `SDL_WINDOWPOS_CENTERED` or @@ -1120,8 +1123,8 @@ extern DECLSPEC int SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int /** * Get the position of a window. * - * This is the current position of the window as last reported by the windowing - * system. + * This is the current position of the window as last reported by the + * windowing system. * * If you do not need the value for one of the positions a NULL may be passed * in the `x` or `y` parameter. @@ -1144,23 +1147,24 @@ extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, in * NULL can safely be passed as the `w` or `h` parameter if the width or * height value is not desired. * - * If, at the time of this request, the window in a fixed-size state, such - * as maximized or fullscreen, the request will be deferred until the window + * If, at the time of this request, the window in a fixed-size state, such as + * maximized or fullscreen, the request will be deferred until the window * exits this state and becomes resizable again. * - * To change the fullscreen mode of a window, use SDL_SetWindowFullscreenMode() + * To change the fullscreen mode of a window, use + * SDL_SetWindowFullscreenMode() * - * On some windowing systems, this request is asynchronous and the new window size - * may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the - * changes have taken effect. + * On some windowing systems, this request is asynchronous and the new window + * size may not have have been applied immediately upon the return of this + * function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. * * When the window size changes, an SDL_EVENT_WINDOW_RESIZED event will be * emitted with the new window dimensions. Note that the new dimensions may * not match the exact size requested, as some windowing systems can restrict - * the window size in certain scenarios (e.g. constraining the size of the content - * area to remain within the usable desktop bounds). Additionally, as this is just - * a request, it can be denied by the windowing system. + * the window size in certain scenarios (e.g. constraining the size of the + * content area to remain within the usable desktop bounds). Additionally, as + * this is just a request, it can be denied by the windowing system. * * \param window the window to change * \param w the width of the window, must be > 0 @@ -1421,17 +1425,19 @@ extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); * Non-resizable windows can't be maximized. The window must have the * SDL_WINDOW_RESIZABLE flag set, or this will have no effect. * - * On some windowing systems this request is asynchronous and the new window state - * may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the - * changes have taken effect. + * On some windowing systems this request is asynchronous and the new window + * state may not have have been applied immediately upon the return of this + * function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. * - * When the window state changes, an SDL_EVENT_WINDOW_MAXIMIZED event will be emitted. - * Note that, as this is just a request, the windowing system can deny the state change. + * When the window state changes, an SDL_EVENT_WINDOW_MAXIMIZED event will be + * emitted. Note that, as this is just a request, the windowing system can + * deny the state change. * - * When maximizing a window, whether the constraints set via SDL_SetWindowMaximumSize() - * are honored depends on the policy of the window manager. Win32 and macOS enforce the - * constraints when maximizing, while X11 and Wayland window managers may vary. + * When maximizing a window, whether the constraints set via + * SDL_SetWindowMaximumSize() are honored depends on the policy of the window + * manager. Win32 and macOS enforce the constraints when maximizing, while X11 + * and Wayland window managers may vary. * * \param window the window to maximize * \returns 0 on success or a negative error code on failure; call @@ -1448,13 +1454,14 @@ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); /** * Request that the window be minimized to an iconic representation. * - * On some windowing systems this request is asynchronous and the new window state - * may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the - * changes have taken effect. + * On some windowing systems this request is asynchronous and the new window + * state may not have have been applied immediately upon the return of this + * function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. * - * When the window state changes, an SDL_EVENT_WINDOW_MINIMIZED event will be emitted. - * Note that, as this is just a request, the windowing system can deny the state change. + * When the window state changes, an SDL_EVENT_WINDOW_MINIMIZED event will be + * emitted. Note that, as this is just a request, the windowing system can + * deny the state change. * * \param window the window to minimize * \returns 0 on success or a negative error code on failure; call @@ -1469,15 +1476,17 @@ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); /** - * Request that the size and position of a minimized or maximized window be restored. + * Request that the size and position of a minimized or maximized window be + * restored. * - * On some windowing systems this request is asynchronous and the new window state - * may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the - * changes have taken effect. + * On some windowing systems this request is asynchronous and the new window + * state may not have have been applied immediately upon the return of this + * function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. * - * When the window state changes, an SDL_EVENT_WINDOW_RESTORED event will be emitted. - * Note that, as this is just a request, the windowing system can deny the state change. + * When the window state changes, an SDL_EVENT_WINDOW_RESTORED event will be + * emitted. Note that, as this is just a request, the windowing system can + * deny the state change. * * \param window the window to restore * \returns 0 on success or a negative error code on failure; call @@ -1497,14 +1506,14 @@ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); * By default a window in fullscreen state uses fullscreen desktop mode, but a * specific display mode can be set using SDL_SetWindowFullscreenMode(). * - * On some windowing systems this request is asynchronous and the new fullscreen - * state may not have have been applied immediately upon the return of this function. - * If an immediate change is required, call SDL_SyncWindow() to block until the - * changes have taken effect. + * On some windowing systems this request is asynchronous and the new + * fullscreen state may not have have been applied immediately upon the return + * of this function. If an immediate change is required, call SDL_SyncWindow() + * to block until the changes have taken effect. * * When the window state changes, an SDL_EVENT_WINDOW_ENTER_FULLSCREEN or - * SDL_EVENT_WINDOW_LEAVE_FULLSCREEN event will be emitted. Note that, as this is - * just a request, it can be denied by the windowing system. + * SDL_EVENT_WINDOW_LEAVE_FULLSCREEN event will be emitted. Note that, as this + * is just a request, it can be denied by the windowing system. * * \param window the window to change * \param fullscreen SDL_TRUE for fullscreen mode, SDL_FALSE for windowed mode @@ -1522,19 +1531,20 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool /** * Block until any pending window state is finalized. * - * On asynchronous windowing systems, this acts as a synchronization barrier for - * pending window state. It will attempt to wait until any pending window state - * has been applied and is guaranteed to return within finite time. Note that for - * how long it can potentially block depends on the underlying window system, as - * window state changes may involve somewhat lengthy animations that must complete - * before the window is in its final requested state. + * On asynchronous windowing systems, this acts as a synchronization barrier + * for pending window state. It will attempt to wait until any pending window + * state has been applied and is guaranteed to return within finite time. Note + * that for how long it can potentially block depends on the underlying window + * system, as window state changes may involve somewhat lengthy animations + * that must complete before the window is in its final requested state. * * On windowing systems where changes are immediate, this does nothing. * - * \param window the window for which to wait for the pending state to be applied - * \returns 0 on success, a positive value if the operation timed out before the - * window was in the requested state, or a negative error code on failure; - * call SDL_GetError() for more information. + * \param window the window for which to wait for the pending state to be + * applied + * \returns 0 on success, a positive value if the operation timed out before + * the window was in the requested state, or a negative error code on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * From 7484d02a2e839652ab73857fb250f5ed8f4140d5 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 27 Nov 2023 21:20:01 +0100 Subject: [PATCH 530/725] testshape: use SDL_test to create multiple windows --- test/testshape.c | 150 +++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 77 deletions(-) diff --git a/test/testshape.c b/test/testshape.c index e136bb28bc38d..23fc5cb42dbc3 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -50,7 +50,9 @@ typedef struct SDL_WindowShapeMode typedef struct LoadedPicture { SDL_Surface *surface; - SDL_Texture *texture; + int num_textures; + SDL_Texture **textures; + SDL_Texture **shape_textures; SDL_WindowShapeMode mode; const char *name; struct LoadedPicture *next; @@ -59,7 +61,6 @@ typedef struct LoadedPicture static Uint8 *g_bitmap = NULL; static int g_bitmap_w = 0, g_bitmap_h = 0; static SDL_Surface *g_shape_surface = NULL; -static SDL_Texture *g_shape_texture = NULL; static void log_usage(SDLTest_CommonState *state, char *progname) { static const char *options[] = { "sample1.bmp [sample2.bmp [sample3.bmp ...]]", NULL }; @@ -115,16 +116,23 @@ static void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shap } } -static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode) +static int SDL3_SetWindowShape(LoadedPicture *picture, SDL_WindowShapeMode *shape_mode) { if (g_bitmap) { SDL_free(g_bitmap); g_bitmap = NULL; } - if (g_shape_texture) { - SDL_DestroyTexture(g_shape_texture); - g_shape_texture = NULL; + if (!picture) { + return SDL_SetError("picture"); + } + + if (picture->shape_textures[0]) { + int i; + for (i = 0; i < picture->num_textures; i++) { + SDL_DestroyTexture(picture->shape_textures[i]); + picture->shape_textures[i] = NULL; + } } if (g_shape_surface) { @@ -132,22 +140,18 @@ static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_Windo g_shape_surface = NULL; } - if (!shape) { - return SDL_SetError("shape"); - } - if (!shape_mode) { return SDL_SetError("shape_mode"); } - g_bitmap_w = shape->w; - g_bitmap_h = shape->h; - g_bitmap = (Uint8*) SDL_malloc(shape->w * shape->h); + g_bitmap_w = picture->surface->w; + g_bitmap_h = picture->surface->h; + g_bitmap = (Uint8*) SDL_malloc(picture->surface->w * picture->surface->h); if (!g_bitmap) { return -1; } - SDL_CalculateShapeBitmap(*shape_mode, shape, g_bitmap, 1); + SDL_CalculateShapeBitmap(*shape_mode, picture->surface, g_bitmap, 1); g_shape_surface = SDL_CreateSurface(g_bitmap_w, g_bitmap_h, SDL_PIXELFORMAT_ABGR8888); if (g_shape_surface) { @@ -169,14 +173,14 @@ static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_Windo return 0; } -static void render(SDL_Renderer *renderer, SDL_Texture *texture) +static void render(int index, SDL_Renderer *renderer, LoadedPicture *picture) { /* Clear render-target to blue. */ SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xff, 0xff); SDL_RenderClear(renderer); /* Render the texture. */ - SDL_RenderTexture(renderer, texture, NULL, NULL); + SDL_RenderTexture(renderer, picture->textures[index], NULL, NULL); /* Apply the shape */ if (g_shape_surface) { @@ -200,19 +204,19 @@ static void render(SDL_Renderer *renderer, SDL_Texture *texture) SDL_SetRenderDrawColor(renderer, r, g, b, a); } } else { - if (!g_shape_texture) { + if (!picture->shape_textures[index]) { SDL_BlendMode bm; - g_shape_texture = SDL_CreateTextureFromSurface(renderer, g_shape_surface); + picture->shape_textures[index] = SDL_CreateTextureFromSurface(renderer, g_shape_surface); /* if Alpha is 0, set all to 0, else leave unchanged. */ bm = SDL_ComposeCustomBlendMode( SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD); - SDL_SetTextureBlendMode(g_shape_texture, bm); + SDL_SetTextureBlendMode(picture->shape_textures[index], bm); } - SDL_RenderTexture(renderer, g_shape_texture, NULL, NULL); + SDL_RenderTexture(renderer, picture->shape_textures[index], NULL, NULL); } } @@ -226,13 +230,11 @@ int main(int argc, char **argv) LoadedPicture *picture_linked_list = NULL; LoadedPicture **pictures = NULL; int i; + int j; const SDL_DisplayMode *mode; SDL_PixelFormat *format = NULL; - SDL_Window *window = NULL; - SDL_Renderer *renderer = NULL; SDL_Color black = { 0, 0, 0, 0xff }; - SDL_Event event; - int should_exit = 0; + int done = 0; int current_picture; int button_down; Uint32 pixelFormat = 0; @@ -241,11 +243,14 @@ int main(int argc, char **argv) int rc; /* Initialize test framework */ - state = SDLTest_CommonCreateState(argv, 0); + state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); if (!state) { return 1; } + state->window_flags |= SDL_WINDOW_TRANSPARENT; + state->window_flags &= ~SDL_WINDOW_RESIZABLE; + rc = 0; /* SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); */ @@ -277,14 +282,16 @@ int main(int argc, char **argv) i += consumed; } if (!num_pictures) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Shape requires at least one bitmap file as argument."); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testshape requires at least one bitmap file as argument."); log_usage(state, argv[0]); - exit(-1); + rc = -1; + goto ret; } - if (SDL_Init(SDL_INIT_VIDEO) == -1) { + if (!SDLTest_CommonInit(state)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not initialize SDL video."); - exit(-2); + rc = -2; + goto ret; } mode = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay()); @@ -323,48 +330,42 @@ int main(int argc, char **argv) } } - window = SDL_CreateWindow("SDL_Shape test", SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, SDL_WINDOW_TRANSPARENT); - if (!window) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create shaped window for SDL_Shape."); - rc = -4; - goto ret; - } - renderer = SDL_CreateRenderer(window, NULL, 0); - if (!renderer) { - SDL_DestroyWindow(window); - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create rendering context for SDL_Shape window."); - rc = -4; - goto ret; - } - for (i = 0; i < num_pictures; i++) { - pictures[i]->texture = NULL; - } - for (i = 0; i < num_pictures; i++) { - pictures[i]->texture = SDL_CreateTextureFromSurface(renderer, pictures[i]->surface); - if (pictures[i]->texture == NULL) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create texture for SDL_shape."); - rc = -6; + pictures[i]->textures = SDL_calloc(state->num_windows, sizeof(SDL_Texture *)); + pictures[i]->shape_textures = SDL_calloc(state->num_windows, sizeof(SDL_Texture *)); + if (!pictures[i]->textures || !pictures[i]->shape_textures) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create textures array(s)."); + rc = -4; goto ret; } + + for (j = 0; j < state->num_windows; j++) { + pictures[i]->textures[j] = SDL_CreateTextureFromSurface(state->renderers[j], pictures[i]->surface); + if (!pictures[i]->textures[j]) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create textures for SDL_shape."); + rc = -5; + goto ret; + } + } } - should_exit = 0; + done = 0; current_picture = 0; button_down = 0; SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture]->name); - SDL_QueryTexture(pictures[current_picture]->texture, &pixelFormat, &access, &w, &h); - /* We want to set the window size in pixels */ - SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->pixel_density), (int)SDL_ceilf(h / mode->pixel_density)); - SDL3_SetWindowShape(window, pictures[current_picture]->surface, &pictures[current_picture]->mode); - while (should_exit == 0) { + for (i = 0; i < state->num_windows; i++) { + SDL_QueryTexture(pictures[current_picture]->textures[i], &pixelFormat, &access, &w, &h); + /* We want to set the window size in pixels */ + SDL_SetWindowSize(state->windows[i], (int)SDL_ceilf(w / mode->pixel_density), (int)SDL_ceilf(h / mode->pixel_density)); + } + SDL3_SetWindowShape(pictures[current_picture], &pictures[current_picture]->mode); + while (!done) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + SDLTest_CommonEvent(state, &event, &done); if (event.type == SDL_EVENT_KEY_DOWN) { button_down = 1; - if (event.key.keysym.sym == SDLK_ESCAPE) { - should_exit = 1; - break; - } } if (button_down && event.type == SDL_EVENT_KEY_UP) { button_down = 0; @@ -373,16 +374,16 @@ int main(int argc, char **argv) current_picture = 0; } SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture]->name); - SDL_QueryTexture(pictures[current_picture]->texture, &pixelFormat, &access, &w, &h); - SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->pixel_density), (int)SDL_ceilf(h / mode->pixel_density)); - SDL3_SetWindowShape(window, pictures[current_picture]->surface, &pictures[current_picture]->mode); - } - if (event.type == SDL_EVENT_QUIT) { - should_exit = 1; - break; + for (i = 0; i < state->num_windows; i++) { + SDL_QueryTexture(pictures[current_picture]->textures[i], &pixelFormat, &access, &w, &h); + SDL_SetWindowSize(state->windows[i], (int)SDL_ceilf(w / mode->pixel_density),(int)SDL_ceilf(h / mode->pixel_density)); + SDL3_SetWindowShape(pictures[current_picture], &pictures[current_picture]->mode); + } } } - render(renderer, pictures[current_picture]->texture); + for (i = 0; i < state->num_windows; i++) { + render(i, state->renderers[i], pictures[current_picture]); + } SDL_Delay(10); } @@ -390,20 +391,16 @@ int main(int argc, char **argv) /* Free the textures + original surfaces backing the textures. */ for (pic_i = picture_linked_list; pic_i; ) { LoadedPicture *next = pic_i->next; - if (pic_i->texture) { - SDL_DestroyTexture(pic_i->texture); + for (j = 0; j < state->num_windows; j++) { + SDL_DestroyTexture(pic_i->textures[i]); } + SDL_free(pic_i->textures); SDL_DestroySurface(pic_i->surface); SDL_free(pic_i); pic_i = next; } SDL_free(pictures); - /* Destroy the renderer. */ - SDL_DestroyRenderer(renderer); - /* Destroy the window. */ - SDL_DestroyWindow(window); - if (g_bitmap) { SDL_free(g_bitmap); g_bitmap = NULL; @@ -413,8 +410,7 @@ int main(int argc, char **argv) g_shape_surface = NULL; } - SDL_Quit(); - SDLTest_CommonDestroyState(state); + SDLTest_CommonQuit(state); return rc; } From fbb0914b78bebfe83601a7b100f0d2ff5cf956c1 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 27 Nov 2023 21:30:59 +0100 Subject: [PATCH 531/725] wayland+x11: free system cursors when quiting video --- src/video/wayland/SDL_waylandmouse.c | 6 ++++++ src/video/x11/SDL_x11mouse.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index c670cdc18a13a..11ab35cad30e1 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -831,6 +831,7 @@ void Wayland_InitMouse(void) void Wayland_FiniMouse(SDL_VideoData *data) { struct SDL_WaylandInput *input = data->input; + int i; Wayland_FreeCursorThemes(data); @@ -840,6 +841,11 @@ void Wayland_FiniMouse(SDL_VideoData *data) SDL_DelHintCallback(SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP, Wayland_EmulateMouseWarpChanged, input); + + for (i = 0; i < SDL_arraysize(sys_cursors); i++) { + Wayland_FreeCursor(sys_cursors[i]); + sys_cursors[i] = NULL; + } } void Wayland_SetHitTestCursor(SDL_HitTestResult rc) diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 9c32b12f80ba3..a9199815202ec 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -511,6 +511,12 @@ void X11_QuitMouse(SDL_VideoDevice *_this) SDL_VideoData *data = _this->driverdata; SDL_XInput2DeviceInfo *i; SDL_XInput2DeviceInfo *next; + int j; + + for (j = 0; j < SDL_arraysize(sys_cursors); j++) { + X11_FreeCursor(sys_cursors[j]); + sys_cursors[j] = NULL; + } for (i = data->mouse_device_info; i; i = next) { next = i->next; From a197efe3a7135fff23ed73f5a1668062e4aa6a19 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 27 Nov 2023 21:37:02 +0100 Subject: [PATCH 532/725] pen: fix leak caused by pen subsystem --- src/events/SDL_mouse.c | 1 + src/events/SDL_pen.c | 13 +++++++++++++ src/events/SDL_pen_c.h | 5 +++++ test/testautomation_pen.c | 1 + 4 files changed, 20 insertions(+) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 44c732e0fb563..97510469794c8 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -898,6 +898,7 @@ void SDL_QuitMouse(void) } SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(); + SDL_PenQuit(); if (mouse->def_cursor) { SDL_SetDefaultCursor(NULL); diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index 655d729d56e5f..e3f55482f7af6 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -829,6 +829,19 @@ void SDL_PenInit(void) #endif } +void SDL_PenQuit(void) +{ + SDL_DelHintCallback(SDL_HINT_PEN_NOT_MOUSE, + SDL_PenUpdateHint, &pen_mouse_emulation_mode); + + SDL_DelHintCallback(SDL_HINT_PEN_DELAY_MOUSE_BUTTON, + SDL_PenUpdateHint, &pen_delay_mouse_button_mode); +#ifndef SDL_THREADS_DISABLED + SDL_DestroyMutex(SDL_pen_access_lock); + SDL_pen_access_lock = NULL; +#endif +} + SDL_bool SDL_PenPerformHitTest(void) { return pen_mouse_emulation_mode == PEN_MOUSE_EMULATE; diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h index 0488d5d92f798..70b1b7fefd1ef 100644 --- a/src/events/SDL_pen_c.h +++ b/src/events/SDL_pen_c.h @@ -331,6 +331,11 @@ extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_W */ extern void SDL_PenInit(void); +/** + * De-initialises the pen subsystem. + */ +extern void SDL_PenQuit(void); + #endif /* SDL_pen_c_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/test/testautomation_pen.c b/test/testautomation_pen.c index d200656603964..d9a6ef2a28890 100644 --- a/test/testautomation_pen.c +++ b/test/testautomation_pen.c @@ -54,6 +54,7 @@ #define SDL_SendPenWindowEvent SDL_SUT_SendPenWindowEvent #define SDL_PenPerformHitTest SDL_SUT_PenPerformHitTest #define SDL_PenInit SDL_SUT_PenInit +#define SDL_PenQuit SDL_SUT_PenQuit /* ================= Mock API ================== */ From 53cda988f4827197ae4cf0df893ea0ec60ca9d1f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 7 Dec 2023 14:30:40 -0800 Subject: [PATCH 533/725] Clear any errors from a previous run The error is thread-local, and the java thread may run onCreate initialization multiple times depending on the Android life cycle --- src/core/android/SDL_android.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 63bd79d6524c4..c34c301105b6e 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -573,6 +573,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeSetupJNI()"); + /* Start with a clean slate */ + SDL_ClearError(); + /* * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this From 3c5e9e61123f9e020081a4a7936e305dc1ef378a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 7 Dec 2023 14:30:44 -0800 Subject: [PATCH 534/725] We can wait up to 500ms in onNativeSurfaceDestroyed(), so wait at least that long in onDestroy() --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 676faee36e9a7..ba773765e1aec 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -683,11 +683,11 @@ protected void onDestroy() { // Wait for "SDLThread" thread to end try { - // 500ms timeout, because: + // Use a timeout because: // C SDLmain() thread might have started (mSDLThread.start() called) // while the SDL_Init() might not have been called yet, // and so the previous QUIT event will be discarded by SDL_Init() and app is running, not exiting. - SDLActivity.mSDLThread.join(500); + SDLActivity.mSDLThread.join(1000); } catch(Exception e) { Log.v(TAG, "Problem stopping SDLThread: " + e); } From 7e5511d3cdfb0767e57af11af571adc193e817a0 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 8 Dec 2023 04:50:52 -0500 Subject: [PATCH 535/725] x11: Move unrelated variables out of XFixes #ifdef --- src/video/x11/SDL_x11window.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 32130f2298412..03be883c7c9ae 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -78,7 +78,7 @@ struct SDL_WindowData SDL_bool pointer_barrier_active; PointerBarrier barrier[4]; SDL_Rect barrier_rect; - +#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ SDL_Rect expected; SDL_DisplayMode requested_fullscreen_mode; @@ -94,7 +94,6 @@ struct SDL_WindowData SDL_bool initial_border_adjustment; SDL_bool window_was_maximized; int skip_size_count; -#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ SDL_HitTestResult hit_test_result; }; From 63ae84e140bc145177a6ffc123a0bdd7e7f8ff63 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 8 Dec 2023 12:37:10 -0500 Subject: [PATCH 536/725] x11: Improve sync algorithm Track and check move and resize requests separately, and consider them done if either the window is already at the expected location, or at least one configure event which moved or resized the window was processed. The avoids a timeout condition if resizing the window caused it to be implicitly moved in order to keep it within desktop bounds. The automated positioning test now runs on GNOME/X11 without any sync requests timing out. --- src/video/x11/SDL_x11events.c | 13 +++++++++++++ src/video/x11/SDL_x11window.c | 26 +++++++++++++++----------- src/video/x11/SDL_x11window.h | 4 +++- test/testautomation_video.c | 3 +-- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 72f6caf1c07a0..764bfa8e9738a 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1330,6 +1330,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) int x = xevent->xconfigure.x; int y = xevent->xconfigure.y; + data->pending_operation &= ~X11_PENDING_OP_MOVE; SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); @@ -1349,6 +1350,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) if (xevent->xconfigure.width != data->last_xconfigure.width || xevent->xconfigure.height != data->last_xconfigure.height) { if (!data->skip_size_count) { + data->pending_operation &= ~X11_PENDING_OP_RESIZE; SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, xevent->xconfigure.width, xevent->xconfigure.height); @@ -1675,6 +1677,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) /* Restore the last known floating state if leaving maximized mode */ if (!(flags & SDL_WINDOW_FULLSCREEN)) { + data->pending_operation |= X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE; + data->expected.x = data->window->floating.x; + data->expected.y = data->window->floating.y; + data->expected.w = data->window->floating.w; + data->expected.h = data->window->floating.h; X11_XMoveWindow(display, data->xwindow, data->window->floating.x, data->window->floating.y); X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } @@ -1696,8 +1703,14 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) if (data->border_top != 0 || data->border_left != 0 || data->border_right != 0 || data->border_bottom != 0) { /* Adjust if the window size changed to accommodate the borders. */ if (data->window->flags & SDL_WINDOW_MAXIMIZED) { + data->pending_operation |= X11_PENDING_OP_RESIZE; + data->expected.w = data->window->windowed.w; + data->expected.h = data->window->windowed.h; X11_XResizeWindow(display, data->xwindow, data->window->windowed.w, data->window->windowed.h); } else { + data->pending_operation |= X11_PENDING_OP_RESIZE; + data->expected.w = data->window->floating.w; + data->expected.h = data->window->floating.h; X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 67a0c877c2a5f..5a2de89d94cb0 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -614,12 +614,12 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI window->floating.x, window->floating.y, &win_x, &win_y); - /* Always create this with the window->windowed.* fields; if we're - creating a windowed mode window, that's fine. If we're creating a - fullscreen window, the window manager will want to know these values - so it can use them if we go _back_ to windowed mode. SDL manages - migration to fullscreen after CreateSDLWindow returns, which will - put all the SDL_Window fields and system state as expected. */ + /* Always create this with the window->floating.* fields; if we're creating a windowed mode window, + * that's fine. If we're creating a maximized or fullscreen window, the window manager will want to + * know these values so it can use them if we go _back_ to the base floating windowed mode. SDL manages + * migration to fullscreen after CreateSDLWindow returns, which will put all the SDL_Window fields and + * system state as expected. + */ w = X11_XCreateWindow(display, RootWindow(display, screen), win_x, win_y, window->floating.w, window->floating.h, 0, depth, InputOutput, visual, @@ -868,9 +868,9 @@ static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int X11_XSync(display, False); X11_PumpEvents(_this); - if (window->x == data->expected.x && window->y == data->expected.y && - window->w == data->expected.w && window->h == data->expected.h && - data->pending_operation == X11_PENDING_OP_NONE) { + if ((!(data->pending_operation & X11_PENDING_OP_MOVE) || (window->x == data->expected.x && window->y == data->expected.y)) && + (!(data->pending_operation & X11_PENDING_OP_RESIZE) || (window->w == data->expected.w && window->h == data->expected.h)) && + (data->pending_operation & ~(X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE)) == X11_PENDING_OP_NONE) { /* The window is where it is wanted and nothing is pending. Done. */ break; } @@ -882,8 +882,6 @@ static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int data->expected.w = window->w; data->expected.h = window->h; - data->pending_operation = X11_PENDING_OP_NONE; - ret = 1; break; } @@ -891,6 +889,8 @@ static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int SDL_Delay(10); } + data->pending_operation = X11_PENDING_OP_NONE; + if (!caught_x11_error) { X11_PumpEvents(_this); } else { @@ -973,6 +973,7 @@ void X11_UpdateWindowPosition(SDL_Window *window, SDL_bool use_current_position) &data->expected.x, &data->expected.y); /* Attempt to move the window */ + data->pending_operation |= X11_PENDING_OP_MOVE; X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); } @@ -1116,6 +1117,7 @@ void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) } else { data->expected.w = window->floating.w; data->expected.h = window->floating.h; + data->pending_operation |= X11_PENDING_OP_RESIZE; X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); } } @@ -1598,10 +1600,12 @@ static int X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *wind data->expected.w = window->floating.w; data->expected.h = window->floating.h; + data->pending_operation |= X11_PENDING_OP_MOVE; X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); /* If the window is bordered, the size will be set when the borders turn themselves back on. */ if (window->flags & SDL_WINDOW_BORDERLESS) { + data->pending_operation |= X11_PENDING_OP_RESIZE; X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); } } diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 03be883c7c9ae..11977a57b9579 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -88,7 +88,9 @@ struct SDL_WindowData X11_PENDING_OP_RESTORE = 0x01, X11_PENDING_OP_MINIMIZE = 0x02, X11_PENDING_OP_MAXIMIZE = 0x04, - X11_PENDING_OP_FULLSCREEN = 0x08 + X11_PENDING_OP_FULLSCREEN = 0x08, + X11_PENDING_OP_MOVE = 0x10, + X11_PENDING_OP_RESIZE = 0x20 } pending_operation; SDL_bool initial_border_adjustment; diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 46ba4e37433c9..7a3c95d7766fd 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1134,10 +1134,9 @@ static int video_getSetWindowSize(void *arg) SDL_SetWindowSize(window, desiredW, desiredH); SDLTest_AssertPass("Call to SDL_SetWindowSize(...,%d,%d)", desiredW, desiredH); - /* The sync may time out if changing the size changes the window position. */ result = SDL_SyncWindow(window); SDLTest_AssertPass("SDL_SyncWindow()"); - SDLTest_AssertCheck(result >= 0, "Verify return value; expected: >=0, got: %d", result); + SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); /* Get size */ currentW = desiredW + 1; From f3d8a2def5e2214290bbbc075a6381fa9b753acf Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 9 Dec 2023 15:41:45 -0500 Subject: [PATCH 537/725] audio: Fixed resource leak in unlikely failure case during device add. --- src/audio/SDL_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 54f74d89b1448..c43506426e0c7 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -551,6 +551,8 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) { SDL_AtomicAdd(device_count, 1); } else { + SDL_DestroyCondition(device->close_cond); + SDL_DestroyMutex(device->lock); SDL_free(device->name); SDL_free(device); device = NULL; From 17723381da9bc3eadb129beaeaed2164c64b5155 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 9 Dec 2023 20:31:28 -0800 Subject: [PATCH 538/725] Sort Steam virtual gamepads by Steam controller slot This makes sure that games launched by Steam see the first controller first, and the controllers in the game match up with the controllers in the Steam UI. Fixes https://github.com/libsdl-org/SDL/issues/8672 --- src/joystick/linux/SDL_sysjoystick.c | 115 +++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 9b8a85f26678f..50a4e99891764 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -832,6 +832,104 @@ static int SDLCALL sort_entries(const void *_a, const void *_b) return numA - numB; } +typedef struct +{ + char *path; + int slot; +} VirtualGamepadEntry; + +static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b) +{ + const VirtualGamepadEntry *a = (const VirtualGamepadEntry *)_a; + const VirtualGamepadEntry *b = (const VirtualGamepadEntry *)_b; + return a->slot - b->slot; +} + +static SDL_bool get_virtual_gamepad_slot(const char *name, int *slot) +{ + const char *digits = SDL_strstr(name, "pad "); + if (digits) { + digits += 4; + if (SDL_isdigit(*digits)) { + *slot = SDL_atoi(digits); + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static void LINUX_ScanSteamVirtualGamepads(void) +{ + int i, count; + int fd; + struct dirent **entries = NULL; + char path[PATH_MAX]; + char name[128]; + struct input_id inpid; + int num_virtual_gamepads = 0; + int virtual_gamepad_slot; + VirtualGamepadEntry *virtual_gamepads = NULL; + + count = scandir("/dev/input", &entries, filter_entries, NULL); + for (i = 0; i < count; ++i) { + (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); + + fd = open(path, O_RDONLY | O_CLOEXEC, 0); + if (fd >= 0) { + if (ioctl(fd, EVIOCGID, &inpid) == 0 && + inpid.vendor == USB_VENDOR_VALVE && + inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && + ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && + get_virtual_gamepad_slot(name, &virtual_gamepad_slot)) { + VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); + if (new_virtual_gamepads) { + VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; + entry->path = SDL_strdup(path); + entry->slot = virtual_gamepad_slot; + if (entry->path) { + virtual_gamepads = new_virtual_gamepads; + ++num_virtual_gamepads; + } else { + SDL_free(entry->path); + SDL_free(new_virtual_gamepads); + } + } + } + close(fd); + } + free(entries[i]); /* This should NOT be SDL_free() */ + } + free(entries); /* This should NOT be SDL_free() */ + + if (num_virtual_gamepads > 1) { + SDL_qsort(virtual_gamepads, num_virtual_gamepads, sizeof(*virtual_gamepads), sort_virtual_gamepads); + } + for (i = 0; i < num_virtual_gamepads; ++i) { + MaybeAddDevice(virtual_gamepads[i].path); + SDL_free(virtual_gamepads[i].path); + } + SDL_free(virtual_gamepads); +} + +static void LINUX_ScanInputDevices(void) +{ + int i, count; + struct dirent **entries = NULL; + char path[PATH_MAX]; + + count = scandir("/dev/input", &entries, filter_entries, NULL); + if (count > 1) { + SDL_qsort(entries, count, sizeof(*entries), sort_entries); + } + for (i = 0; i < count; ++i) { + (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); + MaybeAddDevice(path); + + free(entries[i]); /* This should NOT be SDL_free() */ + } + free(entries); /* This should NOT be SDL_free() */ +} + static void LINUX_FallbackJoystickDetect(void) { const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ @@ -842,21 +940,10 @@ static void LINUX_FallbackJoystickDetect(void) /* Opening input devices can generate synchronous device I/O, so avoid it if we can */ if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) { - int i, count; - struct dirent **entries = NULL; - char path[PATH_MAX]; + /* Look for Steam virtual gamepads first, and sort by Steam controller slot */ + LINUX_ScanSteamVirtualGamepads(); - count = scandir("/dev/input", &entries, filter_entries, NULL); - if (count > 1) { - SDL_qsort(entries, count, sizeof(*entries), sort_entries); - } - for (i = 0; i < count; ++i) { - (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); - MaybeAddDevice(path); - - free(entries[i]); /* This should NOT be SDL_free() */ - } - free(entries); /* This should NOT be SDL_free() */ + LINUX_ScanInputDevices(); last_input_dir_mtime = sb.st_mtime; } From 445f08a0fba49562498b64fc28faa22dd690aeaf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 9 Dec 2023 21:00:11 -0800 Subject: [PATCH 539/725] Print the gamepad player index when opening a gamepad --- test/testcontroller.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/testcontroller.c b/test/testcontroller.c index f6d406e01fcb8..a18bb0b066228 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -995,6 +995,10 @@ static void HandleGamepadAdded(SDL_JoystickID id, SDL_bool verbose) if (SDL_GamepadHasRumbleTriggers(gamepad)) { SDL_Log("Trigger rumble supported"); } + + if (SDL_GetGamepadPlayerIndex(gamepad) >= 0) { + SDL_Log("Player index: %d\n", SDL_GetGamepadPlayerIndex(gamepad)); + } } for (i = 0; i < SDL_arraysize(sensors); ++i) { From 7529d25b2b99e2f790c418e479e7ce85c1c818e6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 9 Dec 2023 21:00:32 -0800 Subject: [PATCH 540/725] Use the Steam virtual gamepad slot as the gamepad player index --- src/joystick/linux/SDL_sysjoystick.c | 44 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 50a4e99891764..965e5f415af0a 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -156,6 +156,7 @@ typedef struct SDL_joylist_item char *name; /* "SideWinder 3D Pro" or whatever */ SDL_JoystickGUID guid; dev_t devnum; + int steam_virtual_gamepad_slot; struct joystick_hwdata *hwdata; struct SDL_joylist_item *next; @@ -219,6 +220,19 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, } #endif /* SDL_JOYSTICK_HIDAPI */ +static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot) +{ + const char *digits = SDL_strstr(name, "pad "); + if (digits) { + digits += 4; + if (SDL_isdigit(*digits)) { + *slot = SDL_atoi(digits); + return SDL_TRUE; + } + } + return SDL_FALSE; +} + static int GuessDeviceClass(int fd) { unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 }; @@ -259,7 +273,7 @@ static int GuessIsSensor(int fd) return 0; } -static int IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid) +static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid) { struct input_id inpid; char *name; @@ -312,6 +326,8 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick return 0; } *name_return = name; + *vendor_return = inpid.vendor; + *product_return = inpid.product; return 1; } @@ -389,6 +405,7 @@ static void MaybeAddDevice(const char *path) struct stat sb; int fd = -1; char *name = NULL; + Uint16 vendor, product; SDL_JoystickGUID guid; SDL_joylist_item *item; SDL_sensorlist_item *item_sensor; @@ -424,7 +441,7 @@ static void MaybeAddDevice(const char *path) SDL_Log("Checking %s\n", path); #endif - if (IsJoystick(path, fd, &name, &guid)) { + if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) { #ifdef DEBUG_INPUT_EVENTS SDL_Log("found joystick: %s\n", path); #endif @@ -436,10 +453,16 @@ static void MaybeAddDevice(const char *path) } item->devnum = sb.st_rdev; + item->steam_virtual_gamepad_slot = -1; item->path = SDL_strdup(path); item->name = name; item->guid = guid; + if (vendor == USB_VENDOR_VALVE && + product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot); + } + if ((!item->path) || (!item->name)) { FreeJoylistItem(item); goto done; @@ -845,19 +868,6 @@ static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b) return a->slot - b->slot; } -static SDL_bool get_virtual_gamepad_slot(const char *name, int *slot) -{ - const char *digits = SDL_strstr(name, "pad "); - if (digits) { - digits += 4; - if (SDL_isdigit(*digits)) { - *slot = SDL_atoi(digits); - return SDL_TRUE; - } - } - return SDL_FALSE; -} - static void LINUX_ScanSteamVirtualGamepads(void) { int i, count; @@ -880,7 +890,7 @@ static void LINUX_ScanSteamVirtualGamepads(void) inpid.vendor == USB_VENDOR_VALVE && inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && - get_virtual_gamepad_slot(name, &virtual_gamepad_slot)) { + GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) { VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); if (new_virtual_gamepads) { VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; @@ -1108,7 +1118,7 @@ static const char *LINUX_JoystickGetDevicePath(int device_index) static int LINUX_JoystickGetDevicePlayerIndex(int device_index) { - return -1; + return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot; } static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) From 34eb24ebc4f140b91aecc38701ee549c377f9eca Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 10 Dec 2023 08:35:35 -0800 Subject: [PATCH 541/725] Back out Steam virtual gamepad changes We are planning a different approach to handle these --- src/joystick/linux/SDL_sysjoystick.c | 131 ++++----------------------- 1 file changed, 17 insertions(+), 114 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 965e5f415af0a..9b8a85f26678f 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -156,7 +156,6 @@ typedef struct SDL_joylist_item char *name; /* "SideWinder 3D Pro" or whatever */ SDL_JoystickGUID guid; dev_t devnum; - int steam_virtual_gamepad_slot; struct joystick_hwdata *hwdata; struct SDL_joylist_item *next; @@ -220,19 +219,6 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, } #endif /* SDL_JOYSTICK_HIDAPI */ -static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot) -{ - const char *digits = SDL_strstr(name, "pad "); - if (digits) { - digits += 4; - if (SDL_isdigit(*digits)) { - *slot = SDL_atoi(digits); - return SDL_TRUE; - } - } - return SDL_FALSE; -} - static int GuessDeviceClass(int fd) { unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 }; @@ -273,7 +259,7 @@ static int GuessIsSensor(int fd) return 0; } -static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid) +static int IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid) { struct input_id inpid; char *name; @@ -326,8 +312,6 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend return 0; } *name_return = name; - *vendor_return = inpid.vendor; - *product_return = inpid.product; return 1; } @@ -405,7 +389,6 @@ static void MaybeAddDevice(const char *path) struct stat sb; int fd = -1; char *name = NULL; - Uint16 vendor, product; SDL_JoystickGUID guid; SDL_joylist_item *item; SDL_sensorlist_item *item_sensor; @@ -441,7 +424,7 @@ static void MaybeAddDevice(const char *path) SDL_Log("Checking %s\n", path); #endif - if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) { + if (IsJoystick(path, fd, &name, &guid)) { #ifdef DEBUG_INPUT_EVENTS SDL_Log("found joystick: %s\n", path); #endif @@ -453,16 +436,10 @@ static void MaybeAddDevice(const char *path) } item->devnum = sb.st_rdev; - item->steam_virtual_gamepad_slot = -1; item->path = SDL_strdup(path); item->name = name; item->guid = guid; - if (vendor == USB_VENDOR_VALVE && - product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { - GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot); - } - if ((!item->path) || (!item->name)) { FreeJoylistItem(item); goto done; @@ -855,91 +832,6 @@ static int SDLCALL sort_entries(const void *_a, const void *_b) return numA - numB; } -typedef struct -{ - char *path; - int slot; -} VirtualGamepadEntry; - -static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b) -{ - const VirtualGamepadEntry *a = (const VirtualGamepadEntry *)_a; - const VirtualGamepadEntry *b = (const VirtualGamepadEntry *)_b; - return a->slot - b->slot; -} - -static void LINUX_ScanSteamVirtualGamepads(void) -{ - int i, count; - int fd; - struct dirent **entries = NULL; - char path[PATH_MAX]; - char name[128]; - struct input_id inpid; - int num_virtual_gamepads = 0; - int virtual_gamepad_slot; - VirtualGamepadEntry *virtual_gamepads = NULL; - - count = scandir("/dev/input", &entries, filter_entries, NULL); - for (i = 0; i < count; ++i) { - (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); - - fd = open(path, O_RDONLY | O_CLOEXEC, 0); - if (fd >= 0) { - if (ioctl(fd, EVIOCGID, &inpid) == 0 && - inpid.vendor == USB_VENDOR_VALVE && - inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && - ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && - GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) { - VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); - if (new_virtual_gamepads) { - VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; - entry->path = SDL_strdup(path); - entry->slot = virtual_gamepad_slot; - if (entry->path) { - virtual_gamepads = new_virtual_gamepads; - ++num_virtual_gamepads; - } else { - SDL_free(entry->path); - SDL_free(new_virtual_gamepads); - } - } - } - close(fd); - } - free(entries[i]); /* This should NOT be SDL_free() */ - } - free(entries); /* This should NOT be SDL_free() */ - - if (num_virtual_gamepads > 1) { - SDL_qsort(virtual_gamepads, num_virtual_gamepads, sizeof(*virtual_gamepads), sort_virtual_gamepads); - } - for (i = 0; i < num_virtual_gamepads; ++i) { - MaybeAddDevice(virtual_gamepads[i].path); - SDL_free(virtual_gamepads[i].path); - } - SDL_free(virtual_gamepads); -} - -static void LINUX_ScanInputDevices(void) -{ - int i, count; - struct dirent **entries = NULL; - char path[PATH_MAX]; - - count = scandir("/dev/input", &entries, filter_entries, NULL); - if (count > 1) { - SDL_qsort(entries, count, sizeof(*entries), sort_entries); - } - for (i = 0; i < count; ++i) { - (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); - MaybeAddDevice(path); - - free(entries[i]); /* This should NOT be SDL_free() */ - } - free(entries); /* This should NOT be SDL_free() */ -} - static void LINUX_FallbackJoystickDetect(void) { const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ @@ -950,10 +842,21 @@ static void LINUX_FallbackJoystickDetect(void) /* Opening input devices can generate synchronous device I/O, so avoid it if we can */ if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) { - /* Look for Steam virtual gamepads first, and sort by Steam controller slot */ - LINUX_ScanSteamVirtualGamepads(); + int i, count; + struct dirent **entries = NULL; + char path[PATH_MAX]; - LINUX_ScanInputDevices(); + count = scandir("/dev/input", &entries, filter_entries, NULL); + if (count > 1) { + SDL_qsort(entries, count, sizeof(*entries), sort_entries); + } + for (i = 0; i < count; ++i) { + (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); + MaybeAddDevice(path); + + free(entries[i]); /* This should NOT be SDL_free() */ + } + free(entries); /* This should NOT be SDL_free() */ last_input_dir_mtime = sb.st_mtime; } @@ -1118,7 +1021,7 @@ static const char *LINUX_JoystickGetDevicePath(int device_index) static int LINUX_JoystickGetDevicePlayerIndex(int device_index) { - return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot; + return -1; } static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) From 5173b0c2cce5a68f1f72d77b4788f5e1da332719 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 10 Dec 2023 11:27:15 -0800 Subject: [PATCH 542/725] Make built-in joystick device lists extendable by using hints Fixes https://github.com/libsdl-org/SDL/issues/8595 --- include/SDL3/SDL_hints.h | 195 +++++++++ src/joystick/SDL_gamepad.c | 41 +- src/joystick/SDL_joystick.c | 792 +++++++++++++++++++--------------- src/joystick/SDL_joystick_c.h | 20 +- 4 files changed, 681 insertions(+), 367 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index f71ed32f80ffa..10c24e1151bff 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -631,6 +631,110 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" +/** + * A variable containing a list of arcade stick style controllers. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES" + +/** + * A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED" + +/** + * A variable containing a list of devices that should not be considerd joysticks. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES" + +/** + * A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" + +/** + * A variable containing a list of flightstick style controllers. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES" + +/** + * A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED" + +/** + * A variable containing a list of devices known to have a GameCube form factor. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES" + +/** + * A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" + /** * A variable controlling whether the HIDAPI joystick drivers should be used. * @@ -1025,6 +1129,32 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" +/** + * A variable containing a list of throttle style controllers. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES" + +/** + * A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED" + /** * A variable controlling whether Windows.Gaming.Input should be used for controller handling. * @@ -1034,6 +1164,45 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" +/** + * A variable containing a list of wheel style controllers. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES" + +/** + * A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" + +/** + * A variable containing a list of devices known to have all axes centered at zero. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" + /** * Determines whether SDL enforces that DRM master is required in order * to initialize the KMSDRM video backend. @@ -1491,6 +1660,32 @@ extern "C" { */ #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" +/** + * A variable containing a list of ROG gamepad capable mice. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE" + +/** + * A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" + /** * A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS * diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 66b74cd0027de..e206f7feb67be 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -140,18 +140,18 @@ struct SDL_Gamepad return retval; \ } -static SDL_vidpid_list SDL_allowed_gamepads; -static SDL_vidpid_list SDL_ignored_gamepads; - -static void SDLCALL SDL_GamepadIgnoreDevicesChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_LoadVIDPIDListFromHint(hint, &SDL_ignored_gamepads); -} - -static void SDLCALL SDL_GamepadIgnoreDevicesExceptChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_LoadVIDPIDListFromHint(hint, &SDL_allowed_gamepads); -} +static SDL_vidpid_list SDL_allowed_gamepads = { + SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, 0, 0, NULL, + NULL, 0, 0, NULL, + 0, NULL, + SDL_FALSE +}; +static SDL_vidpid_list SDL_ignored_gamepads = { + SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES, 0, 0, NULL, + NULL, 0, 0, NULL, + 0, NULL, + SDL_FALSE +}; static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_bool *existing, SDL_GamepadMappingPriority priority); static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t *pGamepadMapping); @@ -2276,10 +2276,8 @@ int SDL_InitGamepadMappings(void) /* load in any user supplied config */ SDL_LoadGamepadHints(); - SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES, - SDL_GamepadIgnoreDevicesChanged, NULL); - SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, - SDL_GamepadIgnoreDevicesExceptChanged, NULL); + SDL_LoadVIDPIDList(&SDL_allowed_gamepads); + SDL_LoadVIDPIDList(&SDL_ignored_gamepads); PopMappingChangeTracking(); @@ -2506,8 +2504,8 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) return SDL_TRUE; } - if (SDL_allowed_gamepads.num_entries == 0 && - SDL_ignored_gamepads.num_entries == 0) { + if (SDL_allowed_gamepads.num_included_entries == 0 && + SDL_ignored_gamepads.num_included_entries == 0) { return SDL_FALSE; } @@ -2530,7 +2528,7 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) } } - if (SDL_allowed_gamepads.num_entries > 0) { + if (SDL_allowed_gamepads.num_included_entries > 0) { if (SDL_VIDPIDInList(vendor, product, &SDL_allowed_gamepads)) { return SDL_FALSE; } @@ -3583,11 +3581,6 @@ void SDL_QuitGamepadMappings(void) SDL_free(pGamepadMap); } - SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES, - SDL_GamepadIgnoreDevicesChanged, NULL); - SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, - SDL_GamepadIgnoreDevicesExceptChanged, NULL); - SDL_FreeVIDPIDList(&SDL_allowed_gamepads); SDL_FreeVIDPIDList(&SDL_ignored_gamepads); } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index cc0ca88d3a754..48ce23acc9b9c 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -121,6 +121,284 @@ static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; char SDL_joystick_magic; +static Uint32 initial_arcadestick_devices[] = { + MAKE_VIDPID(0x0079, 0x181a), /* Venom Arcade Stick */ + MAKE_VIDPID(0x0079, 0x181b), /* Venom Arcade Stick */ + MAKE_VIDPID(0x0c12, 0x0ef6), /* Hitbox Arcade Stick */ + MAKE_VIDPID(0x0e6f, 0x0109), /* PDP Versus Fighting Pad */ + MAKE_VIDPID(0x0f0d, 0x0016), /* Hori Real Arcade Pro.EX */ + MAKE_VIDPID(0x0f0d, 0x001b), /* Hori Real Arcade Pro VX */ + MAKE_VIDPID(0x0f0d, 0x0063), /* Hori Real Arcade Pro Hayabusa (USA) Xbox One */ + MAKE_VIDPID(0x0f0d, 0x006a), /* Real Arcade Pro 4 */ + MAKE_VIDPID(0x0f0d, 0x0078), /* Hori Real Arcade Pro V Kai Xbox One */ + MAKE_VIDPID(0x0f0d, 0x008a), /* HORI Real Arcade Pro 4 */ + MAKE_VIDPID(0x0f0d, 0x008c), /* Hori Real Arcade Pro 4 */ + MAKE_VIDPID(0x0f0d, 0x00aa), /* HORI Real Arcade Pro V Hayabusa in Switch Mode */ + MAKE_VIDPID(0x0f0d, 0x00ed), /* Hori Fighting Stick mini 4 kai */ + MAKE_VIDPID(0x0f0d, 0x011c), /* Hori Fighting Stick α in PS4 Mode */ + MAKE_VIDPID(0x0f0d, 0x011e), /* Hori Fighting Stick α in PC Mode */ + MAKE_VIDPID(0x0f0d, 0x0184), /* Hori Fighting Stick α in PS5 Mode */ + MAKE_VIDPID(0x146b, 0x0604), /* NACON Daija Arcade Stick */ + MAKE_VIDPID(0x1532, 0x0a00), /* Razer Atrox Arcade Stick */ + MAKE_VIDPID(0x1bad, 0xf03d), /* Street Fighter IV Arcade Stick TE - Chun Li */ + MAKE_VIDPID(0x1bad, 0xf502), /* Hori Real Arcade Pro.VX SA */ + MAKE_VIDPID(0x1bad, 0xf504), /* Hori Real Arcade Pro. EX */ + MAKE_VIDPID(0x1bad, 0xf506), /* Hori Real Arcade Pro.EX Premium VLX */ + MAKE_VIDPID(0x20d6, 0xa715), /* PowerA Nintendo Switch Fusion Arcade Stick */ + MAKE_VIDPID(0x24c6, 0x5000), /* Razer Atrox Arcade Stick */ + MAKE_VIDPID(0x24c6, 0x5501), /* Hori Real Arcade Pro VX-SA */ + MAKE_VIDPID(0x24c6, 0x550e), /* Hori Real Arcade Pro V Kai 360 */ + MAKE_VIDPID(0x2c22, 0x2300), /* Qanba Obsidian Arcade Joystick in PS4 Mode */ + MAKE_VIDPID(0x2c22, 0x2302), /* Qanba Obsidian Arcade Joystick in PS3 Mode */ + MAKE_VIDPID(0x2c22, 0x2303), /* Qanba Obsidian Arcade Joystick in PC Mode */ + MAKE_VIDPID(0x2c22, 0x2500), /* Qanba Dragon Arcade Joystick in PS4 Mode */ + MAKE_VIDPID(0x2c22, 0x2502), /* Qanba Dragon Arcade Joystick in PS3 Mode */ + MAKE_VIDPID(0x2c22, 0x2503), /* Qanba Dragon Arcade Joystick in PC Mode */ +}; +static SDL_vidpid_list arcadestick_devices = { + SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_arcadestick_devices), initial_arcadestick_devices, + SDL_FALSE +}; + +/* This list is taken from: + https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py + */ +static Uint32 initial_blacklist_devices[] = { + /* Microsoft Microsoft Wireless Optical Desktop 2.10 */ + /* Microsoft Wireless Desktop - Comfort Edition */ + MAKE_VIDPID(0x045e, 0x009d), + + /* Microsoft Microsoft Digital Media Pro Keyboard */ + /* Microsoft Corp. Digital Media Pro Keyboard */ + MAKE_VIDPID(0x045e, 0x00b0), + + /* Microsoft Microsoft Digital Media Keyboard */ + /* Microsoft Corp. Digital Media Keyboard 1.0A */ + MAKE_VIDPID(0x045e, 0x00b4), + + /* Microsoft Microsoft Digital Media Keyboard 3000 */ + MAKE_VIDPID(0x045e, 0x0730), + + /* Microsoft Microsoft 2.4GHz Transceiver v6.0 */ + /* Microsoft Microsoft 2.4GHz Transceiver v8.0 */ + /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */ + /* Microsoft Wireless Mobile Mouse 1000 */ + /* Microsoft Wireless Desktop 3000 */ + MAKE_VIDPID(0x045e, 0x0745), + + /* Microsoft SideWinder(TM) 2.4GHz Transceiver */ + MAKE_VIDPID(0x045e, 0x0748), + + /* Microsoft Corp. Wired Keyboard 600 */ + MAKE_VIDPID(0x045e, 0x0750), + + /* Microsoft Corp. Sidewinder X4 keyboard */ + MAKE_VIDPID(0x045e, 0x0768), + + /* Microsoft Corp. Arc Touch Mouse Transceiver */ + MAKE_VIDPID(0x045e, 0x0773), + + /* Microsoft 2.4GHz Transceiver v9.0 */ + /* Microsoft Nano Transceiver v2.1 */ + /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */ + MAKE_VIDPID(0x045e, 0x07a5), + + /* Microsoft Nano Transceiver v1.0 */ + /* Microsoft Wireless Keyboard 800 */ + MAKE_VIDPID(0x045e, 0x07b2), + + /* Microsoft Nano Transceiver v2.0 */ + MAKE_VIDPID(0x045e, 0x0800), + + MAKE_VIDPID(0x046d, 0xc30a), /* Logitech, Inc. iTouch Composite keboard */ + + MAKE_VIDPID(0x04d9, 0xa0df), /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */ + + /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */ + MAKE_VIDPID(0x056a, 0x0010), /* Wacom ET-0405 Graphire */ + MAKE_VIDPID(0x056a, 0x0011), /* Wacom ET-0405A Graphire2 (4x5) */ + MAKE_VIDPID(0x056a, 0x0012), /* Wacom ET-0507A Graphire2 (5x7) */ + MAKE_VIDPID(0x056a, 0x0013), /* Wacom CTE-430 Graphire3 (4x5) */ + MAKE_VIDPID(0x056a, 0x0014), /* Wacom CTE-630 Graphire3 (6x8) */ + MAKE_VIDPID(0x056a, 0x0015), /* Wacom CTE-440 Graphire4 (4x5) */ + MAKE_VIDPID(0x056a, 0x0016), /* Wacom CTE-640 Graphire4 (6x8) */ + MAKE_VIDPID(0x056a, 0x0017), /* Wacom CTE-450 Bamboo Fun (4x5) */ + MAKE_VIDPID(0x056a, 0x0018), /* Wacom CTE-650 Bamboo Fun 6x8 */ + MAKE_VIDPID(0x056a, 0x0019), /* Wacom CTE-631 Bamboo One */ + MAKE_VIDPID(0x056a, 0x00d1), /* Wacom Bamboo Pen and Touch CTH-460 */ + MAKE_VIDPID(0x056a, 0x030e), /* Wacom Intuos Pen (S) CTL-480 */ + + MAKE_VIDPID(0x09da, 0x054f), /* A4 Tech Co., G7 750 mouse */ + MAKE_VIDPID(0x09da, 0x1410), /* A4 Tech Co., Ltd Bloody AL9 mouse */ + MAKE_VIDPID(0x09da, 0x3043), /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */ + MAKE_VIDPID(0x09da, 0x31b5), /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */ + MAKE_VIDPID(0x09da, 0x3997), /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */ + MAKE_VIDPID(0x09da, 0x3f8b), /* A4 Tech Co., Ltd Bloody V8 mouse */ + MAKE_VIDPID(0x09da, 0x51f4), /* Modecom MC-5006 Keyboard */ + MAKE_VIDPID(0x09da, 0x5589), /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */ + MAKE_VIDPID(0x09da, 0x7b22), /* A4 Tech Co., Ltd Bloody V5 */ + MAKE_VIDPID(0x09da, 0x7f2d), /* A4 Tech Co., Ltd Bloody R3 mouse */ + MAKE_VIDPID(0x09da, 0x8090), /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */ + MAKE_VIDPID(0x09da, 0x9033), /* A4 Tech Co., X7 X-705K */ + MAKE_VIDPID(0x09da, 0x9066), /* A4 Tech Co., Sharkoon Fireglider Optical */ + MAKE_VIDPID(0x09da, 0x9090), /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */ + MAKE_VIDPID(0x09da, 0x90c0), /* A4 Tech Co., Ltd X7 G800V keyboard */ + MAKE_VIDPID(0x09da, 0xf012), /* A4 Tech Co., Ltd Bloody V7 mouse */ + MAKE_VIDPID(0x09da, 0xf32a), /* A4 Tech Co., Ltd Bloody B540 keyboard */ + MAKE_VIDPID(0x09da, 0xf613), /* A4 Tech Co., Ltd Bloody V2 mouse */ + MAKE_VIDPID(0x09da, 0xf624), /* A4 Tech Co., Ltd Bloody B120 Keyboard */ + + MAKE_VIDPID(0x1b1c, 0x1b3c), /* Corsair Harpoon RGB gaming mouse */ + + MAKE_VIDPID(0x1d57, 0xad03), /* [T3] 2.4GHz and IR Air Mouse Remote Control */ + + MAKE_VIDPID(0x1e7d, 0x2e4a), /* Roccat Tyon Mouse */ + + MAKE_VIDPID(0x20a0, 0x422d), /* Winkeyless.kr Keyboards */ + + MAKE_VIDPID(0x2516, 0x001f), /* Cooler Master Storm Mizar Mouse */ + MAKE_VIDPID(0x2516, 0x0028), /* Cooler Master Storm Alcor Mouse */ + + /*****************************************************************/ + /* Additional entries */ + /*****************************************************************/ + + MAKE_VIDPID(0x04d9, 0x8008), /* OBINLB USB-HID Keyboard (Anne Pro II) */ + MAKE_VIDPID(0x04d9, 0x8009), /* OBINLB USB-HID Keyboard (Anne Pro II) */ + MAKE_VIDPID(0x04d9, 0xa292), /* OBINLB USB-HID Keyboard (Anne Pro II) */ + MAKE_VIDPID(0x04d9, 0xa293), /* OBINLB USB-HID Keyboard (Anne Pro II) */ + MAKE_VIDPID(0x1532, 0x0266), /* Razer Huntsman V2 Analog, non-functional DInput device */ + MAKE_VIDPID(0x1532, 0x0282), /* Razer Huntsman Mini Analog, non-functional DInput device */ + MAKE_VIDPID(0x26ce, 0x01a2), /* ASRock LED Controller */ + MAKE_VIDPID(0x20d6, 0x0002), /* PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only) */ +}; +static SDL_vidpid_list blacklist_devices = { + SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_blacklist_devices), initial_blacklist_devices, + SDL_FALSE +}; + +static Uint32 initial_flightstick_devices[] = { + MAKE_VIDPID(0x044f, 0x0402), /* HOTAS Warthog Joystick */ + MAKE_VIDPID(0x0738, 0x2221), /* Saitek Pro Flight X-56 Rhino Stick */ + MAKE_VIDPID(0x044f, 0xb10a), /* ThrustMaster, Inc. T.16000M Joystick */ + MAKE_VIDPID(0x046d, 0xc215), /* Logitech Extreme 3D */ + MAKE_VIDPID(0x231d, 0x0126), /* Gunfighter Mk.III ‘Space Combat Edition’ (right) */ + MAKE_VIDPID(0x231d, 0x0127), /* Gunfighter Mk.III ‘Space Combat Edition’ (left) */ +}; +static SDL_vidpid_list flightstick_devices = { + SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_flightstick_devices), initial_flightstick_devices, + SDL_FALSE +}; + +static Uint32 initial_gamecube_devices[] = { + MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ + MAKE_VIDPID(0x20d6, 0xa711), /* PowerA Wired Controller Nintendo GameCube Style */ +}; +static SDL_vidpid_list gamecube_devices = { + SDL_HINT_JOYSTICK_GAMECUBE_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_gamecube_devices), initial_gamecube_devices, + SDL_FALSE +}; + +static Uint32 initial_rog_gamepad_mice[] = { + MAKE_VIDPID(0x0b05, 0x1906), /* ROG Pugio II */ + MAKE_VIDPID(0x0b05, 0x1958), /* ROG Chakram Core Mouse */ + MAKE_VIDPID(0x0b05, 0x18e3), /* ROG Chakram (wired) Mouse */ + MAKE_VIDPID(0x0b05, 0x18e5), /* ROG Chakram (wireless) Mouse */ + MAKE_VIDPID(0x0b05, 0x1a18), /* ROG Chakram X (wired) Mouse */ + MAKE_VIDPID(0x0b05, 0x1a1a), /* ROG Chakram X (wireless) Mouse */ + MAKE_VIDPID(0x0b05, 0x1a1c), /* ROG Chakram X (Bluetooth) Mouse */ +}; +static SDL_vidpid_list rog_gamepad_mice = { + SDL_HINT_ROG_GAMEPAD_MICE, 0, 0, NULL, + SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_rog_gamepad_mice), initial_rog_gamepad_mice, + SDL_FALSE +}; + +static Uint32 initial_throttle_devices[] = { + MAKE_VIDPID(0x044f, 0x0404), /* HOTAS Warthog Throttle */ + MAKE_VIDPID(0x0738, 0xa221), /* Saitek Pro Flight X-56 Rhino Throttle */ +}; +static SDL_vidpid_list throttle_devices = { + SDL_HINT_JOYSTICK_THROTTLE_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_throttle_devices), initial_throttle_devices, + SDL_FALSE +}; + +static Uint32 initial_wheel_devices[] = { + MAKE_VIDPID(0x0079, 0x1864), /* DragonRise Inc. Wired Wheel (active mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ + MAKE_VIDPID(0x046d, 0xc294), /* Logitech generic wheel */ + MAKE_VIDPID(0x046d, 0xc295), /* Logitech Momo Force */ + MAKE_VIDPID(0x046d, 0xc298), /* Logitech Driving Force Pro */ + MAKE_VIDPID(0x046d, 0xc299), /* Logitech G25 */ + MAKE_VIDPID(0x046d, 0xc29a), /* Logitech Driving Force GT */ + MAKE_VIDPID(0x046d, 0xc29b), /* Logitech G27 */ + MAKE_VIDPID(0x046d, 0xc24f), /* Logitech G29 (PS3) */ + MAKE_VIDPID(0x046d, 0xc260), /* Logitech G29 (PS4) */ + MAKE_VIDPID(0x046d, 0xc261), /* Logitech G920 (initial mode) */ + MAKE_VIDPID(0x046d, 0xc262), /* Logitech G920 (active mode) */ + MAKE_VIDPID(0x046d, 0xc268), /* Logitech PRO Racing Wheel (PC mode) */ + MAKE_VIDPID(0x046d, 0xc269), /* Logitech PRO Racing Wheel (PS4/PS5 mode) */ + MAKE_VIDPID(0x046d, 0xc272), /* Logitech PRO Racing Wheel for Xbox (PC mode) */ + MAKE_VIDPID(0x046d, 0xc26d), /* Logitech G923 (Xbox) */ + MAKE_VIDPID(0x046d, 0xc26e), /* Logitech G923 */ + MAKE_VIDPID(0x046d, 0xc266), /* Logitech G923 for Playstation 4 and PC (PC mode) */ + MAKE_VIDPID(0x046d, 0xc267), /* Logitech G923 for Playstation 4 and PC (PS4 mode)*/ + MAKE_VIDPID(0x046d, 0xca03), /* Logitech Momo Racing */ + MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */ + MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */ + MAKE_VIDPID(0x044f, 0xb677), /* Thrustmaster T150 */ + MAKE_VIDPID(0x044f, 0xb696), /* Thrustmaster T248 */ + MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS (normal mode) */ + MAKE_VIDPID(0x044f, 0xb66f), /* Thrustmaster T300RS (advanced mode) */ + MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster T300RS (PS4 mode) */ + MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */ + MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */ + MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */ + MAKE_VIDPID(0x0483, 0x0522), /* Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U) */ + MAKE_VIDPID(0x0eb7, 0x0001), /* Fanatec ClubSport Wheel Base V2 */ + MAKE_VIDPID(0x0eb7, 0x0004), /* Fanatec ClubSport Wheel Base V2.5 */ + MAKE_VIDPID(0x0eb7, 0x0005), /* Fanatec CSL Elite Wheel Base+ (PS4) */ + MAKE_VIDPID(0x0eb7, 0x0006), /* Fanatec Podium Wheel Base DD1 */ + MAKE_VIDPID(0x0eb7, 0x0007), /* Fanatec Podium Wheel Base DD2 */ + MAKE_VIDPID(0x0eb7, 0x0011), /* Fanatec Forza Motorsport (CSR Wheel / CSR Elite Wheel) */ + MAKE_VIDPID(0x0eb7, 0x0020), /* Fanatec generic wheel / CSL DD / GT DD Pro */ + MAKE_VIDPID(0x0eb7, 0x0197), /* Fanatec Porsche Wheel (Turbo / GT3 RS / Turbo S / GT3 V2 / GT2) */ + MAKE_VIDPID(0x0eb7, 0x038e), /* Fanatec ClubSport Wheel Base V1 */ + MAKE_VIDPID(0x0eb7, 0x0e03), /* Fanatec CSL Elite Wheel Base */ + MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ + MAKE_VIDPID(0x2433, 0xf300), /* Asetek SimSports Invicta Wheelbase */ + MAKE_VIDPID(0x2433, 0xf301), /* Asetek SimSports Forte Wheelbase */ + MAKE_VIDPID(0x2433, 0xf303), /* Asetek SimSports La Prima Wheelbase */ + MAKE_VIDPID(0x2433, 0xf306), /* Asetek SimSports Tony Kannan Wheelbase */ +}; +static SDL_vidpid_list wheel_devices = { + SDL_HINT_JOYSTICK_WHEEL_DEVICES, 0, 0, NULL, + SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED, 0, 0, NULL, + SDL_arraysize(initial_wheel_devices), initial_wheel_devices, + SDL_FALSE +}; + +static Uint32 initial_zero_centered_devices[] = { + MAKE_VIDPID(0x0e8f, 0x3013), /* HuiJia SNES USB adapter */ + MAKE_VIDPID(0x05a0, 0x3232), /* 8Bitdo Zero Gamepad */ +}; +static SDL_vidpid_list zero_centered_devices = { + SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES, 0, 0, NULL, + NULL, 0, 0, NULL, + SDL_arraysize(initial_zero_centered_devices), initial_zero_centered_devices, + SDL_FALSE +}; + #define CHECK_JOYSTICK_MAGIC(joystick, retval) \ if (!joystick || joystick->magic != &SDL_joystick_magic) { \ SDL_InvalidParamError("joystick"); \ @@ -333,6 +611,15 @@ int SDL_InitJoysticks(void) SDL_InitGamepadMappings(); + SDL_LoadVIDPIDList(&arcadestick_devices); + SDL_LoadVIDPIDList(&blacklist_devices); + SDL_LoadVIDPIDList(&flightstick_devices); + SDL_LoadVIDPIDList(&gamecube_devices); + SDL_LoadVIDPIDList(&rog_gamepad_mice); + SDL_LoadVIDPIDList(&throttle_devices); + SDL_LoadVIDPIDList(&wheel_devices); + SDL_LoadVIDPIDList(&zero_centered_devices); + /* See if we should allow joystick events while in the background */ SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_JoystickAllowBackgroundEventsChanged, NULL); @@ -474,35 +761,14 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) #ifdef __WINRT__ return SDL_TRUE; #else - static Uint32 zero_centered_joysticks[] = { - MAKE_VIDPID(0x0e8f, 0x3013), /* HuiJia SNES USB adapter */ - MAKE_VIDPID(0x05a0, 0x3232), /* 8Bitdo Zero Gamepad */ - }; - - SDL_bool retval = SDL_FALSE; - int i; - Uint32 id = MAKE_VIDPID(SDL_GetJoystickVendor(joystick), - SDL_GetJoystickProduct(joystick)); - /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/ - SDL_LockJoysticks(); - { - if (joystick->naxes == 2) { - /* Assume D-pad or thumbstick style axes are centered at 0 */ - retval = SDL_TRUE; - } - - for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) { - if (id == zero_centered_joysticks[i]) { - retval = SDL_TRUE; - break; - } - } + if (joystick->naxes == 2) { + /* Assume D-pad or thumbstick style axes are centered at 0 */ + return SDL_TRUE; } - SDL_UnlockJoysticks(); - return retval; + return SDL_VIDPIDInList(SDL_GetJoystickVendor(joystick), SDL_GetJoystickProduct(joystick), &zero_centered_devices); #endif /* __WINRT__ */ } @@ -587,7 +853,7 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *inve /* See if the gamepad is in our list of devices to enable */ guid = SDL_GetJoystickGUID(joystick); SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); - SDL_LoadVIDPIDListFromHint(hint, &gamepads); + SDL_LoadVIDPIDListFromHints(&gamepads, hint, NULL); enabled = SDL_VIDPIDInList(vendor, product, &gamepads); SDL_FreeVIDPIDList(&gamepads); if (enabled) { @@ -1560,6 +1826,15 @@ void SDL_QuitJoysticks(void) SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_JoystickAllowBackgroundEventsChanged, NULL); + SDL_FreeVIDPIDList(&arcadestick_devices); + SDL_FreeVIDPIDList(&blacklist_devices); + SDL_FreeVIDPIDList(&flightstick_devices); + SDL_FreeVIDPIDList(&gamecube_devices); + SDL_FreeVIDPIDList(&rog_gamepad_mice); + SDL_FreeVIDPIDList(&throttle_devices); + SDL_FreeVIDPIDList(&wheel_devices); + SDL_FreeVIDPIDList(&zero_centered_devices); + SDL_QuitGamepadMappings(); SDL_joysticks_quitting = SDL_FALSE; @@ -2613,19 +2888,7 @@ SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id) { - static Uint32 gamecube_formfactor[] = { - MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ - MAKE_VIDPID(0x20d6, 0xa711), /* PowerA Wired Controller Nintendo GameCube Style */ - }; - Uint32 id = MAKE_VIDPID(vendor_id, product_id); - int i; - - for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) { - if (id == gamecube_formfactor[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; + return SDL_VIDPIDInList(vendor_id, product_id, &gamecube_devices); } SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id) @@ -2682,152 +2945,48 @@ SDL_bool SDL_IsJoystickVIRTUAL(SDL_JoystickGUID guid) return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE; } -static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid) -{ - static Uint32 wheel_joysticks[] = { - MAKE_VIDPID(0x0079, 0x1864), /* DragonRise Inc. Wired Wheel (active mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ - MAKE_VIDPID(0x046d, 0xc294), /* Logitech generic wheel */ - MAKE_VIDPID(0x046d, 0xc295), /* Logitech Momo Force */ - MAKE_VIDPID(0x046d, 0xc298), /* Logitech Driving Force Pro */ - MAKE_VIDPID(0x046d, 0xc299), /* Logitech G25 */ - MAKE_VIDPID(0x046d, 0xc29a), /* Logitech Driving Force GT */ - MAKE_VIDPID(0x046d, 0xc29b), /* Logitech G27 */ - MAKE_VIDPID(0x046d, 0xc24f), /* Logitech G29 (PS3) */ - MAKE_VIDPID(0x046d, 0xc260), /* Logitech G29 (PS4) */ - MAKE_VIDPID(0x046d, 0xc261), /* Logitech G920 (initial mode) */ - MAKE_VIDPID(0x046d, 0xc262), /* Logitech G920 (active mode) */ - MAKE_VIDPID(0x046d, 0xc268), /* Logitech PRO Racing Wheel (PC mode) */ - MAKE_VIDPID(0x046d, 0xc269), /* Logitech PRO Racing Wheel (PS4/PS5 mode) */ - MAKE_VIDPID(0x046d, 0xc272), /* Logitech PRO Racing Wheel for Xbox (PC mode) */ - MAKE_VIDPID(0x046d, 0xc26d), /* Logitech G923 (Xbox) */ - MAKE_VIDPID(0x046d, 0xc26e), /* Logitech G923 */ - MAKE_VIDPID(0x046d, 0xc266), /* Logitech G923 for Playstation 4 and PC (PC mode) */ - MAKE_VIDPID(0x046d, 0xc267), /* Logitech G923 for Playstation 4 and PC (PS4 mode)*/ - MAKE_VIDPID(0x046d, 0xca03), /* Logitech Momo Racing */ - MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */ - MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */ - MAKE_VIDPID(0x044f, 0xb677), /* Thrustmaster T150 */ - MAKE_VIDPID(0x044f, 0xb696), /* Thrustmaster T248 */ - MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS (normal mode) */ - MAKE_VIDPID(0x044f, 0xb66f), /* Thrustmaster T300RS (advanced mode) */ - MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster T300RS (PS4 mode) */ - MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */ - MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */ - MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */ - MAKE_VIDPID(0x0483, 0x0522), /* Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U) */ - MAKE_VIDPID(0x0eb7, 0x0001), /* Fanatec ClubSport Wheel Base V2 */ - MAKE_VIDPID(0x0eb7, 0x0004), /* Fanatec ClubSport Wheel Base V2.5 */ - MAKE_VIDPID(0x0eb7, 0x0005), /* Fanatec CSL Elite Wheel Base+ (PS4) */ - MAKE_VIDPID(0x0eb7, 0x0006), /* Fanatec Podium Wheel Base DD1 */ - MAKE_VIDPID(0x0eb7, 0x0007), /* Fanatec Podium Wheel Base DD2 */ - MAKE_VIDPID(0x0eb7, 0x0011), /* Fanatec Forza Motorsport (CSR Wheel / CSR Elite Wheel) */ - MAKE_VIDPID(0x0eb7, 0x0020), /* Fanatec generic wheel / CSL DD / GT DD Pro */ - MAKE_VIDPID(0x0eb7, 0x0197), /* Fanatec Porsche Wheel (Turbo / GT3 RS / Turbo S / GT3 V2 / GT2) */ - MAKE_VIDPID(0x0eb7, 0x038e), /* Fanatec ClubSport Wheel Base V1 */ - MAKE_VIDPID(0x0eb7, 0x0e03), /* Fanatec CSL Elite Wheel Base */ - MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ - MAKE_VIDPID(0x2433, 0xf300), /* Asetek SimSports Invicta Wheelbase */ - MAKE_VIDPID(0x2433, 0xf301), /* Asetek SimSports Forte Wheelbase */ - MAKE_VIDPID(0x2433, 0xf303), /* Asetek SimSports La Prima Wheelbase */ - MAKE_VIDPID(0x2433, 0xf306), /* Asetek SimSports Tony Kannan Wheelbase */ - }; - int i; - - for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) { - if (vidpid == wheel_joysticks[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; +static SDL_bool SDL_IsJoystickWheel(Uint16 vendor_id, Uint16 product_id) +{ + return SDL_VIDPIDInList(vendor_id, product_id, &wheel_devices); } -static SDL_bool SDL_IsJoystickProductArcadeStick(Uint32 vidpid) -{ - static Uint32 arcadestick_joysticks[] = { - MAKE_VIDPID(0x0079, 0x181a), /* Venom Arcade Stick */ - MAKE_VIDPID(0x0079, 0x181b), /* Venom Arcade Stick */ - MAKE_VIDPID(0x0c12, 0x0ef6), /* Hitbox Arcade Stick */ - MAKE_VIDPID(0x0e6f, 0x0109), /* PDP Versus Fighting Pad */ - MAKE_VIDPID(0x0f0d, 0x0016), /* Hori Real Arcade Pro.EX */ - MAKE_VIDPID(0x0f0d, 0x001b), /* Hori Real Arcade Pro VX */ - MAKE_VIDPID(0x0f0d, 0x0063), /* Hori Real Arcade Pro Hayabusa (USA) Xbox One */ - MAKE_VIDPID(0x0f0d, 0x006a), /* Real Arcade Pro 4 */ - MAKE_VIDPID(0x0f0d, 0x0078), /* Hori Real Arcade Pro V Kai Xbox One */ - MAKE_VIDPID(0x0f0d, 0x008a), /* HORI Real Arcade Pro 4 */ - MAKE_VIDPID(0x0f0d, 0x008c), /* Hori Real Arcade Pro 4 */ - MAKE_VIDPID(0x0f0d, 0x00aa), /* HORI Real Arcade Pro V Hayabusa in Switch Mode */ - MAKE_VIDPID(0x0f0d, 0x00ed), /* Hori Fighting Stick mini 4 kai */ - MAKE_VIDPID(0x0f0d, 0x011c), /* Hori Fighting Stick α in PS4 Mode */ - MAKE_VIDPID(0x0f0d, 0x011e), /* Hori Fighting Stick α in PC Mode */ - MAKE_VIDPID(0x0f0d, 0x0184), /* Hori Fighting Stick α in PS5 Mode */ - MAKE_VIDPID(0x146b, 0x0604), /* NACON Daija Arcade Stick */ - MAKE_VIDPID(0x1532, 0x0a00), /* Razer Atrox Arcade Stick */ - MAKE_VIDPID(0x1bad, 0xf03d), /* Street Fighter IV Arcade Stick TE - Chun Li */ - MAKE_VIDPID(0x1bad, 0xf502), /* Hori Real Arcade Pro.VX SA */ - MAKE_VIDPID(0x1bad, 0xf504), /* Hori Real Arcade Pro. EX */ - MAKE_VIDPID(0x1bad, 0xf506), /* Hori Real Arcade Pro.EX Premium VLX */ - MAKE_VIDPID(0x20d6, 0xa715), /* PowerA Nintendo Switch Fusion Arcade Stick */ - MAKE_VIDPID(0x24c6, 0x5000), /* Razer Atrox Arcade Stick */ - MAKE_VIDPID(0x24c6, 0x5501), /* Hori Real Arcade Pro VX-SA */ - MAKE_VIDPID(0x24c6, 0x550e), /* Hori Real Arcade Pro V Kai 360 */ - MAKE_VIDPID(0x2c22, 0x2300), /* Qanba Obsidian Arcade Joystick in PS4 Mode */ - MAKE_VIDPID(0x2c22, 0x2302), /* Qanba Obsidian Arcade Joystick in PS3 Mode */ - MAKE_VIDPID(0x2c22, 0x2303), /* Qanba Obsidian Arcade Joystick in PC Mode */ - MAKE_VIDPID(0x2c22, 0x2500), /* Qanba Dragon Arcade Joystick in PS4 Mode */ - MAKE_VIDPID(0x2c22, 0x2502), /* Qanba Dragon Arcade Joystick in PS3 Mode */ - MAKE_VIDPID(0x2c22, 0x2503), /* Qanba Dragon Arcade Joystick in PC Mode */ - }; - int i; - - for (i = 0; i < SDL_arraysize(arcadestick_joysticks); ++i) { - if (vidpid == arcadestick_joysticks[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; +static SDL_bool SDL_IsJoystickArcadeStick(Uint16 vendor_id, Uint16 product_id) +{ + return SDL_VIDPIDInList(vendor_id, product_id, &arcadestick_devices); } -static SDL_bool SDL_IsJoystickProductFlightStick(Uint32 vidpid) +static SDL_bool SDL_IsJoystickFlightStick(Uint16 vendor_id, Uint16 product_id) { - static Uint32 flightstick_joysticks[] = { - MAKE_VIDPID(0x044f, 0x0402), /* HOTAS Warthog Joystick */ - MAKE_VIDPID(0x0738, 0x2221), /* Saitek Pro Flight X-56 Rhino Stick */ - MAKE_VIDPID(0x044f, 0xb10a), /* ThrustMaster, Inc. T.16000M Joystick */ - MAKE_VIDPID(0x046d, 0xc215), /* Logitech Extreme 3D */ - MAKE_VIDPID(0x231d, 0x0126), /* Gunfighter Mk.III ‘Space Combat Edition’ (right) */ - MAKE_VIDPID(0x231d, 0x0127), /* Gunfighter Mk.III ‘Space Combat Edition’ (left) */ - }; - int i; - - for (i = 0; i < SDL_arraysize(flightstick_joysticks); ++i) { - if (vidpid == flightstick_joysticks[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; + return SDL_VIDPIDInList(vendor_id, product_id, &flightstick_devices); } -static SDL_bool SDL_IsJoystickProductThrottle(Uint32 vidpid) +static SDL_bool SDL_IsJoystickThrottle(Uint16 vendor_id, Uint16 product_id) { - static Uint32 throttle_joysticks[] = { - MAKE_VIDPID(0x044f, 0x0404), /* HOTAS Warthog Throttle */ - MAKE_VIDPID(0x0738, 0xa221), /* Saitek Pro Flight X-56 Rhino Throttle */ - }; - int i; - - for (i = 0; i < SDL_arraysize(throttle_joysticks); ++i) { - if (vidpid == throttle_joysticks[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; + return SDL_VIDPIDInList(vendor_id, product_id, &throttle_devices); } static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid) { Uint16 vendor; Uint16 product; - Uint32 vidpid; + + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); + + if (SDL_IsJoystickWheel(vendor, product)) { + return SDL_JOYSTICK_TYPE_WHEEL; + } + + if (SDL_IsJoystickArcadeStick(vendor, product)) { + return SDL_JOYSTICK_TYPE_ARCADE_STICK; + } + + if (SDL_IsJoystickFlightStick(vendor, product)) { + return SDL_JOYSTICK_TYPE_FLIGHT_STICK; + } + + if (SDL_IsJoystickThrottle(vendor, product)) { + return SDL_JOYSTICK_TYPE_THROTTLE; + } if (SDL_IsJoystickXInput(guid)) { /* XInput GUID, get the type based on the XInput device subtype */ @@ -2863,25 +3022,6 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid) return (SDL_JoystickType)guid.data[15]; } - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); - vidpid = MAKE_VIDPID(vendor, product); - - if (SDL_IsJoystickProductWheel(vidpid)) { - return SDL_JOYSTICK_TYPE_WHEEL; - } - - if (SDL_IsJoystickProductArcadeStick(vidpid)) { - return SDL_JOYSTICK_TYPE_ARCADE_STICK; - } - - if (SDL_IsJoystickProductFlightStick(vidpid)) { - return SDL_JOYSTICK_TYPE_FLIGHT_STICK; - } - - if (SDL_IsJoystickProductThrottle(vidpid)) { - return SDL_JOYSTICK_TYPE_THROTTLE; - } - #ifdef SDL_JOYSTICK_HIDAPI if (SDL_IsJoystickHIDAPI(guid)) { return HIDAPI_GetJoystickTypeFromGUID(guid); @@ -2897,148 +3037,18 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid) SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid) { - /* This list is taken from: - https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py - */ - static Uint32 joystick_blacklist[] = { - /* Microsoft Microsoft Wireless Optical Desktop 2.10 */ - /* Microsoft Wireless Desktop - Comfort Edition */ - MAKE_VIDPID(0x045e, 0x009d), - - /* Microsoft Microsoft Digital Media Pro Keyboard */ - /* Microsoft Corp. Digital Media Pro Keyboard */ - MAKE_VIDPID(0x045e, 0x00b0), - - /* Microsoft Microsoft Digital Media Keyboard */ - /* Microsoft Corp. Digital Media Keyboard 1.0A */ - MAKE_VIDPID(0x045e, 0x00b4), - - /* Microsoft Microsoft Digital Media Keyboard 3000 */ - MAKE_VIDPID(0x045e, 0x0730), - - /* Microsoft Microsoft 2.4GHz Transceiver v6.0 */ - /* Microsoft Microsoft 2.4GHz Transceiver v8.0 */ - /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */ - /* Microsoft Wireless Mobile Mouse 1000 */ - /* Microsoft Wireless Desktop 3000 */ - MAKE_VIDPID(0x045e, 0x0745), - - /* Microsoft SideWinder(TM) 2.4GHz Transceiver */ - MAKE_VIDPID(0x045e, 0x0748), - - /* Microsoft Corp. Wired Keyboard 600 */ - MAKE_VIDPID(0x045e, 0x0750), - - /* Microsoft Corp. Sidewinder X4 keyboard */ - MAKE_VIDPID(0x045e, 0x0768), - - /* Microsoft Corp. Arc Touch Mouse Transceiver */ - MAKE_VIDPID(0x045e, 0x0773), - - /* Microsoft 2.4GHz Transceiver v9.0 */ - /* Microsoft Nano Transceiver v2.1 */ - /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */ - MAKE_VIDPID(0x045e, 0x07a5), - - /* Microsoft Nano Transceiver v1.0 */ - /* Microsoft Wireless Keyboard 800 */ - MAKE_VIDPID(0x045e, 0x07b2), - - /* Microsoft Nano Transceiver v2.0 */ - MAKE_VIDPID(0x045e, 0x0800), - - MAKE_VIDPID(0x046d, 0xc30a), /* Logitech, Inc. iTouch Composite keboard */ - - MAKE_VIDPID(0x04d9, 0xa0df), /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */ - - /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */ - MAKE_VIDPID(0x056a, 0x0010), /* Wacom ET-0405 Graphire */ - MAKE_VIDPID(0x056a, 0x0011), /* Wacom ET-0405A Graphire2 (4x5) */ - MAKE_VIDPID(0x056a, 0x0012), /* Wacom ET-0507A Graphire2 (5x7) */ - MAKE_VIDPID(0x056a, 0x0013), /* Wacom CTE-430 Graphire3 (4x5) */ - MAKE_VIDPID(0x056a, 0x0014), /* Wacom CTE-630 Graphire3 (6x8) */ - MAKE_VIDPID(0x056a, 0x0015), /* Wacom CTE-440 Graphire4 (4x5) */ - MAKE_VIDPID(0x056a, 0x0016), /* Wacom CTE-640 Graphire4 (6x8) */ - MAKE_VIDPID(0x056a, 0x0017), /* Wacom CTE-450 Bamboo Fun (4x5) */ - MAKE_VIDPID(0x056a, 0x0018), /* Wacom CTE-650 Bamboo Fun 6x8 */ - MAKE_VIDPID(0x056a, 0x0019), /* Wacom CTE-631 Bamboo One */ - MAKE_VIDPID(0x056a, 0x00d1), /* Wacom Bamboo Pen and Touch CTH-460 */ - MAKE_VIDPID(0x056a, 0x030e), /* Wacom Intuos Pen (S) CTL-480 */ - - MAKE_VIDPID(0x09da, 0x054f), /* A4 Tech Co., G7 750 mouse */ - MAKE_VIDPID(0x09da, 0x1410), /* A4 Tech Co., Ltd Bloody AL9 mouse */ - MAKE_VIDPID(0x09da, 0x3043), /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */ - MAKE_VIDPID(0x09da, 0x31b5), /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */ - MAKE_VIDPID(0x09da, 0x3997), /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */ - MAKE_VIDPID(0x09da, 0x3f8b), /* A4 Tech Co., Ltd Bloody V8 mouse */ - MAKE_VIDPID(0x09da, 0x51f4), /* Modecom MC-5006 Keyboard */ - MAKE_VIDPID(0x09da, 0x5589), /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */ - MAKE_VIDPID(0x09da, 0x7b22), /* A4 Tech Co., Ltd Bloody V5 */ - MAKE_VIDPID(0x09da, 0x7f2d), /* A4 Tech Co., Ltd Bloody R3 mouse */ - MAKE_VIDPID(0x09da, 0x8090), /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */ - MAKE_VIDPID(0x09da, 0x9033), /* A4 Tech Co., X7 X-705K */ - MAKE_VIDPID(0x09da, 0x9066), /* A4 Tech Co., Sharkoon Fireglider Optical */ - MAKE_VIDPID(0x09da, 0x9090), /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */ - MAKE_VIDPID(0x09da, 0x90c0), /* A4 Tech Co., Ltd X7 G800V keyboard */ - MAKE_VIDPID(0x09da, 0xf012), /* A4 Tech Co., Ltd Bloody V7 mouse */ - MAKE_VIDPID(0x09da, 0xf32a), /* A4 Tech Co., Ltd Bloody B540 keyboard */ - MAKE_VIDPID(0x09da, 0xf613), /* A4 Tech Co., Ltd Bloody V2 mouse */ - MAKE_VIDPID(0x09da, 0xf624), /* A4 Tech Co., Ltd Bloody B120 Keyboard */ - - MAKE_VIDPID(0x1b1c, 0x1b3c), /* Corsair Harpoon RGB gaming mouse */ - - MAKE_VIDPID(0x1d57, 0xad03), /* [T3] 2.4GHz and IR Air Mouse Remote Control */ - - MAKE_VIDPID(0x1e7d, 0x2e4a), /* Roccat Tyon Mouse */ - - MAKE_VIDPID(0x20a0, 0x422d), /* Winkeyless.kr Keyboards */ - - MAKE_VIDPID(0x2516, 0x001f), /* Cooler Master Storm Mizar Mouse */ - MAKE_VIDPID(0x2516, 0x0028), /* Cooler Master Storm Alcor Mouse */ - - /*****************************************************************/ - /* Additional entries */ - /*****************************************************************/ - - MAKE_VIDPID(0x04d9, 0x8008), /* OBINLB USB-HID Keyboard (Anne Pro II) */ - MAKE_VIDPID(0x04d9, 0x8009), /* OBINLB USB-HID Keyboard (Anne Pro II) */ - MAKE_VIDPID(0x04d9, 0xa292), /* OBINLB USB-HID Keyboard (Anne Pro II) */ - MAKE_VIDPID(0x04d9, 0xa293), /* OBINLB USB-HID Keyboard (Anne Pro II) */ - MAKE_VIDPID(0x1532, 0x0266), /* Razer Huntsman V2 Analog, non-functional DInput device */ - MAKE_VIDPID(0x1532, 0x0282), /* Razer Huntsman Mini Analog, non-functional DInput device */ - MAKE_VIDPID(0x26ce, 0x01a2), /* ASRock LED Controller */ - MAKE_VIDPID(0x20d6, 0x0002), /* PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only) */ - }; - - static Uint32 rog_chakram_list[] = { - MAKE_VIDPID(0x0b05, 0x1906), /* ROG Pugio II */ - MAKE_VIDPID(0x0b05, 0x1958), /* ROG Chakram Core Mouse */ - MAKE_VIDPID(0x0b05, 0x18e3), /* ROG Chakram (wired) Mouse */ - MAKE_VIDPID(0x0b05, 0x18e5), /* ROG Chakram (wireless) Mouse */ - MAKE_VIDPID(0x0b05, 0x1a18), /* ROG Chakram X (wired) Mouse */ - MAKE_VIDPID(0x0b05, 0x1a1a), /* ROG Chakram X (wireless) Mouse */ - MAKE_VIDPID(0x0b05, 0x1a1c), /* ROG Chakram X (Bluetooth) Mouse */ - }; - - unsigned int i; - Uint32 id; Uint16 vendor; Uint16 product; SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); /* Check the joystick blacklist */ - id = MAKE_VIDPID(vendor, product); - for (i = 0; i < SDL_arraysize(joystick_blacklist); ++i) { - if (id == joystick_blacklist[i]) { - return SDL_TRUE; - } + if (SDL_VIDPIDInList(vendor, product, &blacklist_devices)) { + return SDL_TRUE; } if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_ROG_CHAKRAM, SDL_FALSE)) { - for (i = 0; i < SDL_arraysize(rog_chakram_list); ++i) { - if (id == rog_chakram_list[i]) { - return SDL_TRUE; - } + if (SDL_VIDPIDInList(vendor, product, &rog_gamepad_mice)) { + return SDL_TRUE; } } @@ -3392,14 +3402,12 @@ int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorT return posted; } -void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) +static void SDL_LoadVIDPIDListFromHint(const char *hint, int *num_entries, int *max_entries, Uint32 **entries) { Uint32 entry; char *spot; char *file = NULL; - list->num_entries = 0; - if (hint && *hint == '@') { spot = file = (char *)SDL_LoadFile(hint + 1, NULL); } else { @@ -3419,17 +3427,17 @@ void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) } entry |= (Uint16)SDL_strtol(spot, &spot, 0); - if (list->num_entries == list->max_entries) { - int max_entries = list->max_entries + 16; - Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries)); - if (!entries) { + if (*num_entries == *max_entries) { + int new_max_entries = *max_entries + 16; + Uint32 *new_entries = (Uint32 *)SDL_realloc(*entries, new_max_entries * sizeof(**entries)); + if (!new_entries) { /* Out of memory, go with what we have already */ break; } - list->entries = entries; - list->max_entries = max_entries; + *entries = new_entries; + *max_entries = new_max_entries; } - list->entries[list->num_entries++] = entry; + (*entries)[(*num_entries)++] = entry; } if (file) { @@ -3437,13 +3445,100 @@ void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) } } +void SDL_LoadVIDPIDListFromHints(SDL_vidpid_list *list, const char *included_list, const char *excluded_list) +{ + /* Empty the list */ + list->num_included_entries = 0; + list->num_excluded_entries = 0; + + /* Add the initial entries */ + if (list->num_initial_entries > 0) { + if (list->num_included_entries < list->num_initial_entries) { + Uint32 *entries = (Uint32 *)SDL_malloc(list->num_initial_entries * sizeof(*entries)); + if (entries) { + SDL_memcpy(entries, list->initial_entries, list->num_initial_entries * sizeof(*entries)); + list->included_entries = entries; + list->num_included_entries = list->num_initial_entries; + list->max_included_entries = list->num_initial_entries; + } + } + } + + /* Add the included entries from the hint */ + SDL_LoadVIDPIDListFromHint(included_list, &list->num_included_entries, &list->max_included_entries, &list->included_entries); + + /* Add the excluded entries from the hint */ + SDL_LoadVIDPIDListFromHint(excluded_list, &list->num_excluded_entries, &list->max_excluded_entries, &list->excluded_entries); +} + +static void SDLCALL SDL_VIDPIDIncludedHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_vidpid_list *list = (SDL_vidpid_list *)userdata; + const char *included_list = hint; + const char *excluded_list = NULL; + + if (!list->initialized) { + return; + } + + if (list->excluded_hint_name) { + excluded_list = SDL_GetHint(list->excluded_hint_name); + } + SDL_LoadVIDPIDListFromHints(list, included_list, excluded_list); +} + +static void SDLCALL SDL_VIDPIDExcludedHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_vidpid_list *list = (SDL_vidpid_list *)userdata; + const char *included_list = NULL; + const char *excluded_list = hint; + + if (!list->initialized) { + return; + } + + if (list->included_hint_name) { + included_list = SDL_GetHint(list->included_hint_name); + } + SDL_LoadVIDPIDListFromHints(list, included_list, excluded_list); +} + +void SDL_LoadVIDPIDList(SDL_vidpid_list *list) +{ + const char *included_list = NULL; + const char *excluded_list = NULL; + + if (list->included_hint_name) { + SDL_AddHintCallback(list->included_hint_name, SDL_VIDPIDIncludedHintChanged, list); + } + + if (list->excluded_hint_name) { + SDL_AddHintCallback(list->excluded_hint_name, SDL_VIDPIDExcludedHintChanged, list); + } + + list->initialized = SDL_TRUE; + + if (list->included_hint_name) { + included_list = SDL_GetHint(list->included_hint_name); + } + if (list->excluded_hint_name) { + excluded_list = SDL_GetHint(list->excluded_hint_name); + } + SDL_LoadVIDPIDListFromHints(list, included_list, excluded_list); +} + SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list) { int i; Uint32 vidpid = MAKE_VIDPID(vendor_id, product_id); - for (i = 0; i < list->num_entries; ++i) { - if (vidpid == list->entries[i]) { + for (i = 0; i < list->num_excluded_entries; ++i) { + if (vidpid == list->excluded_entries[i]) { + return SDL_FALSE; + } + } + for (i = 0; i < list->num_included_entries; ++i) { + if (vidpid == list->included_entries[i]) { return SDL_TRUE; } } @@ -3452,8 +3547,27 @@ SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_ void SDL_FreeVIDPIDList(SDL_vidpid_list *list) { - if (list->entries) { - SDL_free(list->entries); - SDL_zerop(list); + if (list->included_hint_name) { + SDL_DelHintCallback(list->included_hint_name, SDL_VIDPIDIncludedHintChanged, list); + } + + if (list->excluded_hint_name) { + SDL_DelHintCallback(list->excluded_hint_name, SDL_VIDPIDExcludedHintChanged, list); } + + if (list->included_entries) { + SDL_free(list->included_entries); + list->included_entries = NULL; + list->num_included_entries = 0; + list->max_included_entries = 0; + } + + if (list->excluded_entries) { + SDL_free(list->excluded_entries); + list->excluded_entries = NULL; + list->num_excluded_entries = 0; + list->max_excluded_entries = 0; + } + + list->initialized = SDL_FALSE; } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 68424775b490f..0d14caec9e6b2 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -225,12 +225,24 @@ extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance typedef struct { - int num_entries; - int max_entries; - Uint32 *entries; + const char *included_hint_name; + int num_included_entries; + int max_included_entries; + Uint32 *included_entries; + + const char *excluded_hint_name; + int num_excluded_entries; + int max_excluded_entries; + Uint32 *excluded_entries; + + int num_initial_entries; + Uint32 *initial_entries; + + SDL_bool initialized; } SDL_vidpid_list; -extern void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list); +extern void SDL_LoadVIDPIDList(SDL_vidpid_list *list); +extern void SDL_LoadVIDPIDListFromHints(SDL_vidpid_list *list, const char *included_list, const char *excluded_list); extern SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list); extern void SDL_FreeVIDPIDList(SDL_vidpid_list *list); From 581d1cab257a14cd235df2192f012abb0d4e36e0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 11 Dec 2023 08:43:31 -0800 Subject: [PATCH 543/725] You should call present when using a software renderer as well. Fixes https://github.com/libsdl-org/SDL/issues/8676 --- test/testdrawchessboard.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index e4c9a882d12c6..e067c32995355 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -57,6 +57,7 @@ static void DrawChessBoard(void) } } } + SDL_RenderPresent(renderer); } static void loop(void) From c790572674b225de34fe53c0a0188dca8a05c722 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Mon, 11 Dec 2023 15:19:02 +0200 Subject: [PATCH 544/725] Use existing XUSB driver software PID 0x02a1 instead of PID 0x02fe 0x02fe is actually PID of Xbox Wireless Adapter for Windows 10 (Model 1790) and creates confusion. Here is USB descriptor dump: https://github.com/DJm00n/ControllersInfo/blob/master/xboxone/DescriptorDump_Adapter%20(Xbox%20Wireless%20Adapter%20for%20Windows).txt --- src/joystick/SDL_joystick.c | 3 --- src/joystick/hidapi/SDL_hidapijoystick.c | 2 +- src/joystick/usb_ids.h | 1 - src/joystick/windows/SDL_xinputjoystick.c | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 48ce23acc9b9c..1405800cd7636 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2615,9 +2615,6 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons } else if (vendor == 0x0001 && product == 0x0001) { type = SDL_GAMEPAD_TYPE_STANDARD; - } else if (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) { - type = SDL_GAMEPAD_TYPE_XBOXONE; - } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) { type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT; diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 037651eca4689..db17fd4096dcd 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1174,7 +1174,7 @@ static SDL_bool HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, } /* If we're looking for an XInput controller, match it against any other Xbox controller */ - if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) { + if (product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER) { if (device->type == SDL_GAMEPAD_TYPE_XBOX360 || device->type == SDL_GAMEPAD_TYPE_XBOXONE) { return SDL_TRUE; } diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index a582512ad87d7..75582605d100b 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -143,7 +143,6 @@ #define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002 #define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6 #define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */ -#define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */ #define USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD 0x11ff /* USB usage pages */ diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 7fbf1b6ffb8b7..f1990da9377af 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -301,7 +301,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC #ifdef SDL_JOYSTICK_HIDAPI /* Since we're guessing about the VID/PID, use a hard-coded VID/PID to represent XInput */ - if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER, version, pNewJoystick->joystickname)) { + if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX360_XUSB_CONTROLLER, version, pNewJoystick->joystickname)) { /* The HIDAPI driver is taking care of this device */ SDL_free(pNewJoystick); return; From 835c733f4d2199b4b9f195f0d1c4b9286726e071 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 12 Dec 2023 12:58:05 -0500 Subject: [PATCH 545/725] video: Only sync when programmatically entering/exiting fullscreen Otherwise, the sync function can be recursively entered when the fullscreen state is updated by a window manager event. --- src/video/SDL_video.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 03ad6ffe09291..ecf909568acd0 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1754,7 +1754,6 @@ int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen, SDL_bool c done: window->last_fullscreen_exclusive_display = display && (window->flags & SDL_WINDOW_FULLSCREEN) && window->fullscreen_exclusive ? display->id : 0; - SDL_SyncIfRequired(window); return 0; error: @@ -2974,6 +2973,10 @@ int SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) SDL_zero(window->current_fullscreen_mode); } + if (ret == 0) { + SDL_SyncIfRequired(window); + } + return ret; } From bddbd1e31748e695a4010001cb91dbeac683c89b Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 12 Dec 2023 14:31:41 -0500 Subject: [PATCH 546/725] cocoa: Check the resizable flag along with zoomed status when resizing isZoomed always returns true if the window is not resizable, so the resizable flag needs to be checked as well. --- src/video/cocoa/SDL_cocoawindow.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 7c49a69de0f2d..9115e65fd7b02 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2209,7 +2209,8 @@ void Cocoa_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) Cocoa_SyncWindow(_this, window); } - if (!Cocoa_IsZoomed(window)) { + /* isZoomed always returns true if the window is not resizable */ + if (!Cocoa_IsZoomed(window) || !(window->flags & SDL_WINDOW_RESIZABLE)) { if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES]; ScheduleContextUpdates(windata); From 0baee3e6768c8e4a227bb4eacee5a8bc70afc2dd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 12 Dec 2023 12:25:51 -0800 Subject: [PATCH 547/725] Reversed test to be easier to read, more efficient, and match other code --- src/video/cocoa/SDL_cocoawindow.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 9115e65fd7b02..a2482cf8a3808 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2210,7 +2210,7 @@ void Cocoa_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) } /* isZoomed always returns true if the window is not resizable */ - if (!Cocoa_IsZoomed(window) || !(window->flags & SDL_WINDOW_RESIZABLE)) { + if (!(window->flags & SDL_WINDOW_RESIZABLE) || !Cocoa_IsZoomed(window)) { if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES]; ScheduleContextUpdates(windata); From c1a7d0f96ed4123c63600b1f97cb4c51eb9bdb62 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:04:01 +0200 Subject: [PATCH 548/725] Add steam deck detection and HIDAPI driver scaffold. --- include/SDL3/SDL_hints.h | 11 ++ src/joystick/SDL_joystick.c | 6 + src/joystick/SDL_joystick_c.h | 3 + src/joystick/controller_list.h | 1 + src/joystick/controller_type.h | 1 + src/joystick/hidapi/SDL_hidapi_steamdeck.c | 156 +++++++++++++++++++++ src/joystick/hidapi/SDL_hidapijoystick.c | 3 + src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 + 8 files changed, 183 insertions(+) create mode 100644 src/joystick/hidapi/SDL_hidapi_steamdeck.c diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 10c24e1151bff..baf43e54a78df 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -943,6 +943,17 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" +/** + * A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" + /** * A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 1405800cd7636..28fcdda3af766 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2912,6 +2912,12 @@ SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2; } +SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id) +{ + EControllerType eType = GuessControllerType(vendor_id, product_id); + return eType == k_eControllerType_SteamDeck; +} + SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) { return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE; diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 0d14caec9e6b2..53360bb5d13aa 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -126,6 +126,9 @@ extern SDL_bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 pr /* Function to return whether a joystick is a Steam Controller */ extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id); +/* Function to return whether a joystick is a Steam Deck */ +extern SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id); + /* Function to return whether a joystick guid comes from the XInput driver */ extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid); diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index d8342f680907f..38f638b2a3ce4 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -597,4 +597,5 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller { MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB) { MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB) + { MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamDeck, NULL }, // Valve Steam Deck Builtin Controller }; diff --git a/src/joystick/controller_type.h b/src/joystick/controller_type.h index cf89239562545..78c595586301f 100644 --- a/src/joystick/controller_type.h +++ b/src/joystick/controller_type.h @@ -37,6 +37,7 @@ typedef enum k_eControllerType_UnknownSteamController = 1, k_eControllerType_SteamController = 2, k_eControllerType_SteamControllerV2 = 3, + k_eControllerType_SteamDeck = 4, // Other Controllers k_eControllerType_UnknownNonSteamController = 30, diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c new file mode 100644 index 0000000000000..95f8ea9a918aa --- /dev/null +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -0,0 +1,156 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2023 Max Maisel + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_JOYSTICK_HIDAPI + +#include "../SDL_sysjoystick.h" +#include "SDL_hidapijoystick_c.h" + +#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK + +/*****************************************************************************************************/ + +#include + +/*****************************************************************************************************/ + +static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); +} + +static void HIDAPI_DriverSteamDeck_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); +} + +static SDL_bool HIDAPI_DriverSteamDeck_IsEnabled(void) +{ + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT)); +} + +static SDL_bool HIDAPI_DriverSteamDeck_IsSupportedDevice( + SDL_HIDAPI_Device *device, + const char *name, + SDL_GamepadType type, + Uint16 vendor_id, + Uint16 product_id, + Uint16 version, + int interface_number, + int interface_class, + int interface_subclass, + int interface_protocol) +{ + return SDL_IsJoystickSteamDeck(vendor_id, product_id); +} + +static SDL_bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device) +{ + return SDL_FALSE; +} + +static int HIDAPI_DriverSteamDeck_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void HIDAPI_DriverSteamDeck_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + +static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) +{ + return SDL_FALSE; +} + +static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return SDL_FALSE; +} + +static int HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + /* You should use the full Steam Input API for rumble support */ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) +{ + return SDL_Unsupported(); +} + +static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return 0; +} + +static int HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) +{ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) +{ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled) +{ + // On steam deck, sensors are enabled by default. Nothing to do here. + return 0; +} + +static void HIDAPI_DriverSteamDeck_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + // Lizard mode id automatically re-enabled by watchdog. Nothing to do here. +} + +static void HIDAPI_DriverSteamDeck_FreeDevice(SDL_HIDAPI_Device *device) +{ +} + +SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck = { + SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, + SDL_TRUE, + HIDAPI_DriverSteamDeck_RegisterHints, + HIDAPI_DriverSteamDeck_UnregisterHints, + HIDAPI_DriverSteamDeck_IsEnabled, + HIDAPI_DriverSteamDeck_IsSupportedDevice, + HIDAPI_DriverSteamDeck_InitDevice, + HIDAPI_DriverSteamDeck_GetDevicePlayerIndex, + HIDAPI_DriverSteamDeck_SetDevicePlayerIndex, + HIDAPI_DriverSteamDeck_UpdateDevice, + HIDAPI_DriverSteamDeck_OpenJoystick, + HIDAPI_DriverSteamDeck_RumbleJoystick, + HIDAPI_DriverSteamDeck_RumbleJoystickTriggers, + HIDAPI_DriverSteamDeck_GetJoystickCapabilities, + HIDAPI_DriverSteamDeck_SetJoystickLED, + HIDAPI_DriverSteamDeck_SendJoystickEffect, + HIDAPI_DriverSteamDeck_SetSensorsEnabled, + HIDAPI_DriverSteamDeck_CloseJoystick, + HIDAPI_DriverSteamDeck_FreeDevice, +}; + +#endif /* SDL_JOYSTICK_HIDAPI_STEAMDECK */ + +#endif /* SDL_JOYSTICK_HIDAPI */ diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index db17fd4096dcd..5152828f8d0d5 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -66,6 +66,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = { #ifdef SDL_JOYSTICK_HIDAPI_STEAM &SDL_HIDAPI_DriverSteam, #endif +#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK + &SDL_HIDAPI_DriverSteamDeck, +#endif #ifdef SDL_JOYSTICK_HIDAPI_SWITCH &SDL_HIDAPI_DriverNintendoClassic, &SDL_HIDAPI_DriverJoyCons, diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 04961b2ecd4f3..acca9a5c85bad 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -33,6 +33,7 @@ #define SDL_JOYSTICK_HIDAPI_PS5 #define SDL_JOYSTICK_HIDAPI_STADIA #define SDL_JOYSTICK_HIDAPI_STEAM /* Simple support for BLE Steam Controller, hint is disabled by default */ +#define SDL_JOYSTICK_HIDAPI_STEAMDECK #define SDL_JOYSTICK_HIDAPI_SWITCH #define SDL_JOYSTICK_HIDAPI_WII #define SDL_JOYSTICK_HIDAPI_XBOX360 @@ -126,6 +127,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam; +extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360; From 94f621e030cd9af56ec63dc5ed7c3c1d883019e8 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:12:33 +0200 Subject: [PATCH 549/725] Implement steam deck HIDAPI initialization. --- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 45 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index 95f8ea9a918aa..02566e94b0f7b 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -31,6 +31,11 @@ #include +typedef struct +{ + Uint32 update_rate_us; +} SDL_DriverSteamDeck_Context; + /*****************************************************************************************************/ static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata) @@ -66,7 +71,31 @@ static SDL_bool HIDAPI_DriverSteamDeck_IsSupportedDevice( static SDL_bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device) { - return SDL_FALSE; + int size; + Uint8 data[64]; + SDL_DriverSteamDeck_Context *ctx; + + ctx = (SDL_DriverSteamDeck_Context *)SDL_calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + + // Always 1kHz according to USB descriptor + ctx->update_rate_us = 1000; + + device->context = ctx; + + // Read a report to see if this is the correct endpoint. + // Mouse, Keyboard and Controller have the same VID/PID but + // only the controller hidraw device receives hid reports. + size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); + if (size == 0) + return SDL_FALSE; + + HIDAPI_SetDeviceName(device, "Steam Deck"); + + return HIDAPI_JoystickConnected(device, NULL); } static int HIDAPI_DriverSteamDeck_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) @@ -85,7 +114,19 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_FALSE; + SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context; + float update_rate_in_hz = 1.0f / (float)(ctx->update_rate_us) * 1.0e6f; + + SDL_AssertJoysticksLocked(); + + // Initialize the joystick capabilities + joystick->nbuttons = 20; + joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz); + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz); + + return SDL_TRUE; } static int HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) From 6dd68273438e979590e8211d8a85cd785c9d4bd3 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:18:12 +0200 Subject: [PATCH 550/725] Translate steam deck HID reports to SDL events. --- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 121 +++++++++++++++++- .../hidapi/steam/controller_constants.h | 31 +++++ .../hidapi/steam/controller_structs.h | 62 +++++++++ 3 files changed, 213 insertions(+), 1 deletion(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index 02566e94b0f7b..a8bce66bca7b0 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -31,9 +31,21 @@ #include +#define bool SDL_bool +#define true SDL_TRUE +#define false SDL_FALSE + +typedef uint32_t uint32; +typedef uint64_t uint64; + +#include "steam/controller_constants.h" +#include "steam/controller_structs.h" + typedef struct { Uint32 update_rate_us; + Uint32 sensor_timestamp_us; + Uint64 last_button_state; } SDL_DriverSteamDeck_Context; /*****************************************************************************************************/ @@ -109,7 +121,114 @@ static void HIDAPI_DriverSteamDeck_SetDevicePlayerIndex(SDL_HIDAPI_Device *devic static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) { - return SDL_FALSE; + SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context; + SDL_Joystick *joystick = NULL; + int r; + uint8_t data[64]; + float values[3]; + ValveInReport_t *pInReport = (ValveInReport_t *)data; + + if (device->num_joysticks > 0) { + joystick = SDL_GetJoystickFromInstanceID(device->joysticks[0]); + if (joystick == NULL) { + return SDL_FALSE; + } + } else { + return SDL_FALSE; + } + + SDL_memset(data, 0, sizeof(data)); + r = SDL_hid_read(device->dev, data, sizeof(data)); + if (r == 0) { + return SDL_FALSE; + } else if (r <= 0) { + /* Failed to read from controller */ + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + return SDL_FALSE; + } + + if (!(r == 64 && pInReport->header.unReportVersion == k_ValveInReportMsgVersion && pInReport->header.ucType == ID_CONTROLLER_DECK_STATE && pInReport->header.ucLength == 64)) { + return SDL_FALSE; + } + + Uint64 timestamp = SDL_GetTicksNS(); + + if (pInReport->payload.deckState.ulButtons != ctx->last_button_state) { + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_A) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_B) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_X) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_Y) ? SDL_PRESSED : SDL_RELEASED); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_LT) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_RT) ? SDL_PRESSED : SDL_RELEASED); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_SELECT) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_START) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MODE) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_BASE) ? SDL_PRESSED : SDL_RELEASED); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STICKL) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STICKR) ? SDL_PRESSED : SDL_RELEASED); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_PADDLE1) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_PADDLE2) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_PADDLE3) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_PADDLE4) ? SDL_PRESSED : SDL_RELEASED); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_DOWN) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_LEFT) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_RIGHT) ? SDL_PRESSED : SDL_RELEASED); + ctx->last_button_state = pInReport->payload.deckState.ulButtons; + } + + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, + (int)pInReport->payload.deckState.sLeftTrigger * 2 - 32768); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, + (int)pInReport->payload.deckState.sRightTrigger * 2 - 32768); + + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, + pInReport->payload.deckState.sLeftStickX); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, + -pInReport->payload.deckState.sLeftStickY); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, + pInReport->payload.deckState.sRightStickX); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, + -pInReport->payload.deckState.sRightStickY); + + ctx->sensor_timestamp_us += ctx->update_rate_us; + + values[0] = (pInReport->payload.deckState.sGyroX / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); + values[1] = (pInReport->payload.deckState.sGyroZ / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); + values[2] = (-pInReport->payload.deckState.sGyroY / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f)); + SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, ctx->sensor_timestamp_us, values, 3); + + values[0] = (pInReport->payload.deckState.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; + values[1] = (pInReport->payload.deckState.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; + values[2] = (-pInReport->payload.deckState.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; + SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp_us, values, 3); + + return SDL_TRUE; } static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) diff --git a/src/joystick/hidapi/steam/controller_constants.h b/src/joystick/hidapi/steam/controller_constants.h index d0d568851662f..42c84f247dd53 100644 --- a/src/joystick/hidapi/steam/controller_constants.h +++ b/src/joystick/hidapi/steam/controller_constants.h @@ -315,6 +315,37 @@ enum GamepadButtons GAMEPAD_BTN_COUNT }; +typedef enum +{ + // Low word button bits + STEAMDECK_LBUTTON_RT2 = (1 << 0), + STEAMDECK_LBUTTON_LT2 = (1 << 1), + STEAMDECK_LBUTTON_RT = (1 << 2), + STEAMDECK_LBUTTON_LT = (1 << 3), + STEAMDECK_LBUTTON_Y = (1 << 4), + STEAMDECK_LBUTTON_B = (1 << 5), + STEAMDECK_LBUTTON_X = (1 << 6), + STEAMDECK_LBUTTON_A = (1 << 7), + STEAMDECK_LBUTTON_DPAD_UP = (1 << 8), + STEAMDECK_LBUTTON_DPAD_RIGHT = (1 << 9), + STEAMDECK_LBUTTON_DPAD_LEFT = (1 << 10), + STEAMDECK_LBUTTON_DPAD_DOWN = (1 << 11), + STEAMDECK_LBUTTON_SELECT = (1 << 12), + STEAMDECK_LBUTTON_MODE = (1 << 13), + STEAMDECK_LBUTTON_START = (1 << 14), + STEAMDECK_LBUTTON_PADDLE3 = (1 << 15), + STEAMDECK_LBUTTON_PADDLE4 = (1 << 16), + STEAMDECK_LBUTTON_PADL = (1 << 17), + STEAMDECK_LBUTTON_PADR = (1 << 18), + STEAMDECK_LBUTTON_STICKL = (1 << 22), + STEAMDECK_LBUTTON_STICKR = (1 << 26), + + // High word button bits + STEAMDECK_HBUTTON_PADDLE1 = (1 << 9), + STEAMDECK_HBUTTON_PADDLE2 = (1 << 10), + STEAMDECK_HBUTTON_BASE = (1 << 18) +} DeckButtons; + // Mode adjust enum ModeAdjustModes { diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h index e60428e26bf7f..6e86426d7e73f 100644 --- a/src/joystick/hidapi/steam/controller_structs.h +++ b/src/joystick/hidapi/steam/controller_structs.h @@ -77,6 +77,7 @@ typedef enum ID_CONTROLLER_DEBUG2 = 5, ID_CONTROLLER_SECONDARY_STATE = 6, ID_CONTROLLER_BLE_STATE = 7, + ID_CONTROLLER_DECK_STATE = 9, ID_CONTROLLER_MSG_COUNT } ValveInReportMessageIDs; @@ -258,6 +259,66 @@ typedef struct unsigned char ucBatteryLevel; } SteamControllerStatusEvent_t; +// Deck State payload +typedef struct +{ + // If packet num matches that on your prior call, then the controller + // state hasn't been changed since your last call and there is no need to + // process it + uint32 unPacketNum; + + // Button bitmask and trigger data. + union + { + uint64 ulButtons; + struct + { + uint32 ulButtonsL; + uint32 ulButtonsH; + }; + }; + + // Left pad coordinates + short sLeftPadX; + short sLeftPadY; + + // Right pad coordinates + short sRightPadX; + short sRightPadY; + + // Accelerometer values + short sAccelX; + short sAccelY; + short sAccelZ; + + // Gyroscope values + short sGyroX; + short sGyroY; + short sGyroZ; + + // Gyro quaternions + short sGyroQuatW; + short sGyroQuatX; + short sGyroQuatY; + short sGyroQuatZ; + + // Uncalibrated trigger values + short sLeftTrigger; + short sRightTrigger; + + // Left stick values + short sLeftStickX; + short sLeftStickY; + + // Right stick values + short sRightStickX; + short sRightStickY; + + // Touchpad pressures + short sLeftPadPressure; + short sRightPadPressure; +} SteamDeckStatePacket_t; + typedef struct { ValveInReportHeader_t header; @@ -271,6 +332,7 @@ typedef struct ValveControllerRawTrackpadImage_t rawPadImage; SteamControllerWirelessEvent_t wirelessEvent; SteamControllerStatusEvent_t statusEvent; + SteamDeckStatePacket_t deckState; } payload; } ValveInReport_t; From 67d44c1017ad3eb883b29083681c441bbc6f1bd0 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:20:24 +0200 Subject: [PATCH 551/725] Disable lizard mode while steam deck HID device is opened. --- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 74 +++++++++++++++++++ .../hidapi/steam/controller_constants.h | 9 +++ .../hidapi/steam/controller_structs.h | 14 ++++ 3 files changed, 97 insertions(+) diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index a8bce66bca7b0..a95483bd021b9 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -46,8 +46,73 @@ typedef struct Uint32 update_rate_us; Uint32 sensor_timestamp_us; Uint64 last_button_state; + Uint8 watchdog_counter; } SDL_DriverSteamDeck_Context; +static SDL_bool DisableDeckLizardMode(SDL_hid_device *dev) +{ + int rc; + Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; + FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); + + msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS; + + rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); + if (rc != sizeof(buffer)) + return SDL_FALSE; + + msg->header.type = ID_SET_SETTINGS_VALUES; + msg->header.length = 5 * sizeof(WriteDeckRegister); + msg->payload.wrDeckRegister.reg[0].addr = SETTING_DECK_RPAD_MARGIN; // disable margin + msg->payload.wrDeckRegister.reg[0].val = 0; + msg->payload.wrDeckRegister.reg[1].addr = SETTING_DECK_LPAD_MODE; // disable mouse + msg->payload.wrDeckRegister.reg[1].val = 7; + msg->payload.wrDeckRegister.reg[2].addr = SETTING_DECK_RPAD_MODE; // disable mouse + msg->payload.wrDeckRegister.reg[2].val = 7; + msg->payload.wrDeckRegister.reg[3].addr = SETTING_DECK_LPAD_CLICK_PRESSURE; // disable clicky pad + msg->payload.wrDeckRegister.reg[3].val = 0xFFFF; + msg->payload.wrDeckRegister.reg[4].addr = SETTING_DECK_RPAD_CLICK_PRESSURE; // disable clicky pad + msg->payload.wrDeckRegister.reg[4].val = 0xFFFF; + + rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); + if (rc != sizeof(buffer)) + return SDL_FALSE; + + // There may be a lingering report read back after changing settings. + // Discard it. + SDL_hid_get_feature_report(dev, buffer, sizeof(buffer)); + + return SDL_TRUE; +} + +static SDL_bool FeedDeckLizardWatchdog(SDL_hid_device *dev) +{ + int rc; + Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; + FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); + + msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS; + + rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); + if (rc != sizeof(buffer)) + return SDL_FALSE; + + msg->header.type = ID_SET_SETTINGS_VALUES; + msg->header.length = 1 * sizeof(WriteDeckRegister); + msg->payload.wrDeckRegister.reg[0].addr = SETTING_DECK_RPAD_MODE; // disable mouse + msg->payload.wrDeckRegister.reg[0].val = 7; + + rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); + if (rc != sizeof(buffer)) + return SDL_FALSE; + + // There may be a lingering report read back after changing settings. + // Discard it. + SDL_hid_get_feature_report(dev, buffer, sizeof(buffer)); + + return SDL_TRUE; +} + /*****************************************************************************************************/ static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata) @@ -105,6 +170,9 @@ static SDL_bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device) if (size == 0) return SDL_FALSE; + if (!DisableDeckLizardMode(device->dev)) + return SDL_FALSE; + HIDAPI_SetDeviceName(device, "Steam Deck"); return HIDAPI_JoystickConnected(device, NULL); @@ -137,6 +205,12 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) return SDL_FALSE; } + if (ctx->watchdog_counter++ > 200) { + ctx->watchdog_counter = 0; + if (!FeedDeckLizardWatchdog(device->dev)) + return SDL_FALSE; + } + SDL_memset(data, 0, sizeof(data)); r = SDL_hid_read(device->dev, data, sizeof(data)); if (r == 0) { diff --git a/src/joystick/hidapi/steam/controller_constants.h b/src/joystick/hidapi/steam/controller_constants.h index 42c84f247dd53..dc0c3f220a517 100644 --- a/src/joystick/hidapi/steam/controller_constants.h +++ b/src/joystick/hidapi/steam/controller_constants.h @@ -467,6 +467,15 @@ typedef enum SETTING_ALL=0xFF } ControllerSettings; +typedef enum +{ + SETTING_DECK_LPAD_MODE = 0x07, + SETTING_DECK_RPAD_MODE = 0x08, + SETTING_DECK_RPAD_MARGIN = 0x18, + SETTING_DECK_LPAD_CLICK_PRESSURE = 0x34, + SETTING_DECK_RPAD_CLICK_PRESSURE = 0x35 +} DeckSettings; + typedef enum { SETTING_DEFAULT, diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h index 6e86426d7e73f..d3de7338fc5e8 100644 --- a/src/joystick/hidapi/steam/controller_structs.h +++ b/src/joystick/hidapi/steam/controller_structs.h @@ -45,6 +45,19 @@ typedef struct ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ]; } MsgGetAttributes; +// 16bit Steam Deck register with address +typedef struct +{ + uint8_t addr; + uint16_t val; +} WriteDeckRegister; + +// Generic Steam Deck write register message +typedef struct +{ + WriteDeckRegister reg[ (HID_FEATURE_REPORT_BYTES - sizeof ( FeatureReportHeader ) ) / sizeof (WriteDeckRegister ) ]; +} MsgWriteDeckRegister; + // This is the only message struct that application code should use to interact with feature request messages. Any new // messages should be added to the union. The structures defined here should correspond to the ones defined in @@ -56,6 +69,7 @@ typedef struct union { MsgGetAttributes getAttributes; + MsgWriteDeckRegister wrDeckRegister; } payload; } FeatureReportMsg; From 5a21febecbec3e5f2d110d700fd4ffc58d6603e6 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:21:08 +0200 Subject: [PATCH 552/725] Add new steam deck HIDAPI controller to controller database. --- src/joystick/SDL_gamepad_db.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 6496e03304237..75bc7ead9d6bc 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -727,6 +727,7 @@ static const char *s_GamepadMappings[] = { "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,", + "03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b17,paddle2:b16,paddle3:b19,paddle4:b18,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b6,leftstick:b13,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:+a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", From f3048e3cd2d791fac1cb1e6a88c82d8a4df001e2 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Fri, 8 Sep 2023 17:09:36 +0200 Subject: [PATCH 553/725] Add new file to vcxproj files. --- VisualC-GDK/SDL/SDL.vcxproj | 1 + VisualC-GDK/SDL/SDL.vcxproj.filters | 3 +++ VisualC/SDL/SDL.vcxproj | 1 + VisualC/SDL/SDL.vcxproj.filters | 3 +++ 4 files changed, 8 insertions(+) diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 2c5b186f8965f..40bf69560b16e 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -626,6 +626,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index c1f85c5a83df3..cd21c505f0d96 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -1102,6 +1102,9 @@ joystick\hidapi + + joystick\hidapi + joystick\hidapi diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index e547e4256ba94..b89ae43ba0099 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -529,6 +529,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 5f1d2836f06de..79a582b8e1a57 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1083,6 +1083,9 @@ joystick\hidapi + + joystick\hidapi + joystick\hidapi From 69288038ed0085df09d43e76641451b9050c9329 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Tue, 26 Sep 2023 18:31:12 +0200 Subject: [PATCH 554/725] Refactor away some additional integer types. --- src/joystick/hidapi/SDL_hidapi_steam.c | 11 +++-------- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 9 --------- src/joystick/hidapi/steam/controller_structs.h | 16 ++++++++-------- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index aa6f18fff2dae..cd00e27fcd280 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -29,29 +29,24 @@ /*****************************************************************************************************/ -#include - #define bool SDL_bool #define true SDL_TRUE #define false SDL_FALSE -typedef uint32_t uint32; -typedef uint64_t uint64; - #include "steam/controller_constants.h" #include "steam/controller_structs.h" typedef struct SteamControllerStateInternal_t { // Controller Type for this Controller State - uint32 eControllerType; + Uint32 eControllerType; // If packet num matches that on your prior call, then the controller state hasn't been changed since // your last call and there is no need to process it - uint32 unPacketNum; + Uint32 unPacketNum; // bit flags for each of the buttons - uint64 ulButtons; + Uint64 ulButtons; // Left pad coordinates short sLeftPadX; diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index a95483bd021b9..f04cfc8952b61 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -29,15 +29,6 @@ /*****************************************************************************************************/ -#include - -#define bool SDL_bool -#define true SDL_TRUE -#define false SDL_FALSE - -typedef uint32_t uint32; -typedef uint64_t uint64; - #include "steam/controller_constants.h" #include "steam/controller_structs.h" diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h index d3de7338fc5e8..d7904bee658f1 100644 --- a/src/joystick/hidapi/steam/controller_structs.h +++ b/src/joystick/hidapi/steam/controller_structs.h @@ -109,12 +109,12 @@ typedef struct { // If packet num matches that on your prior call, then the controller state hasn't been changed since // your last call and there is no need to process it - uint32 unPacketNum; + Uint32 unPacketNum; // Button bitmask and trigger data. union { - uint64 ulButtons; + Uint64 ulButtons; struct { unsigned char _pad0[3]; @@ -158,12 +158,12 @@ typedef struct { // If packet num matches that on your prior call, then the controller state hasn't been changed since // your last call and there is no need to process it - uint32 unPacketNum; + Uint32 unPacketNum; // Button bitmask and trigger data. union { - uint64 ulButtons; + Uint64 ulButtons; struct { unsigned char _pad0[3]; @@ -279,16 +279,16 @@ typedef struct // If packet num matches that on your prior call, then the controller // state hasn't been changed since your last call and there is no need to // process it - uint32 unPacketNum; + Uint32 unPacketNum; // Button bitmask and trigger data. union { - uint64 ulButtons; + Uint64 ulButtons; struct { - uint32 ulButtonsL; - uint32 ulButtonsH; + Uint32 ulButtonsL; + Uint32 ulButtonsH; }; }; From b0e7b7db6f94e6ae75ba381b0298f5904393f6b2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 12 Dec 2023 23:17:41 -0800 Subject: [PATCH 555/725] Don't unload graphics libraries until after the window has been destroyed. This fixes creating a window after the first window has been destroyed on Android. The graphics library had been unloaded, so eglDestroySurface() wasn't called, leaving a surface attached to the window, which would prevent attaching new EGL surfaces to the window (eglCreateWindowSurface() would fail with BAD_ALLOC) --- src/video/SDL_video.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index ecf909568acd0..6e4d45f32b133 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3621,12 +3621,18 @@ void SDL_DestroyWindow(SDL_Window *window) } } - /* make no context current if this is the current context window. */ + /* Make no context current if this is the current context window */ if (window->flags & SDL_WINDOW_OPENGL) { if (_this->current_glwin == window) { SDL_GL_MakeCurrent(window, NULL); } } + + if (_this->DestroyWindow) { + _this->DestroyWindow(_this, window); + } + + /* Unload the graphics libraries after the window is destroyed, which may clean up EGL surfaces */ if (window->flags & SDL_WINDOW_OPENGL) { SDL_GL_UnloadLibrary(); } @@ -3634,10 +3640,6 @@ void SDL_DestroyWindow(SDL_Window *window) SDL_Vulkan_UnloadLibrary(); } - if (_this->DestroyWindow) { - _this->DestroyWindow(_this, window); - } - if (_this->grabbed_window == window) { _this->grabbed_window = NULL; /* ungrabbing input. */ } From e6d8ef1a5bfbed1689135ee0ce592bca6003e141 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 13 Dec 2023 09:45:39 -0800 Subject: [PATCH 556/725] Revert "Back out Steam virtual gamepad changes" This reverts commit 34eb24ebc4f140b91aecc38701ee549c377f9eca. --- src/joystick/linux/SDL_sysjoystick.c | 131 +++++++++++++++++++++++---- 1 file changed, 114 insertions(+), 17 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 9b8a85f26678f..965e5f415af0a 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -156,6 +156,7 @@ typedef struct SDL_joylist_item char *name; /* "SideWinder 3D Pro" or whatever */ SDL_JoystickGUID guid; dev_t devnum; + int steam_virtual_gamepad_slot; struct joystick_hwdata *hwdata; struct SDL_joylist_item *next; @@ -219,6 +220,19 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, } #endif /* SDL_JOYSTICK_HIDAPI */ +static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot) +{ + const char *digits = SDL_strstr(name, "pad "); + if (digits) { + digits += 4; + if (SDL_isdigit(*digits)) { + *slot = SDL_atoi(digits); + return SDL_TRUE; + } + } + return SDL_FALSE; +} + static int GuessDeviceClass(int fd) { unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 }; @@ -259,7 +273,7 @@ static int GuessIsSensor(int fd) return 0; } -static int IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid) +static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid) { struct input_id inpid; char *name; @@ -312,6 +326,8 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick return 0; } *name_return = name; + *vendor_return = inpid.vendor; + *product_return = inpid.product; return 1; } @@ -389,6 +405,7 @@ static void MaybeAddDevice(const char *path) struct stat sb; int fd = -1; char *name = NULL; + Uint16 vendor, product; SDL_JoystickGUID guid; SDL_joylist_item *item; SDL_sensorlist_item *item_sensor; @@ -424,7 +441,7 @@ static void MaybeAddDevice(const char *path) SDL_Log("Checking %s\n", path); #endif - if (IsJoystick(path, fd, &name, &guid)) { + if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) { #ifdef DEBUG_INPUT_EVENTS SDL_Log("found joystick: %s\n", path); #endif @@ -436,10 +453,16 @@ static void MaybeAddDevice(const char *path) } item->devnum = sb.st_rdev; + item->steam_virtual_gamepad_slot = -1; item->path = SDL_strdup(path); item->name = name; item->guid = guid; + if (vendor == USB_VENDOR_VALVE && + product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot); + } + if ((!item->path) || (!item->name)) { FreeJoylistItem(item); goto done; @@ -832,6 +855,91 @@ static int SDLCALL sort_entries(const void *_a, const void *_b) return numA - numB; } +typedef struct +{ + char *path; + int slot; +} VirtualGamepadEntry; + +static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b) +{ + const VirtualGamepadEntry *a = (const VirtualGamepadEntry *)_a; + const VirtualGamepadEntry *b = (const VirtualGamepadEntry *)_b; + return a->slot - b->slot; +} + +static void LINUX_ScanSteamVirtualGamepads(void) +{ + int i, count; + int fd; + struct dirent **entries = NULL; + char path[PATH_MAX]; + char name[128]; + struct input_id inpid; + int num_virtual_gamepads = 0; + int virtual_gamepad_slot; + VirtualGamepadEntry *virtual_gamepads = NULL; + + count = scandir("/dev/input", &entries, filter_entries, NULL); + for (i = 0; i < count; ++i) { + (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); + + fd = open(path, O_RDONLY | O_CLOEXEC, 0); + if (fd >= 0) { + if (ioctl(fd, EVIOCGID, &inpid) == 0 && + inpid.vendor == USB_VENDOR_VALVE && + inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && + ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && + GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) { + VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); + if (new_virtual_gamepads) { + VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; + entry->path = SDL_strdup(path); + entry->slot = virtual_gamepad_slot; + if (entry->path) { + virtual_gamepads = new_virtual_gamepads; + ++num_virtual_gamepads; + } else { + SDL_free(entry->path); + SDL_free(new_virtual_gamepads); + } + } + } + close(fd); + } + free(entries[i]); /* This should NOT be SDL_free() */ + } + free(entries); /* This should NOT be SDL_free() */ + + if (num_virtual_gamepads > 1) { + SDL_qsort(virtual_gamepads, num_virtual_gamepads, sizeof(*virtual_gamepads), sort_virtual_gamepads); + } + for (i = 0; i < num_virtual_gamepads; ++i) { + MaybeAddDevice(virtual_gamepads[i].path); + SDL_free(virtual_gamepads[i].path); + } + SDL_free(virtual_gamepads); +} + +static void LINUX_ScanInputDevices(void) +{ + int i, count; + struct dirent **entries = NULL; + char path[PATH_MAX]; + + count = scandir("/dev/input", &entries, filter_entries, NULL); + if (count > 1) { + SDL_qsort(entries, count, sizeof(*entries), sort_entries); + } + for (i = 0; i < count; ++i) { + (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); + MaybeAddDevice(path); + + free(entries[i]); /* This should NOT be SDL_free() */ + } + free(entries); /* This should NOT be SDL_free() */ +} + static void LINUX_FallbackJoystickDetect(void) { const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */ @@ -842,21 +950,10 @@ static void LINUX_FallbackJoystickDetect(void) /* Opening input devices can generate synchronous device I/O, so avoid it if we can */ if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) { - int i, count; - struct dirent **entries = NULL; - char path[PATH_MAX]; + /* Look for Steam virtual gamepads first, and sort by Steam controller slot */ + LINUX_ScanSteamVirtualGamepads(); - count = scandir("/dev/input", &entries, filter_entries, NULL); - if (count > 1) { - SDL_qsort(entries, count, sizeof(*entries), sort_entries); - } - for (i = 0; i < count; ++i) { - (void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name); - MaybeAddDevice(path); - - free(entries[i]); /* This should NOT be SDL_free() */ - } - free(entries); /* This should NOT be SDL_free() */ + LINUX_ScanInputDevices(); last_input_dir_mtime = sb.st_mtime; } @@ -1021,7 +1118,7 @@ static const char *LINUX_JoystickGetDevicePath(int device_index) static int LINUX_JoystickGetDevicePlayerIndex(int device_index) { - return -1; + return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot; } static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) From 58a5f5cbe8893851e5f0bc3a12a39cb54f1f33f0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 13 Dec 2023 10:13:17 -0800 Subject: [PATCH 557/725] Allow sendCommand() to be overridden by derived classes In this case it's used to prevent switching to windowed mode when destroying and recreating the main window --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index ba773765e1aec..9d015a40b13e4 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -810,11 +810,10 @@ public static void handleNativeState() { } // Messages from the SDLMain thread - static final int COMMAND_CHANGE_TITLE = 1; - static final int COMMAND_CHANGE_WINDOW_STYLE = 2; - static final int COMMAND_TEXTEDIT_HIDE = 3; - static final int COMMAND_SET_KEEP_SCREEN_ON = 5; - + protected static final int COMMAND_CHANGE_TITLE = 1; + protected static final int COMMAND_CHANGE_WINDOW_STYLE = 2; + protected static final int COMMAND_TEXTEDIT_HIDE = 3; + protected static final int COMMAND_SET_KEEP_SCREEN_ON = 5; protected static final int COMMAND_USER = 0x8000; protected static boolean mFullscreenModeActive; @@ -922,7 +921,7 @@ public void handleMessage(Message msg) { Handler commandHandler = new SDLCommandHandler(); // Send a message from the SDLMain thread - boolean sendCommand(int command, Object data) { + protected boolean sendCommand(int command, Object data) { Message msg = commandHandler.obtainMessage(); msg.arg1 = command; msg.obj = data; From 21879faf4815a6acdb29e290d51a15bbe4dae03e Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 14 Dec 2023 13:45:34 -0500 Subject: [PATCH 558/725] wayland: Handle mouse focus when receiving touch events Compositors may switch from mouse to touch mode when a touch event is received, causing a pointer leave event and subsequent loss of mouse focus. Don't relinquish mouse focus on surfaces with active touch events. If there are active touch events when pointer focus is lost, the keyboard focus is used as a fallback for relinquishing mouse focus: if, in this case, the keyboard focus is then lost and there are no active touches, mouse focus is lost, and if all touches are raised and there is no keyboard or pointer focus, then the window loses mouse focus. --- src/video/wayland/SDL_waylandevents.c | 53 ++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index ebdf546d55efb..096e357b38f28 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -148,6 +148,19 @@ static void touch_del(SDL_TouchID id, wl_fixed_t *fx, wl_fixed_t *fy, struct wl_ } } +static SDL_bool Wayland_SurfaceHasActiveTouches(struct wl_surface *surface) +{ + struct SDL_WaylandTouchPoint *tp; + + wl_list_for_each (tp, &touch_points, link) { + if (tp->surface == surface) { + return SDL_TRUE; + } + } + + return SDL_FALSE; +} + static Uint64 Wayland_GetEventTimestamp(Uint64 nsTimestamp) { static Uint64 last; @@ -581,7 +594,13 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer, SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, 0, SDL_RELEASED, SDL_BUTTON_X2); } - SDL_SetMouseFocus(NULL); + + /* A pointer leave event may be emitted if the compositor hides the pointer in response to receiving a touch event. + * Don't relinquish focus if the surface has active touches, as the compositor is just transitioning from mouse to touch mode. + */ + if (!Wayland_SurfaceHasActiveTouches(surface)) { + SDL_SetMouseFocus(NULL); + } input->pointer_focus = NULL; } } @@ -984,6 +1003,8 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri y = wl_fixed_to_double(fy) / (window_data->wl_window_height - 1); } + SDL_SetMouseFocus(window_data->sdlwindow); + SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f); } @@ -1007,6 +1028,14 @@ static void touch_handler_up(void *data, struct wl_touch *touch, uint32_t serial SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, SDL_FALSE, x, y, 0.0f); + + /* If the seat lacks pointer focus, the seat's keyboard focus is another window or NULL, this window curently + * has mouse focus, and the surface has no active touch events, consider mouse focus to be lost. + */ + if (!input->pointer_focus && input->keyboard_focus != window_data && + SDL_GetMouseFocus() == window_data->sdlwindow && !Wayland_SurfaceHasActiveTouches(surface)) { + SDL_SetMouseFocus(NULL); + } } } } @@ -1447,15 +1476,18 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { struct SDL_WaylandInput *input = data; - SDL_WindowData *window; + SDL_WindowData *wind; + SDL_Window *window = NULL; if (!surface || !SDL_WAYLAND_own_surface(surface)) { return; } - window = wl_surface_get_user_data(surface); - if (window) { - window->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; + wind = wl_surface_get_user_data(surface); + if (wind) { + wind->keyboard_device = NULL; + window = wind->sdlwindow; + window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; } /* Stop key repeat before clearing keyboard focus */ @@ -1463,6 +1495,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, /* This will release any keys still pressed */ SDL_SetKeyboardFocus(NULL); + input->keyboard_focus = NULL; /* Clear the pressed modifiers. */ input->pressed_modifiers = SDL_KMOD_NONE; @@ -1472,6 +1505,13 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, SDL_IME_SetFocus(SDL_FALSE); } #endif + + /* If the surface had a pointer leave event while still having active touch events, it retained mouse focus. + * Clear it now if all touch events are raised. + */ + if (!input->pointer_focus && SDL_GetMouseFocus() == window && !Wayland_SurfaceHasActiveTouches(surface)) { + SDL_SetMouseFocus(NULL); + } } static SDL_bool keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime) @@ -1651,7 +1691,6 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat, } if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { - WAYLAND_wl_list_init(&touch_points); input->touch = wl_seat_get_touch(seat); SDL_AddTouch((SDL_TouchID)(intptr_t)input->touch, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch"); wl_touch_set_user_data(input->touch, input); @@ -2955,6 +2994,8 @@ void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version) return; } + WAYLAND_wl_list_init(&touch_points); + input->display = d; input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(SDL_WL_SEAT_VERSION, version)); input->sx_w = wl_fixed_from_int(0); From 627d134b9ee2ae9fdc256bad66995014db991cdf Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Thu, 14 Dec 2023 16:11:25 +0200 Subject: [PATCH 559/725] Add support for monochrome cursors with inverted pixels under Windows. Fixes #8157 --- src/events/SDL_mouse.c | 8 ++- src/video/windows/SDL_windowsmouse.c | 78 +++++++++++++++++++++------- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 97510469794c8..57357ad938cc1 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -1238,6 +1238,12 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, const Uint32 black = 0xFF000000; const Uint32 white = 0xFFFFFFFF; const Uint32 transparent = 0x00000000; +#if defined(__WIN32__) + /* Only Windows backend supports inverted pixels in mono cursors. */ + const Uint32 inverted = 0x00FFFFFF; +#else + const Uint32 inverted = 0xFF000000; +#endif /* defined(__WIN32__) */ /* Make sure the width is a multiple of 8 */ w = ((w + 7) & ~7); @@ -1257,7 +1263,7 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, if (maskb & 0x80) { *pixel++ = (datab & 0x80) ? black : white; } else { - *pixel++ = (datab & 0x80) ? black : transparent; + *pixel++ = (datab & 0x80) ? inverted : transparent; } datab <<= 1; maskb <<= 1; diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 95d2e01cfde6b..a037407c925fd 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -25,6 +25,7 @@ #include "SDL_windowsvideo.h" #include "../../events/SDL_mouse_c.h" +#include "../SDL_video_c.h" DWORD SDL_last_warp_time = 0; HCURSOR SDL_cursor = NULL; @@ -80,6 +81,32 @@ static SDL_Cursor *WIN_CreateDefaultCursor() return cursor; } +static SDL_bool IsMonochromeSurface(SDL_Surface *surface) +{ + int x, y; + Uint8 r, g, b, a; + + SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); + + for (y = 0; y < surface->h; y++) { + for (x = 0; x < surface->w; x++) { + SDL_ReadSurfacePixel(surface, x, y, &r, &g, &b, &a); + + /* Black or white pixel. */ + if (!((r == 0x00 && g == 0x00 && b == 0x00) || (r == 0xff && g == 0xff && b == 0xff))) { + return SDL_FALSE; + } + + /* Transparent or opaque pixel. */ + if (!(a == 0x00 || a == 0xff)) { + return SDL_FALSE; + } + } + } + + return SDL_TRUE; +} + static HBITMAP CreateColorBitmap(SDL_Surface *surface) { HBITMAP bitmap; @@ -107,43 +134,55 @@ static HBITMAP CreateColorBitmap(SDL_Surface *surface) return bitmap; } -static HBITMAP CreateMaskBitmap(SDL_Surface *surface) +/* Generate bitmap with a mask and optional monochrome image data. + * + * For info on the expected mask format see: + * https://devblogs.microsoft.com/oldnewthing/20101018-00/?p=12513 + */ +static HBITMAP CreateMaskBitmap(SDL_Surface *surface, SDL_bool is_monochrome) { HBITMAP bitmap; SDL_bool isstack; void *pixels; int x, y; - Uint8 *src, *dst; + Uint8 r, g, b, a; + Uint8 *dst; const int pitch = ((surface->w + 15) & ~15) / 8; + const int size = pitch * surface->h; static const unsigned char masks[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); - pixels = SDL_small_alloc(Uint8, pitch * surface->h, &isstack); + pixels = SDL_small_alloc(Uint8, size * (is_monochrome ? 2 : 1), &isstack); if (!pixels) { return NULL; } - /* Make the entire mask completely transparent. */ - SDL_memset(pixels, 0xff, pitch * surface->h); + dst = pixels; - SDL_LockSurface(surface); + /* Make the mask completely transparent. */ + SDL_memset(dst, 0xff, size); + if (is_monochrome) { + SDL_memset(dst + size, 0x00, size); + } - src = surface->pixels; - dst = pixels; - for (y = 0; y < surface->h; y++, src += surface->pitch, dst += pitch) { + for (y = 0; y < surface->h; y++, dst += pitch) { for (x = 0; x < surface->w; x++) { - Uint8 alpha = src[x * 4 + 3]; - if (alpha != 0) { + SDL_ReadSurfacePixel(surface, x, y, &r, &g, &b, &a); + + if (a != 0) { /* Reset bit of an opaque pixel. */ dst[x >> 3] &= ~masks[x & 7]; } + + if (is_monochrome && !(r == 0x00 && g == 0x00 && b == 0x00)) { + /* Set bit of white or inverted pixel. */ + dst[size + (x >> 3)] |= masks[x & 7]; + } } } - SDL_UnlockSurface(surface); - - bitmap = CreateBitmap(surface->w, surface->h, 1, 1, pixels); + bitmap = CreateBitmap(surface->w, surface->h * (is_monochrome ? 2 : 1), 1, 1, pixels); SDL_small_free(pixels, isstack); if (!bitmap) { WIN_SetError("CreateBitmap()"); @@ -158,22 +197,25 @@ static SDL_Cursor *WIN_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) HCURSOR hcursor; SDL_Cursor *cursor; ICONINFO ii; + SDL_bool is_monochrome = IsMonochromeSurface(surface); SDL_zero(ii); ii.fIcon = FALSE; ii.xHotspot = (DWORD)hot_x; ii.yHotspot = (DWORD)hot_y; - ii.hbmColor = CreateColorBitmap(surface); - ii.hbmMask = CreateMaskBitmap(surface); + ii.hbmMask = CreateMaskBitmap(surface, is_monochrome); + ii.hbmColor = is_monochrome ? NULL : CreateColorBitmap(surface); - if (!ii.hbmColor || !ii.hbmMask) { + if (!ii.hbmMask || (!is_monochrome && !ii.hbmColor)) { return NULL; } hcursor = CreateIconIndirect(&ii); - DeleteObject(ii.hbmColor); DeleteObject(ii.hbmMask); + if (ii.hbmColor) { + DeleteObject(ii.hbmColor); + } if (!hcursor) { WIN_SetError("CreateIconIndirect()"); From 0ab13f2498357af799ff8a4c7d4619674079e353 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Fri, 15 Dec 2023 17:36:17 +0200 Subject: [PATCH 560/725] joystick: fixup for Wireless Xbox 360 Controller VID/PID detection in WGI backend. It turns out that returned PID is zero in this case and it breaks SDL_IsXInputDevice/HIDAPI_IsDevicePresent checks --- .../windows/SDL_windows_gaming_input.c | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index ca86f707c760b..6ffbf8d976e8c 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -385,6 +385,23 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product); + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&game_controller); + if (SUCCEEDED(hr)) { + boolean wireless = 0; + hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(game_controller, &wireless); + if (SUCCEEDED(hr) && wireless) { + bus = SDL_HARDWARE_BUS_BLUETOOTH; + + /* Fixup for Wireless Xbox 360 Controller */ + if (product == 0) { + vendor = USB_VENDOR_MICROSOFT; + product = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; + } + } + + __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(game_controller); + } + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2); if (SUCCEEDED(hr)) { HSTRING hString; @@ -423,18 +440,8 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde } if (!ignore_joystick) { - hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&game_controller); - if (SUCCEEDED(hr)) { - boolean wireless; - + if (game_controller) { type = GetGameControllerType(game_controller); - - hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(game_controller, &wireless); - if (SUCCEEDED(hr) && wireless) { - bus = SDL_HARDWARE_BUS_BLUETOOTH; - } - - __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(game_controller); } guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type); From 55470079150c83a855b72e259246602d2f4db1fd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 15 Dec 2023 09:59:50 -0800 Subject: [PATCH 561/725] Added test for inverted cursor --- test/testcustomcursor.c | 105 +++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 17 deletions(-) diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index c46a250863920..bd91e843132e9 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -65,6 +65,50 @@ static const char *arrow[] = { "0,0" }; +static const char *cross[] = { + /* width height num_colors chars_per_pixel */ + " 32 32 3 1", + /* colors */ + "o c #000000", + ". c #ffffff", + " c None", + /* pixels */ + /* pixels */ + " ", + " ", + " ", + " ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oooooooooooooooooooooooo ", + " oooooooooooooooooooooooo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " oo ", + " ", + " ", + " ", + " ", + "0,0" +}; + static SDL_Cursor * init_color_cursor(const char *file) { @@ -127,6 +171,9 @@ init_system_cursor(const char *image[]) case '.': mask[i] |= 0x01; break; + case 'o': + data[i] |= 0x01; + break; case ' ': break; } @@ -138,8 +185,8 @@ init_system_cursor(const char *image[]) static SDLTest_CommonState *state; static int done; -static SDL_Cursor *cursors[1 + SDL_NUM_SYSTEM_CURSORS]; -static SDL_SystemCursor cursor_types[1 + SDL_NUM_SYSTEM_CURSORS]; +static SDL_Cursor *cursors[3 + SDL_NUM_SYSTEM_CURSORS]; +static SDL_SystemCursor cursor_types[3 + SDL_NUM_SYSTEM_CURSORS]; static int num_cursors; static int current_cursor; static SDL_bool show_cursor; @@ -257,7 +304,29 @@ static void loop(void) for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; - SDL_RenderClear(renderer); + SDL_FRect rect; + int x, y, row; + int window_w = 0, window_h = 0; + + SDL_GetWindowSize(state->windows[i], &window_w, &window_h); + rect.w = 128.0f; + rect.h = 128.0f; + for (y = 0, row = 0; y < window_h; y += (int)rect.h, ++row) { + SDL_bool black = ((row % 2) == 0) ? SDL_TRUE : SDL_FALSE; + for (x = 0; x < window_w; x += (int)rect.w) { + rect.x = (float)x; + rect.y = (float)y; + + if (black) { + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + } else { + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + } + SDL_RenderFillRect(renderer, &rect); + + black = !black; + } + } SDL_RenderPresent(renderer); } #ifdef __EMSCRIPTEN__ @@ -271,6 +340,7 @@ int main(int argc, char *argv[]) { int i; const char *color_cursor = NULL; + SDL_Cursor *cursor; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); @@ -299,23 +369,10 @@ int main(int argc, char *argv[]) quit(2); } - for (i = 0; i < state->num_windows; ++i) { - SDL_Renderer *renderer = state->renderers[i]; - SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); - SDL_RenderClear(renderer); - } - num_cursors = 0; if (color_cursor) { - SDL_Cursor *cursor = init_color_cursor(color_cursor); - if (cursor) { - cursors[num_cursors] = cursor; - cursor_types[num_cursors] = (SDL_SystemCursor)-1; - num_cursors++; - } - } else { - SDL_Cursor *cursor = init_system_cursor(arrow); + cursor = init_color_cursor(color_cursor); if (cursor) { cursors[num_cursors] = cursor; cursor_types[num_cursors] = (SDL_SystemCursor)-1; @@ -323,6 +380,20 @@ int main(int argc, char *argv[]) } } + cursor = init_system_cursor(arrow); + if (cursor) { + cursors[num_cursors] = cursor; + cursor_types[num_cursors] = (SDL_SystemCursor)-1; + num_cursors++; + } + + cursor = init_system_cursor(cross); + if (cursor) { + cursors[num_cursors] = cursor; + cursor_types[num_cursors] = (SDL_SystemCursor)-1; + num_cursors++; + } + for (i = 0; i < SDL_NUM_SYSTEM_CURSORS; ++i) { SDL_Cursor *cursor = SDL_CreateSystemCursor((SDL_SystemCursor)i); if (cursor) { From cbf9012c74c2e2babd3c48386dc42e3e4384337d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 15 Dec 2023 10:03:11 -0800 Subject: [PATCH 562/725] Fixed build --- test/testcustomcursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index bd91e843132e9..cbaaa06d37da3 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -395,7 +395,7 @@ int main(int argc, char *argv[]) } for (i = 0; i < SDL_NUM_SYSTEM_CURSORS; ++i) { - SDL_Cursor *cursor = SDL_CreateSystemCursor((SDL_SystemCursor)i); + cursor = SDL_CreateSystemCursor((SDL_SystemCursor)i); if (cursor) { cursors[num_cursors] = cursor; cursor_types[num_cursors] = i; From 8c285828e586f535b949ce8de05979cf07d44744 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 15 Dec 2023 10:06:01 -0800 Subject: [PATCH 563/725] Fixed return value for SDL_UDEV_AddCallback() Fixes https://github.com/libsdl-org/SDL/issues/8694 --- src/core/linux/SDL_udev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 72a527e036af8..59d37d0e9fdd9 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -530,7 +530,7 @@ int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) _this->last = item; } - return 1; + return 0; } void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb) From b937c54b665f134f241313eb45a4e0110807ae2c Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 15 Dec 2023 15:54:01 -0500 Subject: [PATCH 564/725] win32: Set all size and position variables for external windows --- src/video/windows/SDL_windowswindow.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index b59d2495b34a3..ef93a9a55c4b8 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -361,8 +361,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd int h = rect.bottom; if (window->flags & SDL_WINDOW_EXTERNAL) { - window->windowed.w = window->w = w; - window->windowed.h = window->h = h; + window->floating.w = window->windowed.w = window->w = w; + window->floating.h = window->windowed.h = window->h = h; } else if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) { /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */ int x, y; @@ -384,8 +384,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd point.y = 0; if (ClientToScreen(hwnd, &point)) { if (window->flags & SDL_WINDOW_EXTERNAL) { - window->windowed.x = point.x; - window->windowed.y = point.y; + window->floating.x = window->windowed.x = point.x; + window->floating.y = window->windowed.y = point.y; } window->x = point.x; window->y = point.y; From 240e7747c89d441ec483af3c72eb262a057f9a53 Mon Sep 17 00:00:00 2001 From: Matt Guerrette Date: Sat, 16 Dec 2023 22:11:14 -0500 Subject: [PATCH 565/725] Fix #8702: Add SDL_hidapi_steamdeck.c to Xcode target This commit fixes a linker issue when building SDL 3.0 using Xcode --- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index a5f81e68d4683..e4dca89aa1885 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ A75FDBB823E4CBC700529352 /* ReadMe.txt in Resources */ = {isa = PBXBuildFile; fileRef = F59C710300D5CB5801000001 /* ReadMe.txt */; }; A75FDBC523EA380300529352 /* SDL_hidapi_rumble.h in Headers */ = {isa = PBXBuildFile; fileRef = A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */; }; A75FDBCE23EA380300529352 /* SDL_hidapi_rumble.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */; }; + A79745702B2E9D39009D224A /* SDL_hidapi_steamdeck.c in Sources */ = {isa = PBXBuildFile; fileRef = A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */; }; A7D8A94B23E2514000DCD162 /* SDL.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A57123E2513D00DCD162 /* SDL.c */; }; A7D8A95123E2514000DCD162 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A57323E2513D00DCD162 /* SDL_spinlock.c */; }; A7D8A95723E2514000DCD162 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A57423E2513D00DCD162 /* SDL_atomic.c */; }; @@ -560,6 +561,7 @@ A75FDBA723E4CB6F00529352 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hidapi_rumble.h; sourceTree = ""; }; A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_rumble.c; sourceTree = ""; }; + A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_steamdeck.c; sourceTree = ""; }; A7D8A57123E2513D00DCD162 /* SDL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL.c; sourceTree = ""; }; A7D8A57323E2513D00DCD162 /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = ""; }; A7D8A57423E2513D00DCD162 /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = ""; }; @@ -1709,6 +1711,7 @@ A7D8A7BE23E2513E00DCD162 /* hidapi */ = { isa = PBXGroup; children = ( + A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */, F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */, A7D8A7C923E2513E00DCD162 /* SDL_hidapi_gamecube.c */, F3F07D59269640160074468B /* SDL_hidapi_luna.c */, @@ -2493,6 +2496,7 @@ A7D8BAAF23E2514400DCD162 /* s_atan.c in Sources */, A7D8B75223E2514300DCD162 /* SDL_sysloadso.c in Sources */, A7D8BBE123E2574800DCD162 /* SDL_uikitopenglview.m in Sources */, + A79745702B2E9D39009D224A /* SDL_hidapi_steamdeck.c in Sources */, A7D8B98623E2514400DCD162 /* SDL_render_metal.m in Sources */, A7D8AE7623E2514100DCD162 /* SDL_clipboard.c in Sources */, A7D8AEC423E2514100DCD162 /* SDL_cocoaevents.m in Sources */, From 72b7acfe8ac26498dac57d751e1b3485d30a62e3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 16 Dec 2023 21:27:44 -0800 Subject: [PATCH 566/725] Don't create a TLS error buffer if we're just clearing the error Fixes https://github.com/libsdl-org/SDL/issues/7600 --- src/SDL_error.c | 16 ++++++++++++---- src/SDL_error_c.h | 2 +- src/thread/SDL_thread.c | 6 +++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/SDL_error.c b/src/SDL_error.c index e7773ca492300..c8db336814457 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -30,7 +30,7 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) if (fmt) { va_list ap; int result; - SDL_error *error = SDL_GetErrBuf(); + SDL_error *error = SDL_GetErrBuf(SDL_TRUE); error->error = SDL_ErrorCodeGeneric; @@ -62,7 +62,11 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) /* Available for backwards compatibility */ const char *SDL_GetError(void) { - const SDL_error *error = SDL_GetErrBuf(); + const SDL_error *error = SDL_GetErrBuf(SDL_FALSE); + + if (!error) { + return ""; + } switch (error->error) { case SDL_ErrorCodeGeneric: @@ -76,7 +80,11 @@ const char *SDL_GetError(void) void SDL_ClearError(void) { - SDL_GetErrBuf()->error = SDL_ErrorCodeNone; + SDL_error *error = SDL_GetErrBuf(SDL_FALSE); + + if (error) { + error->error = SDL_ErrorCodeNone; + } } /* Very common errors go here */ @@ -84,7 +92,7 @@ int SDL_Error(SDL_errorcode code) { switch (code) { case SDL_ENOMEM: - SDL_GetErrBuf()->error = SDL_ErrorCodeOutOfMemory; + SDL_GetErrBuf(SDL_TRUE)->error = SDL_ErrorCodeOutOfMemory; return -1; case SDL_EFREAD: return SDL_SetError("Error reading from datastream"); diff --git a/src/SDL_error_c.h b/src/SDL_error_c.h index 291f04b06872d..ed5d06b49f620 100644 --- a/src/SDL_error_c.h +++ b/src/SDL_error_c.h @@ -44,6 +44,6 @@ typedef struct SDL_error } SDL_error; /* Defined in SDL_thread.c */ -extern SDL_error *SDL_GetErrBuf(void); +extern SDL_error *SDL_GetErrBuf(SDL_bool create); #endif /* SDL_error_c_h_ */ diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 84ec9a9ed7534..4f3842c0452f2 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -212,7 +212,7 @@ static void SDLCALL SDL_FreeErrBuf(void *data) #endif /* Routine to get the thread-specific error variable */ -SDL_error *SDL_GetErrBuf(void) +SDL_error *SDL_GetErrBuf(SDL_bool create) { #ifdef SDL_THREADS_DISABLED return SDL_GetStaticErrBuf(); @@ -223,6 +223,10 @@ SDL_error *SDL_GetErrBuf(void) const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1; SDL_error *errbuf; + if (!tls_errbuf && !create) { + return NULL; + } + /* tls_being_created is there simply to prevent recursion if SDL_CreateTLS() fails. It also means it's possible for another thread to also use SDL_global_errbuf, but that's very unlikely and hopefully won't cause issues. From 7f75178908355046e37d908648c44cf4d4625f09 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 16 Dec 2023 21:40:05 -0800 Subject: [PATCH 567/725] Verify that the %p format specifier works for 64-bit pointers --- test/testautomation_stdlib.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index d4abe2a2b2771..e447cf42ce1d2 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -320,6 +320,13 @@ static int stdlib_snprintf(void *arg) SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); SDLTest_AssertCheck(result == SDL_strlen(expected), "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); + if (sizeof(void *) >= 8) { + result = SDL_snprintf(text, sizeof(text), "%p", (void *)0x1ba07bddf60L); + expected = "0x1ba07bddf60"; + SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"%%p\", 0x1ba07bddf60)"); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == SDL_strlen(expected), "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); + } return TEST_COMPLETED; } From 08a7ca4d53ef0d504ec780936fd65616fe3a9f09 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Fri, 15 Dec 2023 17:09:15 +0200 Subject: [PATCH 568/725] XInput: Use XInputGetCapabilitiesEx instead of fragile GuessXInputDevice XInputGetCapabilitiesEx (ordinal 108) is available in XInput 1.4 that is shipped with Windows 8 and newer. --- src/core/windows/SDL_xinput.c | 3 + src/core/windows/SDL_xinput.h | 24 ++++ src/joystick/controller_list.h | 4 +- src/joystick/windows/SDL_xinputjoystick.c | 147 ++-------------------- 4 files changed, 42 insertions(+), 136 deletions(-) diff --git a/src/core/windows/SDL_xinput.c b/src/core/windows/SDL_xinput.c index 8a410e783a016..fe34b75fe148d 100644 --- a/src/core/windows/SDL_xinput.c +++ b/src/core/windows/SDL_xinput.c @@ -30,6 +30,7 @@ extern "C" { XInputGetState_t SDL_XInputGetState = NULL; XInputSetState_t SDL_XInputSetState = NULL; XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL; +XInputGetCapabilitiesEx_t SDL_XInputGetCapabilitiesEx = NULL; XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation = NULL; DWORD SDL_XInputVersion = 0; @@ -111,6 +112,8 @@ int WIN_LoadXInputDLL(void) } SDL_XInputSetState = (XInputSetState_t)GetProcAddress(s_pXInputDLL, "XInputSetState"); SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress(s_pXInputDLL, "XInputGetCapabilities"); + /* 108 is the ordinal for _XInputGetCapabilitiesEx, which additionally returns VID/PID of the controller. */ + SDL_XInputGetCapabilitiesEx = (XInputGetCapabilitiesEx_t)GetProcAddress(s_pXInputDLL, (LPCSTR)108); SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress(s_pXInputDLL, "XInputGetBatteryInformation"); if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) { WIN_UnloadXInputDLL(); diff --git a/src/core/windows/SDL_xinput.h b/src/core/windows/SDL_xinput.h index a92cb8b8cb8ff..1d01da3674d5a 100644 --- a/src/core/windows/SDL_xinput.h +++ b/src/core/windows/SDL_xinput.h @@ -44,6 +44,9 @@ using namespace XInputOnGameInput; #ifndef XINPUT_CAPS_FFB_SUPPORTED #define XINPUT_CAPS_FFB_SUPPORTED 0x0001 #endif +#ifndef XINPUT_CAPS_WIRELESS +#define XINPUT_CAPS_WIRELESS 0x0002 +#endif #ifndef XINPUT_DEVSUBTYPE_UNKNOWN #define XINPUT_DEVSUBTYPE_UNKNOWN 0x00 @@ -207,6 +210,17 @@ typedef struct #endif /* HAVE_XINPUT_H */ +/* This struct is not defined in XInput headers. */ +typedef struct _XINPUT_CAPABILITIES_EX +{ + XINPUT_CAPABILITIES Capabilities; + WORD VendorId; + WORD ProductId; + WORD ProductVersion; + WORD unk1; + DWORD unk2; +} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX; + /* Forward decl's for XInput API's we load dynamically and use if available */ typedef DWORD(WINAPI *XInputGetState_t)( DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ @@ -224,6 +238,14 @@ typedef DWORD(WINAPI *XInputGetCapabilities_t)( XINPUT_CAPABILITIES *pCapabilities /* [out] Receives the capabilities */ ); +/* Only available in XInput 1.4 that is shipped with Windows 8 and newer. */ +typedef DWORD(WINAPI *XInputGetCapabilitiesEx_t)( + DWORD dwReserved, /* [in] Must be 1 */ + DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ + DWORD dwFlags, /* [in] Input flags that identify the device type */ + XINPUT_CAPABILITIES_EX *pCapabilitiesEx /* [out] Receives the capabilities */ +); + typedef DWORD(WINAPI *XInputGetBatteryInformation_t)( DWORD dwUserIndex, BYTE devType, @@ -235,6 +257,7 @@ extern void WIN_UnloadXInputDLL(void); extern XInputGetState_t SDL_XInputGetState; extern XInputSetState_t SDL_XInputSetState; extern XInputGetCapabilities_t SDL_XInputGetCapabilities; +extern XInputGetCapabilitiesEx_t SDL_XInputGetCapabilitiesEx; extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation; extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */ @@ -246,6 +269,7 @@ extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */ #define XINPUTGETSTATE SDL_XInputGetState #define XINPUTSETSTATE SDL_XInputSetState #define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities +#define XINPUTGETCAPABILITIESEX SDL_XInputGetCapabilitiesEx #define XINPUTGETBATTERYINFORMATION SDL_XInputGetBatteryInformation #endif /* SDL_xinput_h_ */ diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 38f638b2a3ce4..f474be7ce0d96 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -169,7 +169,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2 { MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX) { MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR - { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Wireless Controller with XUSB driver on Windows + { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Controller with XUSB driver on Windows { MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff) { MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver { MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310 @@ -308,7 +308,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad { MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad { MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with XBOXGIP driver on Windows + { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One controller with XBOXGIP driver on Windows { MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad // { MAKE_CONTROLLER_ID( 0x045e, 0x0b02 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // The virtual keyboard generated by XboxGip drivers for Xbox One Controllers (see https://github.com/libsdl-org/SDL/pull/5121 for details) { MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth) diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index f1990da9377af..0a1baccf874f5 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -38,7 +38,6 @@ extern "C" { * Internal stuff. */ static SDL_bool s_bXInputEnabled = SDL_TRUE; -static char *s_arrXInputDevicePath[XUSER_MAX_COUNT]; static SDL_bool SDL_XInputUseOldJoystickMapping() { @@ -114,116 +113,25 @@ static const char *GetXInputName(const Uint8 userid, BYTE SubType) return name; } -/* We can't really tell what device is being used for XInput, but we can guess - and we'll be correct for the case where only one device is connected. - */ -static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion) +static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion) { -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) /* TODO: remove this ifndef __WINRT__ block, but only after integrating with UWP/WinRT's HID API */ - PRAWINPUTDEVICELIST devices = NULL; - UINT i, j, device_count = 0; - - if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!device_count)) { - return; /* oh well. */ - } + XINPUT_CAPABILITIES_EX capabilities; - devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count); - if (!devices) { - return; + if (!XINPUTGETCAPABILITIESEX || XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) != ERROR_SUCCESS) { + return SDL_FALSE; } - device_count = GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)); - if (device_count == (UINT)-1) { - SDL_free(devices); - return; /* oh well. */ - } - - /* First see if we have a cached entry for this index */ - if (s_arrXInputDevicePath[userid]) { - for (i = 0; i < device_count; i++) { - RID_DEVICE_INFO rdi; - char devName[128] = { 0 }; - UINT rdiSize = sizeof(rdi); - UINT nameSize = SDL_arraysize(devName); - - rdi.cbSize = sizeof(rdi); - if (devices[i].dwType == RIM_TYPEHID && - GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 && - GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) { - if (SDL_strcmp(devName, s_arrXInputDevicePath[userid]) == 0) { - *pVID = (Uint16)rdi.hid.dwVendorId; - *pPID = (Uint16)rdi.hid.dwProductId; - *pVersion = (Uint16)rdi.hid.dwVersionNumber; - SDL_free(devices); - return; - } - } - } + /* Fixup for Wireless Xbox 360 Controller */ + if (capabilities.ProductId == 0 && capabilities.Capabilities.Flags & XINPUT_CAPS_WIRELESS) { + capabilities.VendorId = USB_VENDOR_MICROSOFT; + capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; } - for (i = 0; i < device_count; i++) { - RID_DEVICE_INFO rdi; - char devName[MAX_PATH] = { 0 }; - UINT rdiSize = sizeof(rdi); - UINT nameSize = SDL_arraysize(devName); - - rdi.cbSize = sizeof(rdi); - if (devices[i].dwType == RIM_TYPEHID && - GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 && - GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) { -#ifdef DEBUG_JOYSTICK - SDL_Log("Raw input device: VID = 0x%x, PID = 0x%x, %s\n", rdi.hid.dwVendorId, rdi.hid.dwProductId, devName); -#endif - if (SDL_strstr(devName, "IG_") != NULL) { - SDL_bool found = SDL_FALSE; - for (j = 0; j < SDL_arraysize(s_arrXInputDevicePath); ++j) { - if (!s_arrXInputDevicePath[j]) { - continue; - } - if (SDL_strcmp(devName, s_arrXInputDevicePath[j]) == 0) { - found = SDL_TRUE; - break; - } - } - if (found) { - /* We already have this device in our XInput device list */ - continue; - } - - /* We don't actually know if this is the right device for this - * userid, but we'll record it so we'll at least be consistent - * when the raw device list changes. - */ - if (rdi.hid.dwVendorId == USB_VENDOR_VALVE && - rdi.hid.dwProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { - /* Steam encodes the real device in the path */ - int realVID = rdi.hid.dwVendorId; - int realPID = rdi.hid.dwProductId; - (void)SDL_sscanf(devName, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%x&%x&", &realVID, &realPID); - *pVID = (Uint16)realVID; - *pPID = (Uint16)realPID; - *pVersion = 0; - } else { - *pVID = (Uint16)rdi.hid.dwVendorId; - *pPID = (Uint16)rdi.hid.dwProductId; - *pVersion = (Uint16)rdi.hid.dwVersionNumber; - } - if (s_arrXInputDevicePath[userid]) { - SDL_free(s_arrXInputDevicePath[userid]); - } - s_arrXInputDevicePath[userid] = SDL_strdup(devName); - SDL_free(devices); - return; - } - } - } - SDL_free(devices); -#endif /* !__WINRT__ */ + *pVID = capabilities.VendorId; + *pPID = capabilities.ProductId; + *pVersion = capabilities.ProductVersion; - /* The device wasn't in the raw HID device list, it's probably Bluetooth */ - *pVID = 0x045e; /* Microsoft */ - *pPID = 0x02fd; /* XBox One S Bluetooth */ - *pVersion = 0; + return SDL_TRUE; } static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) @@ -279,6 +187,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC return; /* better luck next time? */ } + GetXInputDeviceInfo(userid, &vendor, &product, &version); pNewJoystick->bXInputDevice = SDL_TRUE; pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType)); if (!pNewJoystick->joystickname) { @@ -287,8 +196,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC } (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%u", userid); if (!SDL_XInputUseOldJoystickMapping()) { - GuessXInputDevice(userid, &vendor, &product, &version); - pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 'x', SubType); } pNewJoystick->SubType = SubType; @@ -319,14 +226,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC WINDOWS_AddJoystickDevice(pNewJoystick); } -static void DelXInputDevice(Uint8 userid) -{ - if (s_arrXInputDevicePath[userid]) { - SDL_free(s_arrXInputDevicePath[userid]); - s_arrXInputDevicePath[userid] = NULL; - } -} - void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext) { int iuserid; @@ -340,21 +239,7 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext) const Uint8 userid = (Uint8)iuserid; XINPUT_CAPABILITIES capabilities; if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) { - /* Adding a new device, must handle all removes first, or GuessXInputDevice goes terribly wrong (returns - a product/vendor ID that is not even attached to the system) when we get a remove and add on the same tick - (e.g. when disconnecting a device and the OS reassigns which userid an already-attached controller is) - */ - int iuserid2; - for (iuserid2 = iuserid - 1; iuserid2 >= 0; iuserid2--) { - const Uint8 userid2 = (Uint8)iuserid2; - XINPUT_CAPABILITIES capabilities2; - if (XINPUTGETCAPABILITIES(userid2, XINPUT_FLAG_GAMEPAD, &capabilities2) != ERROR_SUCCESS) { - DelXInputDevice(userid2); - } - } AddXInputDevice(userid, capabilities.SubType, pContext); - } else { - DelXInputDevice(userid); } } } @@ -552,12 +437,6 @@ void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick) void SDL_XINPUT_JoystickQuit(void) { - int iuserid; - - for (iuserid = 0; iuserid < XUSER_MAX_COUNT; ++iuserid) { - DelXInputDevice(iuserid); - } - if (s_bXInputEnabled) { WIN_UnloadXInputDLL(); } From 1745289b1b059dd1d3fe83a533249f4244025a67 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 16 Dec 2023 19:13:31 -0500 Subject: [PATCH 569/725] x11: Don't move the window when restoring and ensure that resize and position events are sent when entering or leaving fullscreen Account for the border sizes when restoring the window and only turn off resize events when entering or leaving fullscreen until the frame extents are changed, and only if they are, or previously were, non-zero. This necessitated further refinement to the sync algorithm as well, but as a result, the sync function no longer occasionally times out if creating a window and immediately recreating it when initializing a renderer, and some rare, spurious size and position failures in the centered window and state automated tests seem to be fixed. --- src/video/x11/SDL_x11events.c | 74 +++++++++++++++++++++++------------ src/video/x11/SDL_x11window.c | 51 ++++++++++-------------- src/video/x11/SDL_x11window.h | 4 +- 3 files changed, 72 insertions(+), 57 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 764bfa8e9738a..26f5e060a519f 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1326,36 +1326,36 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) if (xevent->xconfigure.x != data->last_xconfigure.x || xevent->xconfigure.y != data->last_xconfigure.y) { - SDL_Window *w; - int x = xevent->xconfigure.x; - int y = xevent->xconfigure.y; + if (!data->disable_size_position_events) { + SDL_Window *w; + int x = xevent->xconfigure.x; + int y = xevent->xconfigure.y; - data->pending_operation &= ~X11_PENDING_OP_MOVE; - SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); + data->pending_operation &= ~X11_PENDING_OP_MOVE; + SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); #ifdef SDL_USE_IME - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { - /* Update IME candidate list position */ - SDL_IME_UpdateTextRect(NULL); - } + if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + /* Update IME candidate list position */ + SDL_IME_UpdateTextRect(NULL); + } #endif - for (w = data->window->first_child; w; w = w->next_sibling) { - /* Don't update hidden child windows, their relative position doesn't change */ - if (!(w->flags & SDL_WINDOW_HIDDEN)) { - X11_UpdateWindowPosition(w, SDL_TRUE); + for (w = data->window->first_child; w; w = w->next_sibling) { + /* Don't update hidden child windows, their relative position doesn't change */ + if (!(w->flags & SDL_WINDOW_HIDDEN)) { + X11_UpdateWindowPosition(w, SDL_TRUE); + } } } } if (xevent->xconfigure.width != data->last_xconfigure.width || xevent->xconfigure.height != data->last_xconfigure.height) { - if (!data->skip_size_count) { + if (!data->disable_size_position_events) { data->pending_operation &= ~X11_PENDING_OP_RESIZE; SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, xevent->xconfigure.width, xevent->xconfigure.height); - } else { - data->skip_size_count--; } } @@ -1653,9 +1653,28 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) SDL_UpdateFullscreenMode(data->window, SDL_FALSE, SDL_TRUE); } - if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - /* Skip the first resize event if the borders are being turned on/off. */ - data->skip_size_count = 1; + if ((flags & SDL_WINDOW_FULLSCREEN) && + (data->border_top || data->border_left || data->border_bottom || data->border_right)) { + /* If the window is entering fullscreen and the borders are + * non-zero sized, turn off size events until the borders are + * shut off to avoid bogus window sizes and positions, and + * note that the old borders were non-zero for restoration. + */ + data->disable_size_position_events = SDL_TRUE; + data->previous_borders_nonzero = SDL_TRUE; + } else if (!(flags & SDL_WINDOW_FULLSCREEN) && + data->previous_borders_nonzero && + (!data->border_top && !data->border_left && !data->border_bottom && !data->border_right)) { + /* If the window is leaving fullscreen and the current borders + * are zero sized, but weren't when entering fullscreen, turn + * off size events until the borders come back to avoid bogus + * window sizes and positions. + */ + data->disable_size_position_events = SDL_TRUE; + data->previous_borders_nonzero = SDL_FALSE; + } else { + data->disable_size_position_events = SDL_FALSE; + data->previous_borders_nonzero = SDL_FALSE; } } if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { @@ -1678,11 +1697,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) /* Restore the last known floating state if leaving maximized mode */ if (!(flags & SDL_WINDOW_FULLSCREEN)) { data->pending_operation |= X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE; - data->expected.x = data->window->floating.x; - data->expected.y = data->window->floating.y; + data->expected.x = data->window->floating.x - data->border_left; + data->expected.y = data->window->floating.y - data->border_top; data->expected.w = data->window->floating.w; data->expected.h = data->window->floating.h; - X11_XMoveWindow(display, data->xwindow, data->window->floating.x, data->window->floating.y); + X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top); X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } } @@ -1699,18 +1718,23 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) right approach, but it seems to work. */ X11_UpdateKeymap(_this, SDL_TRUE); } else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) { + /* Re-enable size events if they were turned off waiting for the borders to come back + * when leaving fullscreen. + */ + data->disable_size_position_events = SDL_FALSE; X11_GetBorderValues(data); if (data->border_top != 0 || data->border_left != 0 || data->border_right != 0 || data->border_bottom != 0) { - /* Adjust if the window size changed to accommodate the borders. */ + /* Adjust if the window size/position changed to accommodate the borders. */ if (data->window->flags & SDL_WINDOW_MAXIMIZED) { data->pending_operation |= X11_PENDING_OP_RESIZE; data->expected.w = data->window->windowed.w; data->expected.h = data->window->windowed.h; X11_XResizeWindow(display, data->xwindow, data->window->windowed.w, data->window->windowed.h); } else { - data->pending_operation |= X11_PENDING_OP_RESIZE; + data->pending_operation |= X11_PENDING_OP_RESIZE | X11_PENDING_OP_MOVE; data->expected.w = data->window->floating.w; data->expected.h = data->window->floating.h; + X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top); X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 5a2de89d94cb0..24aa08c0904d6 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -856,6 +856,7 @@ static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int int (*prev_handler)(Display *, XErrorEvent *); Uint64 timeout = 0; int ret = 0; + SDL_bool force_exit = SDL_FALSE; X11_XSync(display, False); prev_handler = X11_XSetErrorHandler(X11_CatchAnyError); @@ -868,11 +869,25 @@ static int X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, int X11_XSync(display, False); X11_PumpEvents(_this); - if ((!(data->pending_operation & X11_PENDING_OP_MOVE) || (window->x == data->expected.x && window->y == data->expected.y)) && - (!(data->pending_operation & X11_PENDING_OP_RESIZE) || (window->w == data->expected.w && window->h == data->expected.h)) && - (data->pending_operation & ~(X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE)) == X11_PENDING_OP_NONE) { - /* The window is where it is wanted and nothing is pending. Done. */ - break; + if ((data->pending_operation & X11_PENDING_OP_MOVE) && (window->x == data->expected.x && window->y == data->expected.y)) { + data->pending_operation &= ~X11_PENDING_OP_MOVE; + } + if ((data->pending_operation & X11_PENDING_OP_RESIZE) && (window->w == data->expected.w && window->h == data->expected.h)) { + data->pending_operation &= ~X11_PENDING_OP_RESIZE; + } + + if (data->pending_operation == X11_PENDING_OP_NONE) { + if (force_exit || + (window->x == data->expected.x && window->y == data->expected.y && + window->w == data->expected.w && window->h == data->expected.h)) { + /* The window is in the expected state and nothing is pending. Done. */ + break; + } + + /* No operations are pending, but the window still isn't in the expected state. + * Try one more time before exiting. + */ + force_exit = SDL_TRUE; } if (SDL_GetTicks() >= timeout) { @@ -1310,15 +1325,9 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - /* Get some valid border values, if we haven't them yet */ + /* Get some valid border values, if we haven't received them yet */ if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) { X11_GetBorderValues(data); - - if (!data->initial_border_adjustment) { - data->expected.x += data->border_left; - data->expected.y += data->border_top; - data->initial_border_adjustment = SDL_TRUE; - } } } @@ -1591,24 +1600,6 @@ static int X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *wind e.xclient.data.l[3] = 0l; X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); - - if (!data->window_was_maximized) { - /* Attempt to move the window back to where it was. */ - SDL_RelativeToGlobalForWindow(window, - window->floating.x - data->border_left, window->floating.y - data->border_top, - &data->expected.x, &data->expected.y); - - data->expected.w = window->floating.w; - data->expected.h = window->floating.h; - data->pending_operation |= X11_PENDING_OP_MOVE; - X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); - - /* If the window is bordered, the size will be set when the borders turn themselves back on. */ - if (window->flags & SDL_WINDOW_BORDERLESS) { - data->pending_operation |= X11_PENDING_OP_RESIZE; - X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); - } - } } } else { Uint32 flags; diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 11977a57b9579..01fd049995a96 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -93,9 +93,9 @@ struct SDL_WindowData X11_PENDING_OP_RESIZE = 0x20 } pending_operation; - SDL_bool initial_border_adjustment; SDL_bool window_was_maximized; - int skip_size_count; + SDL_bool disable_size_position_events; + SDL_bool previous_borders_nonzero; SDL_HitTestResult hit_test_result; }; From 695846f2ed2feecf397721a4a5f1a8a4d09d0911 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 17 Dec 2023 09:26:25 -0800 Subject: [PATCH 570/725] Pass through the name of the controller for the XInput mapping --- src/joystick/SDL_gamepad_db.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 75bc7ead9d6bc..34f9c39ae55e9 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -30,7 +30,7 @@ */ static const char *s_GamepadMappings[] = { #ifdef SDL_JOYSTICK_XINPUT - "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "xinput,*,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", #endif #ifdef SDL_JOYSTICK_WGI "03000000491900001904000000007700,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,", From 4d5949dcf64f2633b1b435fb0c22a3b0b44d855f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 17 Dec 2023 10:07:46 -0800 Subject: [PATCH 571/725] Added a controller name for the Steam virtual gamepad --- src/joystick/controller_list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index f474be7ce0d96..09bd41bf329b0 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -594,6 +594,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x28de, 0x1102 ), k_eControllerType_SteamController, NULL }, // Valve wired Steam Controller (D0G) { MAKE_CONTROLLER_ID( 0x28de, 0x1105 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G) { MAKE_CONTROLLER_ID( 0x28de, 0x1106 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G) + { MAKE_CONTROLLER_ID( 0x28de, 0x11ff ), k_eControllerType_UnknownNonSteamController, "Steam Virtual Gamepad" }, // Steam virtual gamepad { MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller { MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB) { MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB) From 84a0d5f623b35952243aea737b2630ab5aa941e9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 14 Dec 2023 21:26:18 +0100 Subject: [PATCH 572/725] Added SDL_SetSurfaceScaleMode() and SDL_GetSurfaceScaleMode() to control scale mode using SDL_BlitSurfaceScaled() --- WhatsNew.txt | 1 + include/SDL3/SDL_render.h | 10 ------- include/SDL3/SDL_surface.h | 45 +++++++++++++++++++++++++++++++ src/dynapi/SDL_dynapi.sym | 2 ++ src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ src/video/SDL_surface.c | 36 +++++++++++++++++++++++-- 7 files changed, 86 insertions(+), 12 deletions(-) diff --git a/WhatsNew.txt b/WhatsNew.txt index 1b84c49b9b06d..18dfd84cbd62c 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -30,3 +30,4 @@ General: * Added SDL_PlayAudioDevice() to start audio playback * Added SDL_ConvertAudioSamples() to convert audio samples from one format to another * Added the hint SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY to control re-creation of Android SDL activity. +* Added SDL_SetSurfaceScaleMode() and SDL_GetSurfaceScaleMode() to control scale mode using SDL_BlitSurfaceScaled() diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index af5889ba9de92..15b0836b485e1 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -95,16 +95,6 @@ typedef struct SDL_Vertex SDL_FPoint tex_coord; /**< Normalized texture coordinates, if needed */ } SDL_Vertex; -/** - * The scaling mode for a texture. - */ -typedef enum -{ - SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ - SDL_SCALEMODE_LINEAR, /**< linear filtering */ - SDL_SCALEMODE_BEST /**< anisotropic filtering */ -} SDL_ScaleMode; - /** * The access pattern allowed for a texture. */ diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index aefb4233844f3..c9e5f765af7e4 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -64,6 +64,17 @@ extern "C" { typedef struct SDL_BlitMap SDL_BlitMap; /* this is an opaque type. */ +/** + * The scaling mode + */ +typedef enum +{ + SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ + SDL_SCALEMODE_LINEAR, /**< linear filtering */ + SDL_SCALEMODE_BEST /**< anisotropic filtering */ +} SDL_ScaleMode; + + /** * A collection of pixels used in software blitting. * @@ -104,6 +115,8 @@ typedef struct SDL_Surface /** clipping information */ SDL_Rect clip_rect; /**< Read-only */ + SDL_ScaleMode scaleMode; /**< The scale mode */ + /** info for fast blit mapping to other surfaces */ SDL_BlitMap *map; /**< Private */ @@ -903,6 +916,7 @@ extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface *src, * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurface + * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled (SDL_Surface *src, const SDL_Rect *srcrect, @@ -926,11 +940,42 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled + * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled (SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); +/** + * Set the scale mode used for surface scale operations. + * + * \param surface the surface to update. + * \param scaleMode the SDL_ScaleMode to use for scaling. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetSurfaceScaleMode + * \sa SDL_BlitSurfaceScaled + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode); + +/** + * Get the scale mode used for surface scale operations. + * + * \param surface the surface to query. + * \param scaleMode a pointer filled in with the current scale mode. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetSurfaceScaleMode + * \sa SDL_BlitSurfaceScaled + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode); + /** * Set the YUV conversion mode * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index e4747421af624..7a68abb998069 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -963,6 +963,8 @@ SDL3_0.0.0 { SDL_strnstr; SDL_wcsnstr; SDL_SyncWindow; + SDL_SetSurfaceScaleMode; + SDL_GetSurfaceScaleMode; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 25d834ce60362..acfbb8c7cf90c 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -988,3 +988,5 @@ #define SDL_strnstr SDL_strnstr_REAL #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_SyncWindow SDL_SyncWindow_REAL +#define SDL_SetSurfaceScaleMode SDL_SetSurfaceScaleMode_REAL +#define SDL_GetSurfaceScaleMode SDL_GetSurfaceScaleMode_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index e6d79cc035bf7..faf3d553e2a03 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1013,3 +1013,5 @@ SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_SetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_GetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode *b),(a,b),return) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 7b26b5e2eb41d..a86f8e068af6b 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -776,7 +776,7 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, int SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) { - return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); + return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, src->scaleMode); } int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, @@ -944,7 +944,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect) { - return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); + return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, src->scaleMode); } int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, @@ -1051,6 +1051,38 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr } } +int SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode) +{ + if (!surface) { + return SDL_InvalidParamError("surface"); + } + + if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) { + return SDL_InvalidParamError("scaleMode"); + } + + if (scaleMode == SDL_SCALEMODE_NEAREST) { + surface->scaleMode = SDL_SCALEMODE_NEAREST; + } else { + surface->scaleMode = SDL_SCALEMODE_LINEAR; + } + + return 0; +} + +int SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode) +{ + if (!surface) { + return SDL_InvalidParamError("surface"); + } + + if (scaleMode) { + *scaleMode = surface->scaleMode; + } + + return 0; +} + /* * Lock a surface to directly access the pixels */ From 43309d38ed5b2f5f47a2fad1205065ad3267d57c Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Fri, 15 Dec 2023 17:30:56 +0200 Subject: [PATCH 573/725] joystick: Extract 0x02a9 and 0x0291 PIDs into separate defines. Cleanup controller list comments block. --- src/joystick/controller_list.h | 47 +++++++++++------------ src/joystick/hidapi/SDL_hidapi_xbox360.c | 2 +- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 2 +- src/joystick/usb_ids.h | 2 + 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 09bd41bf329b0..5a631ba8f20bf 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -165,13 +165,13 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x0079, 0x18d4 ), k_eControllerType_XBox360Controller, NULL }, // GPD Win 2 X-Box Controller { MAKE_CONTROLLER_ID( 0x03eb, 0xff02 ), k_eControllerType_XBox360Controller, NULL }, // Wooting Two { MAKE_CONTROLLER_ID( 0x044f, 0xb326 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Gamepad GP XID - { MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad - { MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2 - { MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX) - { MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR - { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Controller with XUSB driver on Windows - { MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff) - { MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver + { MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Wired Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Play and Charge Cable + { MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff) + { MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft Xbox 360 Big Button IR + { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Controller with XUSB driver on Windows + { MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff) + { MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Receiver { MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310 { MAKE_CONTROLLER_ID( 0x046d, 0xc21e ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F510 { MAKE_CONTROLLER_ID( 0x046d, 0xc21f ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F710 @@ -302,23 +302,22 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x03f0, 0x0495 ), k_eControllerType_XBoxOneController, NULL }, // HP HyperX Clutch Gladiate { MAKE_CONTROLLER_ID( 0x044f, 0xd012 ), k_eControllerType_XBoxOneController, NULL }, // ThrustMaster eSwap PRO Controller Xbox - { MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad - { MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad (Firmware 2015) - { MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad - { MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad - { MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One controller with XBOXGIP driver on Windows - { MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad -// { MAKE_CONTROLLER_ID( 0x045e, 0x0b02 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // The virtual keyboard generated by XboxGip drivers for Xbox One Controllers (see https://github.com/libsdl-org/SDL/pull/5121 for details) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad - { MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad - { MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad (BLE) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (BLE) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (BLE) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (BLE) + { MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller (Firmware 2015) + { MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth) + { MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft Xbox One Elite Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth) + { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller with XBOXGIP driver on Windows + { MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (Bluetooth) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (Bluetooth) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller + { MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller (BLE) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (BLE) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (BLE) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (BLE) { MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2 { MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One { MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 3a7b3accc19db..c71ea3b329a2a 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -71,7 +71,7 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device /* This is the NVIDIA Shield controller which doesn't talk Xbox controller protocol */ return SDL_FALSE; } - if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x0719)) || + if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER)) || (type == SDL_GAMEPAD_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) { /* This is the wireless dongle, which talks a different protocol */ return SDL_FALSE; diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index a58c729e94cfe..411f5ae3b5b4e 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -65,7 +65,7 @@ static SDL_bool HIDAPI_DriverXbox360W_IsSupportedDevice(SDL_HIDAPI_Device *devic { const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */ - if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x02a9 || product_id == 0x0719) && interface_protocol == 0) || + if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY1 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER) && interface_protocol == 0) || (type == SDL_GAMEPAD_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) { return SDL_TRUE; } diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 75582605d100b..2765ebcc2e20d 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -121,6 +121,8 @@ #define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */ #define USB_PRODUCT_XBOX360_WIRED_CONTROLLER 0x028e #define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719 +#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY1 0x02a9 +#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 0x0291 #define USB_PRODUCT_XBOX_ONE_ADAPTIVE 0x0b0a #define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH 0x0b0c #define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE 0x0b21 From a4496f7dcf501646244964e2f8b1fc6b697c9e9a Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 18 Dec 2023 15:15:13 +0100 Subject: [PATCH 574/725] Update doc: SDL_SoftStretch() and SDL_SoftStretchLinear() #8667 --- include/SDL3/SDL_surface.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index c9e5f765af7e4..fcc8c1d2cf5ce 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -862,8 +862,6 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked * Perform a fast, low quality, stretch blit between two surfaces of the same * format. * - * **WARNING**: Please use SDL_BlitSurfaceScaled() instead. - * * \param src the SDL_Surface structure to be copied from * \param srcrect the SDL_Rect structure representing the rectangle to be * copied @@ -874,6 +872,9 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_BlitSurfaceScaled + * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, @@ -893,6 +894,9 @@ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_BlitSurfaceScaled + * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, From 8f79e0b7f8fb0620a9fd91f23ac6c2e71df110e8 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 18 Dec 2023 11:31:37 -0500 Subject: [PATCH 575/725] win32: Fix high-DPI debug logging --- src/video/windows/SDL_windowswindow.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index ef93a9a55c4b8..7bb9a116798fc 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -224,10 +224,10 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m #ifdef HIGHDPI_DEBUG SDL_Log("WIN_AdjustWindowRectWithStyle: in: %d, %d, %dx%d, returning: %d, %d, %dx%d, used dpi %d for frame calculation", - (use_current ? window->requested.x : window->windowed.x), - (use_current ? window->requested.y : window->windowed.y), - (use_current ? window->requested.w : window->windowed.w), - (use_current ? window->requested.h : window->windowed.h), + (rect_type == SDL_WINDOWRECT_FLOATING ? window->floating.x : rect_type == SDL_WINDOWRECT_WINDOWED ? window->windowed.x : window->x), + (rect_type == SDL_WINDOWRECT_FLOATING ? window->floating.y : rect_type == SDL_WINDOWRECT_WINDOWED ? window->windowed.y : window->y), + (rect_type == SDL_WINDOWRECT_FLOATING ? window->floating.w : rect_type == SDL_WINDOWRECT_WINDOWED ? window->windowed.w : window->w), + (rect_type == SDL_WINDOWRECT_FLOATING ? window->floating.h : rect_type == SDL_WINDOWRECT_WINDOWED ? window->windowed.h : window->h), *x, *y, *width, *height, frame_dpi); #endif return 0; From 69ec0322d3d82d542b19320b8faa70ca801ab586 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 18 Dec 2023 11:47:59 -0500 Subject: [PATCH 576/725] win32: Make leaving fullscreen when the window already isn't fullscreen a no-op Otherwise, the styling on external windows may end up being overridden. --- src/video/windows/SDL_windowswindow.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 7bb9a116798fc..07f6c9a2f00f2 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -1083,6 +1083,13 @@ int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vide SDL_Log("WIN_SetWindowFullscreen: %d", (int)fullscreen); #endif + /* Early out if already not in fullscreen, or the styling on + * external windows may end up being overridden. + */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN) && !fullscreen) { + return 0; + } + if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) { top = HWND_TOPMOST; } else { From 9d13be743bf37f4c1705c95d8f232114ea8d6e2a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 18 Dec 2023 19:21:00 -0800 Subject: [PATCH 577/725] Make sure we're rendering whenever the activity might be visible, even if we don't have focus. This fixes rendering when a system dialog is over the application --- .../main/java/org/libsdl/app/SDLActivity.java | 19 +------------------ .../main/java/org/libsdl/app/SDLSurface.java | 7 ++----- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 9d015a40b13e4..5165cef8882e4 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -788,7 +788,7 @@ public static void handleNativeState() { // Try a transition to resumed state if (mNextNativeState == NativeState.RESUMED) { - if (mSurface.mIsSurfaceReady && mHasFocus && mIsResumedCalled) { + if (mSurface.mIsSurfaceReady && (mHasFocus || mHasMultiWindow) && mIsResumedCalled) { if (mSDLThread == null) { // This is the entry point to the C app. // Start up the C app thread and enable sensor input for the first time @@ -1133,23 +1133,6 @@ public static void minimizeWindow() { * This method is called by SDL using JNI. */ public static boolean shouldMinimizeOnFocusLoss() { -/* - if (Build.VERSION.SDK_INT >= 24) { - if (mSingleton == null) { - return true; - } - - if (mSingleton.isInMultiWindowMode()) { - return false; - } - - if (mSingleton.isInPictureInPictureMode()) { - return false; - } - } - - return true; -*/ return false; } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java index fb98f1b624fa6..6cd268659c2a8 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java @@ -164,13 +164,10 @@ public void surfaceChanged(SurfaceHolder holder, } } - // Don't skip in MultiWindow. + // Don't skip if we might be multi-window or have popup dialogs if (skip) { if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) { - if (SDLActivity.mSingleton.isInMultiWindowMode()) { - Log.v("SDL", "Don't skip in Multi-Window"); - skip = false; - } + skip = false; } } From e6e54b22c8f7854b361b40576b3962d25f55dae7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 19 Dec 2023 07:49:57 -0800 Subject: [PATCH 578/725] Ignore all surface comparison output files in the testautomation directory --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 93ee540a98491..e0d5ef3a8a272 100644 --- a/.gitignore +++ b/.gitignore @@ -66,8 +66,7 @@ VisualC/tests/gamepadmap/button.bmp VisualC/tests/gamepadmap/gamepadmap.bmp VisualC/tests/gamepadmap/gamepadmap_back.bmp VisualC/tests/loopwave/sample.wav -VisualC/tests/testautomation/CompareSurfaces0001_Reference.bmp -VisualC/tests/testautomation/CompareSurfaces0001_TestOutput.bmp +VisualC/tests/testautomation/*.bmp VisualC/tests/testgamepad/axis.bmp VisualC/tests/testgamepad/button.bmp VisualC/tests/testgamepad/gamepadmap.bmp From a8f4f40d08a28ca0ef4f518509639f2553d8a123 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 19 Dec 2023 17:53:01 -0800 Subject: [PATCH 579/725] Sync more Steam Controller header definitions for the Steam Deck --- src/joystick/SDL_gamepad_db.h | 2 +- src/joystick/hidapi/SDL_hidapi_steam.c | 4 +- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 85 ++++++++---- .../hidapi/steam/controller_constants.h | 129 ++++++++++++------ .../hidapi/steam/controller_structs.h | 108 +++++++++++++-- 5 files changed, 240 insertions(+), 88 deletions(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 34f9c39ae55e9..1cbfde1a0a82d 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -727,7 +727,7 @@ static const char *s_GamepadMappings[] = { "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,", - "03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b17,paddle2:b16,paddle3:b19,paddle4:b18,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", + "03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b6,leftstick:b13,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:+a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index cd00e27fcd280..2825a529549b5 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1064,9 +1064,9 @@ static int HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_J SDL_memset(buf, 0, 65); buf[1] = ID_SET_SETTINGS_VALUES; if (enabled) { - ADD_SETTING(SETTING_GYRO_MODE, 0x18 /* SETTING_GYRO_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO */); + ADD_SETTING(SETTING_IMU_MODE, SETTING_GYRO_MODE_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO); } else { - ADD_SETTING(SETTING_GYRO_MODE, 0x00 /* SETTING_GYRO_MODE_OFF */); + ADD_SETTING(SETTING_IMU_MODE, SETTING_GYRO_MODE_OFF); } buf[2] = (unsigned char)(nSettings * 3); if (SetFeatureReport(device->dev, buf, 3 + nSettings * 3) < 0) { diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index f04cfc8952b61..688e821691ab3 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -32,6 +32,35 @@ #include "steam/controller_constants.h" #include "steam/controller_structs.h" +typedef enum +{ + STEAMDECK_LBUTTON_R2 = 0x00000001, + STEAMDECK_LBUTTON_L2 = 0x00000002, + STEAMDECK_LBUTTON_R = 0x00000004, + STEAMDECK_LBUTTON_L = 0x00000008, + STEAMDECK_LBUTTON_Y = 0x00000010, + STEAMDECK_LBUTTON_B = 0x00000020, + STEAMDECK_LBUTTON_X = 0x00000040, + STEAMDECK_LBUTTON_A = 0x00000080, + STEAMDECK_LBUTTON_DPAD_UP = 0x00000100, + STEAMDECK_LBUTTON_DPAD_RIGHT = 0x00000200, + STEAMDECK_LBUTTON_DPAD_LEFT = 0x00000400, + STEAMDECK_LBUTTON_DPAD_DOWN = 0x00000800, + STEAMDECK_LBUTTON_VIEW = 0x00001000, + STEAMDECK_LBUTTON_STEAM = 0x00002000, + STEAMDECK_LBUTTON_MENU = 0x00004000, + STEAMDECK_LBUTTON_L5 = 0x00008000, + STEAMDECK_LBUTTON_R5 = 0x00010000, + STEAMDECK_LBUTTON_LEFT_PAD = 0x00020000, + STEAMDECK_LBUTTON_RIGHT_PAD = 0x00040000, + STEAMDECK_LBUTTON_L3 = 0x00400000, + STEAMDECK_LBUTTON_R3 = 0x04000000, + + STEAMDECK_HBUTTON_L4 = 0x00000200, + STEAMDECK_HBUTTON_R4 = 0x00000400, + STEAMDECK_HBUTTON_QAM = 0x00040000, +} SteamDeckButtons; + typedef struct { Uint32 update_rate_us; @@ -53,17 +82,17 @@ static SDL_bool DisableDeckLizardMode(SDL_hid_device *dev) return SDL_FALSE; msg->header.type = ID_SET_SETTINGS_VALUES; - msg->header.length = 5 * sizeof(WriteDeckRegister); - msg->payload.wrDeckRegister.reg[0].addr = SETTING_DECK_RPAD_MARGIN; // disable margin - msg->payload.wrDeckRegister.reg[0].val = 0; - msg->payload.wrDeckRegister.reg[1].addr = SETTING_DECK_LPAD_MODE; // disable mouse - msg->payload.wrDeckRegister.reg[1].val = 7; - msg->payload.wrDeckRegister.reg[2].addr = SETTING_DECK_RPAD_MODE; // disable mouse - msg->payload.wrDeckRegister.reg[2].val = 7; - msg->payload.wrDeckRegister.reg[3].addr = SETTING_DECK_LPAD_CLICK_PRESSURE; // disable clicky pad - msg->payload.wrDeckRegister.reg[3].val = 0xFFFF; - msg->payload.wrDeckRegister.reg[4].addr = SETTING_DECK_RPAD_CLICK_PRESSURE; // disable clicky pad - msg->payload.wrDeckRegister.reg[4].val = 0xFFFF; + msg->header.length = 5 * sizeof(ControllerSetting); + msg->payload.setSettingsValues.settings[0].settingNum = SETTING_SMOOTH_ABSOLUTE_MOUSE; + msg->payload.setSettingsValues.settings[0].settingValue = 0; + msg->payload.setSettingsValues.settings[1].settingNum = SETTING_LEFT_TRACKPAD_MODE; + msg->payload.setSettingsValues.settings[1].settingValue = TRACKPAD_NONE; + msg->payload.setSettingsValues.settings[2].settingNum = SETTING_RIGHT_TRACKPAD_MODE; // disable mouse + msg->payload.setSettingsValues.settings[2].settingValue = TRACKPAD_NONE; + msg->payload.setSettingsValues.settings[3].settingNum = SETTING_LEFT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad + msg->payload.setSettingsValues.settings[3].settingValue = 0xFFFF; + msg->payload.setSettingsValues.settings[4].settingNum = SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad + msg->payload.setSettingsValues.settings[4].settingValue = 0xFFFF; rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); if (rc != sizeof(buffer)) @@ -89,9 +118,9 @@ static SDL_bool FeedDeckLizardWatchdog(SDL_hid_device *dev) return SDL_FALSE; msg->header.type = ID_SET_SETTINGS_VALUES; - msg->header.length = 1 * sizeof(WriteDeckRegister); - msg->payload.wrDeckRegister.reg[0].addr = SETTING_DECK_RPAD_MODE; // disable mouse - msg->payload.wrDeckRegister.reg[0].val = 7; + msg->header.length = 1 * sizeof(ControllerSetting); + msg->payload.setSettingsValues.settings[0].settingNum = SETTING_RIGHT_TRACKPAD_MODE; + msg->payload.setSettingsValues.settings[0].settingValue = TRACKPAD_NONE; rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer)); if (rc != sizeof(buffer)) @@ -229,32 +258,32 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_Y) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_LT) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_RT) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_SELECT) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_VIEW) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_START) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MENU) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MODE) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STEAM) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, - (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_BASE) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_QAM) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STICKL) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L3) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STICKR) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R3) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, - (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_PADDLE1) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_R4) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, - (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_PADDLE2) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_L4) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_PADDLE3) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R5) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_PADDLE4) ? SDL_PRESSED : SDL_RELEASED); + (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L5) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) ? SDL_PRESSED : SDL_RELEASED); @@ -268,9 +297,9 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) } SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, - (int)pInReport->payload.deckState.sLeftTrigger * 2 - 32768); + (int)pInReport->payload.deckState.sTriggerRawL * 2 - 32768); SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, - (int)pInReport->payload.deckState.sRightTrigger * 2 - 32768); + (int)pInReport->payload.deckState.sTriggerRawR * 2 - 32768); SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, pInReport->payload.deckState.sLeftStickX); diff --git a/src/joystick/hidapi/steam/controller_constants.h b/src/joystick/hidapi/steam/controller_constants.h index dc0c3f220a517..ab4ac2ee15cc8 100644 --- a/src/joystick/hidapi/steam/controller_constants.h +++ b/src/joystick/hidapi/steam/controller_constants.h @@ -47,6 +47,8 @@ enum ValveControllerPID D0G_BLE_PID = 0x1105, D0G_BLE2_PID = 0x1106, D0GGLE_PID = 0x1142, + + JUPITER_PID = 0x1205, }; // This enum contains all of the messages exchanged between the host and the target (only add to this enum and never change the order) @@ -68,10 +70,11 @@ enum FeatureReportMessageIDs ID_SET_CONTROLLER_MODE = 0x8D, ID_LOAD_DEFAULT_SETTINGS = 0x8E, ID_TRIGGER_HAPTIC_PULSE = 0x8F, + ID_TURN_OFF_CONTROLLER = 0x9F, ID_GET_DEVICE_INFO = 0xA1, - + ID_CALIBRATE_TRACKPADS = 0xA7, ID_RESERVED_0 = 0xA8, ID_SET_SERIAL_NUMBER = 0xA9, @@ -99,6 +102,12 @@ enum FeatureReportMessageIDs ID_CHECK_GYRO_FW_LOAD = 0xC2, ID_CALIBRATE_ANALOG = 0xC3, ID_DONGLE_GET_CONNECTED_SLOTS = 0xC4, + + ID_RESET_IMU = 0xCE, + + // Deck only + ID_TRIGGER_HAPTIC_CMD = 0xEA, + ID_TRIGGER_RUMBLE_CMD = 0xEB, }; @@ -215,6 +224,32 @@ typedef enum IO_RAW_JOYSTICK_X, IO_RAW_JOYSTICK_Y, IO_GYRO_TILT_VEC, + IO_PRESSURE_LEFT_PAD, + IO_PRESSURE_RIGHT_PAD, + IO_PRESSURE_LEFT_BUMPER, + IO_PRESSURE_RIGHT_BUMPER, + IO_PRESSURE_LEFT_GRIP, + IO_PRESSURE_RIGHT_GRIP, + IO_ANALOG_LEFT_TRIGGER_THRESHOLD, + IO_ANALOG_RIGHT_TRIGGER_THRESHOLD, + IO_PRESSURE_RIGHT_PAD_THRESHOLD, + IO_PRESSURE_LEFT_PAD_THRESHOLD, + IO_PRESSURE_RIGHT_BUMPER_THRESHOLD, + IO_PRESSURE_LEFT_BUMPER_THRESHOLD, + IO_PRESSURE_RIGHT_GRIP_THRESHOLD, + IO_PRESSURE_LEFT_GRIP_THRESHOLD, + IO_PRESSURE_RIGHT_PAD_RAW, + IO_PRESSURE_LEFT_PAD_RAW, + IO_PRESSURE_RIGHT_BUMPER_RAW, + IO_PRESSURE_LEFT_BUMPER_RAW, + IO_PRESSURE_RIGHT_GRIP_RAW, + IO_PRESSURE_LEFT_GRIP_RAW, + IO_PRESSURE_RIGHT_GRIP2_THRESHOLD, + IO_PRESSURE_LEFT_GRIP2_THRESHOLD, + IO_PRESSURE_LEFT_GRIP2, + IO_PRESSURE_RIGHT_GRIP2, + IO_PRESSURE_RIGHT_GRIP2_RAW, + IO_PRESSURE_LEFT_GRIP2_RAW, IO_ANALOG_COUNT } AnalogIO; @@ -315,37 +350,6 @@ enum GamepadButtons GAMEPAD_BTN_COUNT }; -typedef enum -{ - // Low word button bits - STEAMDECK_LBUTTON_RT2 = (1 << 0), - STEAMDECK_LBUTTON_LT2 = (1 << 1), - STEAMDECK_LBUTTON_RT = (1 << 2), - STEAMDECK_LBUTTON_LT = (1 << 3), - STEAMDECK_LBUTTON_Y = (1 << 4), - STEAMDECK_LBUTTON_B = (1 << 5), - STEAMDECK_LBUTTON_X = (1 << 6), - STEAMDECK_LBUTTON_A = (1 << 7), - STEAMDECK_LBUTTON_DPAD_UP = (1 << 8), - STEAMDECK_LBUTTON_DPAD_RIGHT = (1 << 9), - STEAMDECK_LBUTTON_DPAD_LEFT = (1 << 10), - STEAMDECK_LBUTTON_DPAD_DOWN = (1 << 11), - STEAMDECK_LBUTTON_SELECT = (1 << 12), - STEAMDECK_LBUTTON_MODE = (1 << 13), - STEAMDECK_LBUTTON_START = (1 << 14), - STEAMDECK_LBUTTON_PADDLE3 = (1 << 15), - STEAMDECK_LBUTTON_PADDLE4 = (1 << 16), - STEAMDECK_LBUTTON_PADL = (1 << 17), - STEAMDECK_LBUTTON_PADR = (1 << 18), - STEAMDECK_LBUTTON_STICKL = (1 << 22), - STEAMDECK_LBUTTON_STICKR = (1 << 26), - - // High word button bits - STEAMDECK_HBUTTON_PADDLE1 = (1 << 9), - STEAMDECK_HBUTTON_PADDLE2 = (1 << 10), - STEAMDECK_HBUTTON_BASE = (1 << 18) -} DeckButtons; - // Mode adjust enum ModeAdjustModes { @@ -413,13 +417,15 @@ typedef enum SETTING_MOUSE_SENSITIVITY, SETTING_MOUSE_ACCELERATION, SETTING_TRACKBALL_ROTATION_ANGLE, - SETTING_HAPTIC_INTENSITY, + SETTING_HAPTIC_INTENSITY_UNUSED, SETTING_LEFT_GAMEPAD_STICK_ENABLED, SETTING_RIGHT_GAMEPAD_STICK_ENABLED, SETTING_USB_DEBUG_MODE, SETTING_LEFT_TRACKPAD_MODE, SETTING_RIGHT_TRACKPAD_MODE, SETTING_MOUSE_POINTER_ENABLED, + + // 10 SETTING_DPAD_DEADZONE, SETTING_MINIMUM_MOMENTUM_VEL, SETTING_MOMENTUM_DECAY_AMMOUNT, @@ -430,6 +436,8 @@ typedef enum SETTING_MOMENTUM_VERTICAL_DIVISOR, SETTING_MOMENTUM_MAXIMUM_VELOCITY, SETTING_TRACKPAD_Z_ON, + + // 20 SETTING_TRACKPAD_Z_OFF, SETTING_SENSITIVY_SCALE_AMMOUNT, SETTING_LEFT_TRACKPAD_SECONDARY_MODE, @@ -440,6 +448,8 @@ typedef enum SETTING_TRACKPAD_OUTER_RADIUS, SETTING_TRACKPAD_Z_ON_LEFT, SETTING_TRACKPAD_Z_OFF_LEFT, + + // 30 SETTING_TRACKPAD_OUTER_SPIN_VEL, SETTING_TRACKPAD_OUTER_SPIN_RADIUS, SETTING_TRACKPAD_OUTER_SPIN_HORIZONTAL_ONLY, @@ -450,6 +460,8 @@ typedef enum SETTING_TRACKPAD_DOUBLE_TAP_BEEP_PERIOD, SETTING_TRACKPAD_DOUBLE_TAP_BEEP_COUNT, SETTING_TRACKPAD_OUTER_RADIUS_RELEASE_ON_TRANSITION, + + // 40 SETTING_RADIAL_MODE_ANGLE, SETTING_HAPTIC_INTENSITY_MOUSE_MODE, SETTING_LEFT_DPAD_REQUIRES_CLICK, @@ -458,24 +470,54 @@ typedef enum SETTING_LED_USER_BRIGHTNESS, SETTING_ENABLE_RAW_JOYSTICK, SETTING_ENABLE_FAST_SCAN, - SETTING_GYRO_MODE, + SETTING_IMU_MODE, SETTING_WIRELESS_PACKET_VERSION, + + // 50 SETTING_SLEEP_INACTIVITY_TIMEOUT, + SETTING_TRACKPAD_NOISE_THRESHOLD, + SETTING_LEFT_TRACKPAD_CLICK_PRESSURE, + SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE, + SETTING_LEFT_BUMPER_CLICK_PRESSURE, + SETTING_RIGHT_BUMPER_CLICK_PRESSURE, + SETTING_LEFT_GRIP_CLICK_PRESSURE, + SETTING_RIGHT_GRIP_CLICK_PRESSURE, + SETTING_LEFT_GRIP2_CLICK_PRESSURE, + SETTING_RIGHT_GRIP2_CLICK_PRESSURE, + + // 60 + SETTING_PRESSURE_MODE, + SETTING_CONTROLLER_TEST_MODE, + SETTING_TRIGGER_MODE, + SETTING_TRACKPAD_Z_THRESHOLD, + SETTING_FRAME_RATE, + SETTING_TRACKPAD_FILT_CTRL, + SETTING_TRACKPAD_CLIP, + SETTING_DEBUG_OUTPUT_SELECT, + SETTING_TRIGGER_THRESHOLD_PERCENT, + SETTING_TRACKPAD_FREQUENCY_HOPPING, + + // 70 + SETTING_HAPTICS_ENABLED, + SETTING_STEAM_WATCHDOG_ENABLE, + SETTING_TIMP_TOUCH_THRESHOLD_ON, + SETTING_TIMP_TOUCH_THRESHOLD_OFF, + SETTING_FREQ_HOPPING, + SETTING_TEST_CONTROL, + SETTING_HAPTIC_MASTER_GAIN_DB, + SETTING_THUMB_TOUCH_THRESH, + SETTING_DEVICE_POWER_STATUS, + SETTING_HAPTIC_INTENSITY, + + // 80 + SETTING_STABILIZER_ENABLED, + SETTING_TIMP_MODE_MTE, SETTING_COUNT, // This is a special setting value use for callbacks and should not be set/get explicitly. SETTING_ALL=0xFF } ControllerSettings; -typedef enum -{ - SETTING_DECK_LPAD_MODE = 0x07, - SETTING_DECK_RPAD_MODE = 0x08, - SETTING_DECK_RPAD_MARGIN = 0x18, - SETTING_DECK_LPAD_CLICK_PRESSURE = 0x34, - SETTING_DECK_RPAD_CLICK_PRESSURE = 0x35 -} DeckSettings; - typedef enum { SETTING_DEFAULT, @@ -501,6 +543,7 @@ typedef enum HAPTIC_PULSE_NORMAL = 0x0000, HAPTIC_PULSE_HIGH_PRIORITY = 0x0001, HAPTIC_PULSE_VERY_HIGH_PRIORITY = 0x0002, + HAPTIC_PULSE_IGNORE_USER_PREFS = 0x0003, } SettingHapticPulseFlags; typedef struct diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h index d7904bee658f1..69db0ee660700 100644 --- a/src/joystick/hidapi/steam/controller_structs.h +++ b/src/joystick/hidapi/steam/controller_structs.h @@ -32,6 +32,13 @@ typedef struct unsigned char length; } FeatureReportHeader; +// Generic controller settings structure +typedef struct +{ + unsigned char settingNum; + unsigned short settingValue; +} ControllerSetting; + // Generic controller attribute structure typedef struct { @@ -39,25 +46,89 @@ typedef struct uint32_t attributeValue; } ControllerAttribute; +// Generic controller settings structure +typedef struct +{ + ControllerSetting settings[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerSetting ) ]; +} MsgSetSettingsValues, MsgGetSettingsValues, MsgGetSettingsDefaults, MsgGetSettingsMaxs; + // Generic controller settings structure typedef struct { ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ]; } MsgGetAttributes; -// 16bit Steam Deck register with address typedef struct { - uint8_t addr; - uint16_t val; -} WriteDeckRegister; + unsigned char attributeTag; + char attributeValue[20]; +} MsgGetStringAttribute; -// Generic Steam Deck write register message typedef struct { - WriteDeckRegister reg[ (HID_FEATURE_REPORT_BYTES - sizeof ( FeatureReportHeader ) ) / sizeof (WriteDeckRegister ) ]; -} MsgWriteDeckRegister; - + unsigned char mode; +} MsgSetControllerMode; + +// Trigger a haptic pulse +typedef struct { + unsigned char which_pad; + unsigned short pulse_duration; + unsigned short pulse_interval; + unsigned short pulse_count; + short dBgain; + unsigned char priority; +} MsgFireHapticPulse; + +typedef struct { + uint8_t mode; +} MsgHapticSetMode; + +typedef enum { + HAPTIC_TYPE_OFF, + HAPTIC_TYPE_TICK, + HAPTIC_TYPE_CLICK, + HAPTIC_TYPE_TONE, + HAPTIC_TYPE_RUMBLE, + HAPTIC_TYPE_NOISE, + HAPTIC_TYPE_SCRIPT, + HAPTIC_TYPE_LOG_SWEEP, +} haptic_type_t; + +typedef enum { + HAPTIC_INTENSITY_SYSTEM, + HAPTIC_INTENSITY_SHORT, + HAPTIC_INTENSITY_MEDIUM, + HAPTIC_INTENSITY_LONG, + HAPTIC_INTENSITY_INSANE, +} haptic_intensity_t; + +typedef struct { + uint8_t side; // 0x01 = L, 0x02 = R, 0x03 = Both + uint8_t cmd; // 0 = Off, 1 = tick, 2 = click, 3 = tone, 4 = rumble, 5 = + // rumble_noise, 6 = script, 7 = sweep, + uint8_t ui_intensity; // 0-4 (0 = default) + int8_t dBgain; // dB Can be positive (reasonable clipping / limiting will apply) + uint16_t freq; // Frequency of tone (if applicable) + int16_t dur_ms; // Duration of tone / rumble (if applicable) (neg = infinite) + + uint16_t noise_intensity; + uint16_t lfo_freq; // Drives both tone and rumble geneators + uint8_t lfo_depth; // percentage, typically 100 + uint8_t rand_tone_gain; // Randomize each LFO cycle's gain + uint8_t script_id; // Used w/ dBgain for scripted haptics + + uint16_t lss_start_freq; // Used w/ Log Sine Sweep + uint16_t lss_end_freq; // Ditto +} MsgTriggerHaptic; + +typedef struct { + uint8_t unRumbleType; + uint16_t unIntensity; + uint16_t unLeftMotorSpeed; + uint16_t unRightMotorSpeed; + int8_t nLeftGain; + int8_t nRightGain; +} MsgSimpleRumbleCmd; // This is the only message struct that application code should use to interact with feature request messages. Any new // messages should be added to the union. The structures defined here should correspond to the ones defined in @@ -68,8 +139,17 @@ typedef struct FeatureReportHeader header; union { - MsgGetAttributes getAttributes; - MsgWriteDeckRegister wrDeckRegister; + MsgSetSettingsValues setSettingsValues; + MsgGetSettingsValues getSettingsValues; + MsgGetSettingsMaxs getSettingsMaxs; + MsgGetSettingsDefaults getSettingsDefaults; + MsgGetAttributes getAttributes; + MsgSetControllerMode controllerMode; + MsgFireHapticPulse fireHapticPulse; + MsgGetStringAttribute getStringAttribute; + MsgHapticSetMode hapticMode; + MsgTriggerHaptic triggerHaptic; + MsgSimpleRumbleCmd simpleRumble; } payload; } FeatureReportMsg; @@ -317,8 +397,8 @@ typedef struct short sGyroQuatZ; // Uncalibrated trigger values - short sLeftTrigger; - short sRightTrigger; + unsigned short sTriggerRawL; + unsigned short sTriggerRawR; // Left stick values short sLeftStickX; @@ -329,8 +409,8 @@ typedef struct short sRightStickY; // Touchpad pressures - short sLeftPadPressure; - short sRightPadPressure; + unsigned short sPressurePadLeft; + unsigned short sPressurePadRight; } SteamDeckStatePacket_t; typedef struct From c981a597dc7c69e7532796b3a206071807479d35 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 9 Dec 2023 23:05:34 -0800 Subject: [PATCH 580/725] Added Steam Input API support for game controllers Added support for getting the real controller info, as well as the function SDL_GetGamepadSteamHandle() to get the Steam Input API handle, from the virtual gamepads provided by Steam. Also added an event SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED which is triggered when a controller's API handle changes, e.g. the controllers were reassigned slots in the Steam UI. --- VisualC-GDK/SDL/SDL.vcxproj | 2 + VisualC-GDK/SDL/SDL.vcxproj.filters | 6 + VisualC-WinRT/SDL-UWP.vcxproj | 2 + VisualC-WinRT/SDL-UWP.vcxproj.filters | 6 + VisualC/SDL/SDL.vcxproj | 2 + VisualC/SDL/SDL.vcxproj.filters | 6 + Xcode/SDL/SDL.xcodeproj/project.pbxproj | 20 +- include/SDL3/SDL_events.h | 3 +- include/SDL3/SDL_gamepad.h | 13 + src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/events/SDL_events.c | 3 + src/joystick/SDL_gamepad.c | 45 +++- src/joystick/SDL_joystick.c | 140 +++++++++- src/joystick/SDL_joystick_c.h | 4 + src/joystick/SDL_steam_virtual_gamepad.c | 248 ++++++++++++++++++ src/joystick/SDL_steam_virtual_gamepad.h | 36 +++ src/joystick/SDL_sysjoystick.h | 4 + src/joystick/android/SDL_sysjoystick.c | 6 + src/joystick/apple/SDL_mfijoystick.m | 11 + src/joystick/bsd/SDL_bsdjoystick.c | 6 + src/joystick/darwin/SDL_iokitjoystick.c | 21 ++ src/joystick/darwin/SDL_iokitjoystick_c.h | 1 + src/joystick/dummy/SDL_sysjoystick.c | 6 + src/joystick/emscripten/SDL_sysjoystick.c | 6 + src/joystick/haiku/SDL_haikujoystick.cc | 6 + src/joystick/hidapi/SDL_hidapijoystick.c | 6 + src/joystick/linux/SDL_sysjoystick.c | 38 +-- src/joystick/n3ds/SDL_sysjoystick.c | 6 + src/joystick/ps2/SDL_sysjoystick.c | 7 + src/joystick/psp/SDL_sysjoystick.c | 6 + src/joystick/virtual/SDL_virtualjoystick.c | 6 + src/joystick/vita/SDL_sysjoystick.c | 6 + src/joystick/windows/SDL_dinputjoystick.c | 15 +- src/joystick/windows/SDL_rawinputjoystick.c | 21 ++ .../windows/SDL_windows_gaming_input.c | 36 +++ src/joystick/windows/SDL_windowsjoystick.c | 19 +- src/joystick/windows/SDL_windowsjoystick_c.h | 1 + src/joystick/windows/SDL_xinputjoystick.c | 26 +- src/joystick/windows/SDL_xinputjoystick_c.h | 1 + test/testcontroller.c | 19 ++ 42 files changed, 779 insertions(+), 40 deletions(-) create mode 100644 src/joystick/SDL_steam_virtual_gamepad.c create mode 100644 src/joystick/SDL_steam_virtual_gamepad.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 40bf69560b16e..7fe307986cd10 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -407,6 +407,7 @@ + @@ -634,6 +635,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index cd21c505f0d96..08257eaf35f4c 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -507,6 +507,9 @@ joystick + + joystick + joystick @@ -964,6 +967,9 @@ joystick + + joystick + libm diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 9c2d387d23cfa..2e1701a4d627b 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -127,6 +127,7 @@ + @@ -331,6 +332,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 586b0d2a5d2a1..d92ce733801ea 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -261,6 +261,9 @@ Source Files + + Source Files + Source Files @@ -585,6 +588,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index b89ae43ba0099..3f38d13f89f93 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -357,6 +357,7 @@ + @@ -537,6 +538,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 79a582b8e1a57..6002a968c609b 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -501,6 +501,9 @@ joystick + + joystick + joystick @@ -945,6 +948,9 @@ joystick + + joystick + libm diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index e4dca89aa1885..2f9d04f15658e 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -384,6 +384,10 @@ F32DDAD32AB795A30041EAA5 /* SDL_audioqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */; }; F32DDAD42AB795A30041EAA5 /* SDL_audioresample.c in Sources */ = {isa = PBXBuildFile; fileRef = F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */; }; F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; }; + F362B9192B3349E200D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9152B3349E200D30B94 /* controller_list.h */; }; + F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */; }; + F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */; }; + F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */; }; F36C7AD1294BA009004D61C3 /* SDL_runapp.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C7AD0294BA009004D61C3 /* SDL_runapp.c */; }; F376F6552559B4E300CFC0BC /* SDL_hidapi.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A81423E2513F00DCD162 /* SDL_hidapi.c */; }; F37A8E1A28405AA100C38E95 /* CMake in Resources */ = {isa = PBXBuildFile; fileRef = F37A8E1928405AA100C38E95 /* CMake */; }; @@ -879,6 +883,10 @@ F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_resampler_filter.h; sourceTree = ""; }; F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audioqueue.h; sourceTree = ""; }; F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audioresample.c; sourceTree = ""; }; + F362B9152B3349E200D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; sourceTree = ""; }; + F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamepad_c.h; sourceTree = ""; }; + F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steam_virtual_gamepad.h; sourceTree = ""; }; + F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steam_virtual_gamepad.c; sourceTree = ""; }; F36C7AD0294BA009004D61C3 /* SDL_runapp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_runapp.c; sourceTree = ""; }; F376F6182559B29300CFC0BC /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; }; F376F61A2559B2AF00CFC0BC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; @@ -1670,12 +1678,16 @@ A7D8A7BE23E2513E00DCD162 /* hidapi */, A7D8A7A123E2513E00DCD162 /* steam */, 75E09157241EA924004729E1 /* virtual */, - A7D8A7AD23E2513E00DCD162 /* SDL_gamepad.c */, - A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */, + F362B9152B3349E200D30B94 /* controller_list.h */, F3820712284F3609004DD584 /* controller_type.c */, A7D8A7D923E2513E00DCD162 /* controller_type.h */, + F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */, A7D8A79E23E2513E00DCD162 /* SDL_gamepad_db.h */, + A7D8A7AD23E2513E00DCD162 /* SDL_gamepad.c */, A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */, + A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */, + F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */, + F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */, A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */, A7D8A7CB23E2513E00DCD162 /* usb_ids.h */, ); @@ -2167,6 +2179,7 @@ F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */, F3990E062A788303000D8759 /* SDL_hidapi_ios.h in Headers */, A7D8B98023E2514400DCD162 /* SDL_d3dmath.h in Headers */, + F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */, A7D8B8A223E2514400DCD162 /* SDL_diskaudio.h in Headers */, A7D8BB3F23E2514500DCD162 /* SDL_displayevents_c.h in Headers */, A7D8BA1923E2514400DCD162 /* SDL_draw.h in Headers */, @@ -2180,6 +2193,7 @@ A7D8AB1023E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */, A7D8AB1C23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */, F3F7D9252933074E00816151 /* SDL_egl.h in Headers */, + F362B9192B3349E200D30B94 /* controller_list.h in Headers */, A7D8ABD923E2514100DCD162 /* SDL_egl_c.h in Headers */, F3F7D93D2933074E00816151 /* SDL_endian.h in Headers */, F3F7D9352933074E00816151 /* SDL_error.h in Headers */, @@ -2219,6 +2233,7 @@ F3F7D91D2933074E00816151 /* SDL_messagebox.h in Headers */, F3F7D98D2933074E00816151 /* SDL_metal.h in Headers */, F395C1BA2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */, + F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */, F3F7D9992933074E00816151 /* SDL_misc.h in Headers */, F3F7D9AD2933074E00816151 /* SDL_mouse.h in Headers */, A7D8BB1B23E2514500DCD162 /* SDL_mouse_c.h in Headers */, @@ -2583,6 +2598,7 @@ A7D8BAD323E2514500DCD162 /* s_tan.c in Sources */, A7D8AA6523E2514000DCD162 /* SDL_hints.c in Sources */, A7D8B53F23E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */, + F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */, A7D8AD6E23E2514100DCD162 /* SDL_pixels.c in Sources */, A7D8B75E23E2514300DCD162 /* SDL_sysloadso.c in Sources */, A7D8BBD723E2574800DCD162 /* SDL_uikitevents.m in Sources */, diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 1b9edd2bd8243..11276e5ff53bd 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -170,6 +170,7 @@ typedef enum SDL_EVENT_GAMEPAD_TOUCHPAD_UP, /**< Gamepad touchpad finger was lifted */ SDL_EVENT_GAMEPAD_SENSOR_UPDATE, /**< Gamepad sensor was updated */ SDL_EVENT_GAMEPAD_UPDATE_COMPLETE, /**< Gamepad update is complete */ + SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED, /**< Gamepad Steam handle has changed */ /* Touch events */ SDL_EVENT_FINGER_DOWN = 0x700, @@ -457,7 +458,7 @@ typedef struct SDL_GamepadButtonEvent */ typedef struct SDL_GamepadDeviceEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED or ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE */ + Uint32 type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED, ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE or ::SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ } SDL_GamepadDeviceEvent; diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index f536ce352ab66..d7da172763e17 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -758,6 +758,19 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadFirmwareVersion(SDL_Gamepad *gamepa */ extern DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamepad); +/** + * Get the Steam Input handle of an opened gamepad, if available. + * + * Returns an InputHandle_t for the gamepad that can be used with Steam Input API: + * https://partner.steamgames.com/doc/api/ISteamInput + * + * \param gamepad the gamepad object to query. + * \returns the gamepad handle, or 0 if unavailable. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC Uint64 SDLCALL SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad); + /** * Get the battery level of a gamepad, if available. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 7a68abb998069..9b22950ec927b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -965,6 +965,7 @@ SDL3_0.0.0 { SDL_SyncWindow; SDL_SetSurfaceScaleMode; SDL_GetSurfaceScaleMode; + SDL_GetGamepadSteamHandle; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index acfbb8c7cf90c..4c3007636b177 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -990,3 +990,4 @@ #define SDL_SyncWindow SDL_SyncWindow_REAL #define SDL_SetSurfaceScaleMode SDL_SetSurfaceScaleMode_REAL #define SDL_GetSurfaceScaleMode SDL_GetSurfaceScaleMode_REAL +#define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index faf3d553e2a03..7c7993c6f50b3 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1015,3 +1015,4 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode *b),(a,b),return) +SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index ac36e25cc2e77..0801db7d31342 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -433,6 +433,9 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMAPPED) PRINT_GAMEPADDEV_EVENT(event); break; + SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED) + PRINT_GAMEPADDEV_EVENT(event); + break; #undef PRINT_GAMEPADDEV_EVENT #define PRINT_CTOUCHPAD_EVENT(event) \ diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index e206f7feb67be..c911183da8499 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -25,6 +25,7 @@ #include "../SDL_utils_c.h" #include "SDL_sysjoystick.h" #include "SDL_joystick_c.h" +#include "SDL_steam_virtual_gamepad.h" #include "SDL_gamepad_c.h" #include "SDL_gamepad_db.h" #include "controller_type.h" @@ -2411,7 +2412,21 @@ SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id) SDL_GamepadType SDL_GetRealGamepadInstanceType(SDL_JoystickID instance_id) { - return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id)); + SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN; + const SDL_SteamVirtualGamepadInfo *info; + + SDL_LockJoysticks(); + { + info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); + if (info) { + type = info->type; + } else { + type = SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id)); + } + } + SDL_UnlockJoysticks(); + + return type; } char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id) @@ -2518,7 +2533,7 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) #ifdef __LINUX__ bSteamVirtualGamepad = (vendor == USB_VENDOR_VALVE && product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD); #elif defined(__MACOS__) - bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 1); + bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0); #elif defined(__WIN32__) /* We can't tell on Windows, but Steam will block others in input hooks */ bSteamVirtualGamepad = SDL_TRUE; @@ -3190,7 +3205,8 @@ const char *SDL_GetGamepadName(SDL_Gamepad *gamepad) { CHECK_GAMEPAD_MAGIC(gamepad, NULL); - if (SDL_strcmp(gamepad->name, "*") == 0) { + if (SDL_strcmp(gamepad->name, "*") == 0 || + gamepad->joystick->steam_handle != 0) { retval = SDL_GetJoystickName(gamepad->joystick); } else { retval = gamepad->name; @@ -3214,12 +3230,18 @@ const char *SDL_GetGamepadPath(SDL_Gamepad *gamepad) SDL_GamepadType SDL_GetGamepadType(SDL_Gamepad *gamepad) { SDL_GamepadType type; + const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); { CHECK_GAMEPAD_MAGIC(gamepad, SDL_GAMEPAD_TYPE_UNKNOWN); - type = gamepad->type; + info = SDL_GetJoystickInstanceVirtualGamepadInfo(gamepad->joystick->instance_id); + if (info) { + type = info->type; + } else { + type = gamepad->type; + } } SDL_UnlockJoysticks(); @@ -3310,6 +3332,21 @@ const char * SDL_GetGamepadSerial(SDL_Gamepad *gamepad) return SDL_GetJoystickSerial(joystick); } +Uint64 SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad) +{ + Uint64 handle = 0; + + SDL_LockJoysticks(); + { + CHECK_GAMEPAD_MAGIC(gamepad, 0); + + handle = gamepad->joystick->steam_handle; + } + SDL_UnlockJoysticks(); + + return handle; +} + SDL_JoystickPowerLevel SDL_GetGamepadPowerLevel(SDL_Gamepad *gamepad) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 28fcdda3af766..b555449e53fa7 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -26,6 +26,7 @@ #include "../SDL_hints_c.h" #include "SDL_gamepad_c.h" #include "SDL_joystick_c.h" +#include "SDL_steam_virtual_gamepad.h" #ifndef SDL_EVENTS_DISABLED #include "../events/SDL_events_c.h" @@ -624,6 +625,8 @@ int SDL_InitJoysticks(void) SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_JoystickAllowBackgroundEventsChanged, NULL); + SDL_InitSteamVirtualGamepadInfo(); + status = -1; for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { if (SDL_joystick_drivers[i]->Init() >= 0) { @@ -696,6 +699,19 @@ SDL_JoystickID *SDL_GetJoysticks(int *count) return joysticks; } +const SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id) +{ + SDL_JoystickDriver *driver; + int device_index; + const SDL_SteamVirtualGamepadInfo *info = NULL; + + if (SDL_SteamVirtualGamepadEnabled() && + SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { + info = SDL_GetSteamVirtualGamepadInfo(driver->GetDeviceSteamVirtualGamepadSlot(device_index)); + } + return info; +} + /* * Get the implementation dependent name of a joystick */ @@ -704,9 +720,13 @@ const char *SDL_GetJoystickInstanceName(SDL_JoystickID instance_id) SDL_JoystickDriver *driver; int device_index; const char *name = NULL; + const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); - if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { + info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); + if (info) { + name = info->name; + } else if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { name = driver->GetDeviceName(device_index); } SDL_UnlockJoysticks(); @@ -993,6 +1013,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) const char *joystickpath = NULL; SDL_JoystickPowerLevel initial_power_level; SDL_bool invert_sensors = SDL_FALSE; + const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); @@ -1076,6 +1097,12 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) joystick->is_gamepad = SDL_IsGamepad(instance_id); + /* Get the Steam Input API handle */ + info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); + if (info) { + joystick->steam_handle = info->handle; + } + /* Use system gyro and accelerometer if the gamepad doesn't have built-in sensors */ if (ShouldAttemptSensorFusion(joystick, &invert_sensors)) { AttemptSensorFusion(joystick, invert_sensors); @@ -1491,15 +1518,20 @@ SDL_PropertiesID SDL_GetJoystickProperties(SDL_Joystick *joystick) const char *SDL_GetJoystickName(SDL_Joystick *joystick) { const char *retval; + const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); - { + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + retval = info->name; + } else { CHECK_JOYSTICK_MAGIC(joystick, NULL); retval = joystick->name; } SDL_UnlockJoysticks(); + /* FIXME: Really we should reference count this name so it doesn't go away after unlock */ return retval; } @@ -1823,6 +1855,8 @@ void SDL_QuitJoysticks(void) SDL_QuitSubSystem(SDL_INIT_EVENTS); #endif + SDL_QuitSteamVirtualGamepadInfo(); + SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_JoystickAllowBackgroundEventsChanged, NULL); @@ -1921,7 +1955,10 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) SDL_joystick_being_added = SDL_TRUE; if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { - player_index = driver->GetDevicePlayerIndex(device_index); + player_index = driver->GetDeviceSteamVirtualGamepadSlot(device_index); + if (player_index < 0) { + player_index = driver->GetDevicePlayerIndex(device_index); + } } if (player_index < 0 && SDL_IsGamepad(instance_id)) { player_index = SDL_FindFreePlayerIndex(); @@ -2200,6 +2237,43 @@ int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butto return posted; } +static void SendSteamHandleUpdateEvents(void) +{ + SDL_Joystick *joystick; + const SDL_SteamVirtualGamepadInfo *info; + + /* Check to see if any Steam handles changed */ + for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { + SDL_bool changed = SDL_FALSE; + + if (!joystick->is_gamepad) { + continue; + } + + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + if (joystick->steam_handle != info->handle) { + joystick->steam_handle = info->handle; + changed = SDL_TRUE; + } + } else { + if (joystick->steam_handle != 0) { + joystick->steam_handle = 0; + changed = SDL_TRUE; + } + } + if (changed) { + SDL_Event event; + + SDL_zero(event); + event.type = SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED; + event.common.timestamp = 0; + event.gdevice.which = joystick->instance_id; + SDL_PushEvent(&event); + } + } +} + void SDL_UpdateJoysticks(void) { int i; @@ -2212,6 +2286,10 @@ void SDL_UpdateJoysticks(void) SDL_LockJoysticks(); + if (SDL_UpdateSteamVirtualGamepadInfo()) { + SendSteamHandleUpdateEvents(); + } + #ifdef SDL_JOYSTICK_HIDAPI /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */ HIDAPI_UpdateDevices(); @@ -3083,18 +3161,38 @@ SDL_JoystickGUID SDL_GetJoystickInstanceGUID(SDL_JoystickID instance_id) Uint16 SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id) { Uint16 vendor; - SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); + const SDL_SteamVirtualGamepadInfo *info; + + SDL_LockJoysticks(); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); + if (info) { + vendor = info->vendor_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); + + SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); + } + SDL_UnlockJoysticks(); - SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); return vendor; } Uint16 SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id) { Uint16 product; - SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); + const SDL_SteamVirtualGamepadInfo *info; + + SDL_LockJoysticks(); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); + if (info) { + product = info->product_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); + + SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); + } + SDL_UnlockJoysticks(); - SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); return product; } @@ -3141,18 +3239,38 @@ SDL_JoystickGUID SDL_GetJoystickGUID(SDL_Joystick *joystick) Uint16 SDL_GetJoystickVendor(SDL_Joystick *joystick) { Uint16 vendor; - SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + const SDL_SteamVirtualGamepadInfo *info; + + SDL_LockJoysticks(); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + vendor = info->vendor_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + + SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); + } + SDL_UnlockJoysticks(); - SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); return vendor; } Uint16 SDL_GetJoystickProduct(SDL_Joystick *joystick) { Uint16 product; - SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + const SDL_SteamVirtualGamepadInfo *info; + + SDL_LockJoysticks(); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + product = info->product_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + + SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); + } + SDL_UnlockJoysticks(); - SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); return product; } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 53360bb5d13aa..636b79ef5f42b 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -32,6 +32,7 @@ extern "C" { #endif struct SDL_JoystickDriver; +struct SDL_SteamVirtualGamepadInfo; extern char SDL_joystick_magic; /* Initialization and shutdown functions */ @@ -170,6 +171,9 @@ extern int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, extern void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel); +/* Function to get the Steam virtual gamepad info for a joystick */ +extern const struct SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id); + /* Internal sanity checking functions */ extern SDL_bool SDL_IsJoystickValid(SDL_Joystick *joystick); diff --git a/src/joystick/SDL_steam_virtual_gamepad.c b/src/joystick/SDL_steam_virtual_gamepad.c new file mode 100644 index 0000000000000..2d56e08a12207 --- /dev/null +++ b/src/joystick/SDL_steam_virtual_gamepad.c @@ -0,0 +1,248 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL_joystick_c.h" +#include "SDL_steam_virtual_gamepad.h" + +#ifdef __WIN32__ +#include "../core/windows/SDL_windows.h" +#else +#include +#include +#endif + +#define SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE "SteamVirtualGamepadInfo" + +static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0; +static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0; +static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; + + +static Uint64 GetFileModificationTime(const char *file) +{ + Uint64 modification_time = 0; + +#ifdef __WIN32__ + WCHAR *wFile = WIN_UTF8ToStringW(file); + if (wFile) { + HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + FILETIME last_write_time; + if (GetFileTime(hFile, NULL, NULL, &last_write_time)) { + modification_time = last_write_time.dwHighDateTime; + modification_time <<= 32; + modification_time |= last_write_time.dwLowDateTime; + } + CloseHandle(hFile); + } + SDL_free(wFile); + } +#else + struct stat sb; + + if (stat(file, &sb) == 0) { + modification_time = (Uint64)sb.st_mtime; + } +#endif + return modification_time; +} + +static void SDL_FreeSteamVirtualGamepadInfo(void) +{ + int i; + + SDL_AssertJoysticksLocked(); + + for (i = 0; i < SDL_steam_virtual_gamepad_info_count; ++i) { + SDL_SteamVirtualGamepadInfo *entry = SDL_steam_virtual_gamepad_info[i]; + if (entry) { + SDL_free(entry->name); + SDL_free(entry); + } + } + SDL_free(SDL_steam_virtual_gamepad_info); + SDL_steam_virtual_gamepad_info = NULL; + SDL_steam_virtual_gamepad_info_count = 0; +} + +static void AddVirtualGamepadInfo(int slot, SDL_SteamVirtualGamepadInfo *info) +{ + SDL_SteamVirtualGamepadInfo *new_info; + + SDL_AssertJoysticksLocked(); + + if (slot < 0) { + return; + } + + if (slot >= SDL_steam_virtual_gamepad_info_count) { + SDL_SteamVirtualGamepadInfo **slots = (SDL_SteamVirtualGamepadInfo **)SDL_realloc(SDL_steam_virtual_gamepad_info, (slot + 1)*sizeof(*SDL_steam_virtual_gamepad_info)); + if (!slots) { + return; + } + while (SDL_steam_virtual_gamepad_info_count <= slot) { + slots[SDL_steam_virtual_gamepad_info_count++] = NULL; + } + SDL_steam_virtual_gamepad_info = slots; + } + + if (SDL_steam_virtual_gamepad_info[slot]) { + /* We already have this slot info */ + return; + } + + new_info = (SDL_SteamVirtualGamepadInfo *)SDL_malloc(sizeof(*new_info)); + if (!new_info) { + return; + } + SDL_copyp(new_info, info); + SDL_steam_virtual_gamepad_info[slot] = new_info; + SDL_zerop(info); +} + +void SDL_InitSteamVirtualGamepadInfo(void) +{ + const char *file; + + SDL_AssertJoysticksLocked(); + + file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE); + if (file && *file) { + SDL_steam_virtual_gamepad_info_file = SDL_strdup(file); + } + SDL_UpdateSteamVirtualGamepadInfo(); +} + +SDL_bool SDL_SteamVirtualGamepadEnabled(void) +{ + SDL_AssertJoysticksLocked(); + + return (SDL_steam_virtual_gamepad_info != NULL); +} + +SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void) +{ + const int UPDATE_CHECK_INTERVAL_MS = 3000; + Uint64 now; + Uint64 mtime; + char *data, *end, *next, *line, *value; + size_t size; + int slot, new_slot; + SDL_SteamVirtualGamepadInfo info; + + SDL_AssertJoysticksLocked(); + + if (!SDL_steam_virtual_gamepad_info_file) { + return SDL_FALSE; + } + + now = SDL_GetTicks(); + if (SDL_steam_virtual_gamepad_info_check_time && + now < (SDL_steam_virtual_gamepad_info_check_time + UPDATE_CHECK_INTERVAL_MS)) { + return SDL_FALSE; + } + SDL_steam_virtual_gamepad_info_check_time = now; + + mtime = GetFileModificationTime(SDL_steam_virtual_gamepad_info_file); + if (mtime == 0 || mtime == SDL_steam_virtual_gamepad_info_file_mtime) { + return SDL_FALSE; + } + + data = (char *)SDL_LoadFile(SDL_steam_virtual_gamepad_info_file, &size); + if (!data) { + return SDL_FALSE; + } + + SDL_FreeSteamVirtualGamepadInfo(); + + slot = -1; + SDL_zero(info); + + for (next = data, end = data + size; next < end; ) { + while (next < end && (*next == '\0' || *next == '\r' || *next == '\n')) { + ++next; + } + + line = next; + + while (next < end && (*next != '\r' && *next != '\n')) { + ++next; + } + *next = '\0'; + + if (SDL_sscanf(line, "[slot %d]", &new_slot) == 1) { + if (slot >= 0) { + AddVirtualGamepadInfo(slot, &info); + } + slot = new_slot; + } else { + value = SDL_strchr(line, '='); + if (value) { + *value++ = '\0'; + + if (SDL_strcmp(line, "name") == 0) { + SDL_free(info.name); + info.name = SDL_strdup(value); + } else if (SDL_strcmp(line, "VID") == 0) { + info.vendor_id = (Uint16)SDL_strtoul(value, NULL, 0); + } else if (SDL_strcmp(line, "PID") == 0) { + info.product_id = (Uint16)SDL_strtoul(value, NULL, 0); + } else if (SDL_strcmp(line, "type") == 0) { + info.type = SDL_GetGamepadTypeFromString(value); + } else if (SDL_strcmp(line, "handle") == 0) { + info.handle = SDL_strtoull(value, NULL, 0); + } + } + } + } + if (slot >= 0) { + AddVirtualGamepadInfo(slot, &info); + } + SDL_free(data); + + SDL_steam_virtual_gamepad_info_file_mtime = mtime; + + return SDL_TRUE; +} + +const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot) +{ + SDL_AssertJoysticksLocked(); + + if (slot < 0 || slot >= SDL_steam_virtual_gamepad_info_count) { + return NULL; + } + return SDL_steam_virtual_gamepad_info[slot]; +} + +void SDL_QuitSteamVirtualGamepadInfo(void) +{ + SDL_AssertJoysticksLocked(); + + if (SDL_steam_virtual_gamepad_info_file) { + SDL_FreeSteamVirtualGamepadInfo(); + SDL_free(SDL_steam_virtual_gamepad_info_file); + SDL_steam_virtual_gamepad_info_file = NULL; + } +} diff --git a/src/joystick/SDL_steam_virtual_gamepad.h b/src/joystick/SDL_steam_virtual_gamepad.h new file mode 100644 index 0000000000000..fb12e7730f0c7 --- /dev/null +++ b/src/joystick/SDL_steam_virtual_gamepad.h @@ -0,0 +1,36 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +typedef struct SDL_SteamVirtualGamepadInfo +{ + Uint64 handle; + char *name; + Uint16 vendor_id; + Uint16 product_id; + SDL_GamepadType type; +} SDL_SteamVirtualGamepadInfo; + +void SDL_InitSteamVirtualGamepadInfo(void); +SDL_bool SDL_SteamVirtualGamepadEnabled(void); +SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void); +const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot); +void SDL_QuitSteamVirtualGamepadInfo(void); diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 8ac081026aff9..dfab89928820a 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -77,6 +77,7 @@ struct SDL_Joystick char *serial _guarded; /* Joystick serial */ SDL_JoystickGUID guid _guarded; /* Joystick guid */ Uint16 firmware_version _guarded; /* Firmware version, if available */ + Uint64 steam_handle _guarded; /* Steam controller API handle */ int naxes _guarded; /* Number of axis controls on the joystick */ SDL_JoystickAxisInfo *axes _guarded; @@ -168,6 +169,9 @@ typedef struct SDL_JoystickDriver /* Function to get the device-dependent path of a joystick */ const char *(*GetDevicePath)(int device_index); + /* Function to get the Steam virtual gamepad slot of a joystick */ + int (*GetDeviceSteamVirtualGamepadSlot)(int device_index); + /* Function to get the player index of a joystick */ int (*GetDevicePlayerIndex)(int device_index); diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index bcc2a715cb74a..601053659e6ef 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -541,6 +541,11 @@ static const char *ANDROID_JoystickGetDevicePath(int device_index) return NULL; } +static int ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int ANDROID_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -681,6 +686,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = { ANDROID_JoystickDetect, ANDROID_JoystickGetDeviceName, ANDROID_JoystickGetDevicePath, + ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot, ANDROID_JoystickGetDevicePlayerIndex, ANDROID_JoystickSetDevicePlayerIndex, ANDROID_JoystickGetDeviceGUID, diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index b8e6da62cef90..3923e87a0500f 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -661,6 +661,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); + if (SDL_ShouldIgnoreJoystick(name, device->guid)) { + return SDL_FALSE; + } + /* This will be set when the first button press of the controller is * detected. */ controller.playerIndex = -1; @@ -705,6 +709,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet } else if (controller) { #ifdef SDL_JOYSTICK_MFI if (!IOS_AddMFIJoystickDevice(device, controller)) { + SDL_free(device->name); SDL_free(device); return; } @@ -898,6 +903,11 @@ static void IOS_JoystickDetect(void) return NULL; } +static int IOS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int IOS_JoystickGetDevicePlayerIndex(int device_index) { #ifdef SDL_JOYSTICK_MFI @@ -2165,6 +2175,7 @@ static void GetAppleSFSymbolsNameForElement(GCControllerElement *element, char * IOS_JoystickDetect, IOS_JoystickGetDeviceName, IOS_JoystickGetDevicePath, + IOS_JoystickGetDeviceSteamVirtualGamepadSlot, IOS_JoystickGetDevicePlayerIndex, IOS_JoystickSetDevicePlayerIndex, IOS_JoystickGetDeviceGUID, diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index fc97c5d49f5b3..4a04030767594 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -543,6 +543,11 @@ static const char *BSD_JoystickGetDevicePath(int device_index) return GetJoystickByDevIndex(device_index)->path; } +static int BSD_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int BSD_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -850,6 +855,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = { BSD_JoystickDetect, BSD_JoystickGetDeviceName, BSD_JoystickGetDevicePath, + BSD_JoystickGetDeviceSteamVirtualGamepadSlot, BSD_JoystickGetDevicePlayerIndex, BSD_JoystickSetDevicePlayerIndex, BSD_JoystickGetDeviceGUID, diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index b6bc97fd7a6c8..f5a7d76516a27 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -405,6 +405,19 @@ static void AddHIDElement(const void *value, void *parameter) } } +static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *product_string) +{ + int slot = -1; + + if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER) { + /* Gamepad name is "GamePad-N", where N is slot + 1 */ + if (SDL_sscanf(product_string, "GamePad-%d", &slot) == 1) { + slot -= 1; + } + } + return slot; +} + static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) { Sint32 vendor = 0; @@ -485,6 +498,7 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) #endif pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0); + pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); if (array) { @@ -711,6 +725,12 @@ const char *DARWIN_JoystickGetDevicePath(int device_index) return NULL; } +static int DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + recDevice *device = GetDeviceForIndex(device_index); + return device ? device->steam_virtual_gamepad_slot : -1; +} + static int DARWIN_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -1056,6 +1076,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = { DARWIN_JoystickDetect, DARWIN_JoystickGetDeviceName, DARWIN_JoystickGetDevicePath, + DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot, DARWIN_JoystickGetDevicePlayerIndex, DARWIN_JoystickSetDevicePlayerIndex, DARWIN_JoystickGetDeviceGUID, diff --git a/src/joystick/darwin/SDL_iokitjoystick_c.h b/src/joystick/darwin/SDL_iokitjoystick_c.h index 30bad169c021e..630d4aba47cd8 100644 --- a/src/joystick/darwin/SDL_iokitjoystick_c.h +++ b/src/joystick/darwin/SDL_iokitjoystick_c.h @@ -71,6 +71,7 @@ struct joystick_hwdata int instance_id; SDL_JoystickGUID guid; + int steam_virtual_gamepad_slot; struct joystick_hwdata *pNext; /* next device */ }; diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 81a678d08df5f..687175f9f9864 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -51,6 +51,11 @@ static const char *DUMMY_JoystickGetDevicePath(int device_index) return NULL; } +static int DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int DUMMY_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -130,6 +135,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = { DUMMY_JoystickDetect, DUMMY_JoystickGetDeviceName, DUMMY_JoystickGetDevicePath, + DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot, DUMMY_JoystickGetDevicePlayerIndex, DUMMY_JoystickSetDevicePlayerIndex, DUMMY_JoystickGetDeviceGUID, diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index abf074d9b99e0..e98f2213f7d4e 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -269,6 +269,11 @@ static const char *EMSCRIPTEN_JoystickGetDevicePath(int device_index) return NULL; } +static int EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -416,6 +421,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = { EMSCRIPTEN_JoystickDetect, EMSCRIPTEN_JoystickGetDeviceName, EMSCRIPTEN_JoystickGetDevicePath, + EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot, EMSCRIPTEN_JoystickGetDevicePlayerIndex, EMSCRIPTEN_JoystickSetDevicePlayerIndex, EMSCRIPTEN_JoystickGetDeviceGUID, diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index cfdca6a045d08..e107c717902d1 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -101,6 +101,11 @@ extern "C" return SDL_joyport[device_index]; } + static int HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) + { + return -1; + } + static int HAIKU_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -295,6 +300,7 @@ extern "C" HAIKU_JoystickDetect, HAIKU_JoystickGetDeviceName, HAIKU_JoystickGetDevicePath, + HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot, HAIKU_JoystickGetDevicePlayerIndex, HAIKU_JoystickSetDevicePlayerIndex, HAIKU_JoystickGetDeviceGUID, diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 5152828f8d0d5..7f4558baa2718 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1376,6 +1376,11 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index) return path; } +static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index) { SDL_HIDAPI_Device *device; @@ -1654,6 +1659,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = { HIDAPI_JoystickDetect, HIDAPI_JoystickGetDeviceName, HIDAPI_JoystickGetDevicePath, + HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot, HIDAPI_JoystickGetDevicePlayerIndex, HIDAPI_JoystickSetDevicePlayerIndex, HIDAPI_JoystickGetDeviceGUID, diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 965e5f415af0a..aef90cba93771 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -220,14 +220,18 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, } #endif /* SDL_JOYSTICK_HIDAPI */ -static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot) +static SDL_bool GetSteamVirtualGamepadSlot(int fd, int *slot) { - const char *digits = SDL_strstr(name, "pad "); - if (digits) { - digits += 4; - if (SDL_isdigit(*digits)) { - *slot = SDL_atoi(digits); - return SDL_TRUE; + char name[128]; + + if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) { + const char *digits = SDL_strstr(name, "pad "); + if (digits) { + digits += 4; + if (SDL_isdigit(*digits)) { + *slot = SDL_atoi(digits); + return SDL_TRUE; + } } } return SDL_FALSE; @@ -445,7 +449,6 @@ static void MaybeAddDevice(const char *path) #ifdef DEBUG_INPUT_EVENTS SDL_Log("found joystick: %s\n", path); #endif - close(fd); item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); if (!item) { SDL_free(name); @@ -460,7 +463,7 @@ static void MaybeAddDevice(const char *path) if (vendor == USB_VENDOR_VALVE && product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { - GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot); + GetSteamVirtualGamepadSlot(fd, &item->steam_virtual_gamepad_slot); } if ((!item->path) || (!item->name)) { @@ -487,7 +490,6 @@ static void MaybeAddDevice(const char *path) #ifdef DEBUG_INPUT_EVENTS SDL_Log("found sensor: %s\n", path); #endif - close(fd); item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item)); if (!item_sensor) { goto done; @@ -505,8 +507,10 @@ static void MaybeAddDevice(const char *path) goto done; } - close(fd); done: + if (fd >= 0) { + close(fd); + } SDL_UnlockJoysticks(); } @@ -874,7 +878,6 @@ static void LINUX_ScanSteamVirtualGamepads(void) int fd; struct dirent **entries = NULL; char path[PATH_MAX]; - char name[128]; struct input_id inpid; int num_virtual_gamepads = 0; int virtual_gamepad_slot; @@ -889,8 +892,7 @@ static void LINUX_ScanSteamVirtualGamepads(void) if (ioctl(fd, EVIOCGID, &inpid) == 0 && inpid.vendor == USB_VENDOR_VALVE && inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && - ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && - GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) { + GetSteamVirtualGamepadSlot(fd, &virtual_gamepad_slot)) { VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); if (new_virtual_gamepads) { VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; @@ -1116,11 +1118,16 @@ static const char *LINUX_JoystickGetDevicePath(int device_index) return GetJoystickByDevIndex(device_index)->path; } -static int LINUX_JoystickGetDevicePlayerIndex(int device_index) +static int LINUX_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) { return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot; } +static int LINUX_JoystickGetDevicePlayerIndex(int device_index) +{ + return -1; +} + static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) { } @@ -2689,6 +2696,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = { LINUX_JoystickDetect, LINUX_JoystickGetDeviceName, LINUX_JoystickGetDevicePath, + LINUX_JoystickGetDeviceSteamVirtualGamepadSlot, LINUX_JoystickGetDevicePlayerIndex, LINUX_JoystickSetDevicePlayerIndex, LINUX_JoystickGetDeviceGUID, diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index 5ba1348f71cfc..6460235ea6874 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -231,6 +231,11 @@ static const char *N3DS_JoystickGetDevicePath(int device_index) return NULL; } +static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int N3DS_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -271,6 +276,7 @@ SDL_JoystickDriver SDL_N3DS_JoystickDriver = { .Detect = N3DS_JoystickDetect, .GetDeviceName = N3DS_JoystickGetDeviceName, .GetDevicePath = N3DS_JoystickGetDevicePath, + .GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot, .GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex, .SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex, .GetDeviceGUID = N3DS_JoystickGetDeviceGUID, diff --git a/src/joystick/ps2/SDL_sysjoystick.c b/src/joystick/ps2/SDL_sysjoystick.c index e5f6201cbfbd8..46d3a9a4e8d90 100644 --- a/src/joystick/ps2/SDL_sysjoystick.c +++ b/src/joystick/ps2/SDL_sysjoystick.c @@ -157,6 +157,12 @@ static const char *PS2_JoystickGetDevicePath(int index) return NULL; } +/* Function to get the Steam virtual gamepad slot of a joystick */ +static int PS2_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + /* Function to get the player index of a joystick */ static int PS2_JoystickGetDevicePlayerIndex(int device_index) { @@ -341,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = { PS2_JoystickDetect, PS2_JoystickGetDeviceName, PS2_JoystickGetDevicePath, + PS2_JoystickGetDeviceSteamVirtualGamepadSlot, PS2_JoystickGetDevicePlayerIndex, PS2_JoystickSetDevicePlayerIndex, PS2_JoystickGetDeviceGUID, diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index a3812fd2db378..eb2b987841b9f 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -121,6 +121,11 @@ static const char *PSP_JoystickGetDevicePath(int index) return NULL; } +static int PSP_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int PSP_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -253,6 +258,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = { PSP_JoystickDetect, PSP_JoystickGetDeviceName, PSP_JoystickGetDevicePath, + PSP_JoystickGetDeviceSteamVirtualGamepadSlot, PSP_JoystickGetDevicePlayerIndex, PSP_JoystickSetDevicePlayerIndex, PSP_JoystickGetDeviceGUID, diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index f32c76fd27db6..6fcdde1a8213b 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -367,6 +367,11 @@ static const char *VIRTUAL_JoystickGetDevicePath(int device_index) return NULL; } +static int VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int VIRTUAL_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -728,6 +733,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = { VIRTUAL_JoystickDetect, VIRTUAL_JoystickGetDeviceName, VIRTUAL_JoystickGetDevicePath, + VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot, VIRTUAL_JoystickGetDevicePlayerIndex, VIRTUAL_JoystickSetDevicePlayerIndex, VIRTUAL_JoystickGetDeviceGUID, diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c index f426d3aa93708..b1acf232745e0 100644 --- a/src/joystick/vita/SDL_sysjoystick.c +++ b/src/joystick/vita/SDL_sysjoystick.c @@ -181,6 +181,11 @@ const char *VITA_JoystickGetDevicePath(int index) return NULL; } +static int VITA_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return -1; +} + static int VITA_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -378,6 +383,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = { VITA_JoystickDetect, VITA_JoystickGetDeviceName, VITA_JoystickGetDevicePath, + VITA_JoystickGetDeviceSteamVirtualGamepadSlot, VITA_JoystickGetDevicePlayerIndex, VITA_JoystickSetDevicePlayerIndex, VITA_JoystickGetDeviceGUID, diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index f19bba85256db..84cdae8104907 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -435,6 +435,17 @@ int SDL_DINPUT_JoystickInit(void) return 0; } +static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path) +{ + int slot = -1; + + if (vendor_id == USB_VENDOR_VALVE && + product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + (void)SDL_sscanf(device_path, "\\\\?\\HID#VID_28DE&PID_11FF&IG_0%d", &slot); + } + return slot; +} + /* helper function for direct input, gets called for each connected joystick */ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext) { @@ -487,10 +498,10 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta pNewJoystick = pNewJoystick->pNext; } - pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData)); + pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData)); CHECK(pNewJoystick); - SDL_zerop(pNewJoystick); + pNewJoystick->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(vendor, product, hidPath); SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path)); SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE)); diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index f4e68b7bc813e..221e15132527b 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -114,6 +114,7 @@ typedef struct SDL_RAWINPUT_Device SDL_JoystickGUID guid; SDL_bool is_xinput; SDL_bool is_xboxone; + int steam_virtual_gamepad_slot; PHIDP_PREPARSED_DATA preparsed_data; HANDLE hDevice; @@ -841,6 +842,19 @@ static SDL_RAWINPUT_Device *RAWINPUT_DeviceFromHandle(HANDLE hDevice) return NULL; } +static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path) +{ + int slot = -1; + + // The format for the raw input device path is documented here: + // https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices + if (vendor_id == USB_VENDOR_VALVE && + product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + (void)SDL_sscanf(device_path, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%*X&%*X&%*X#%d#%*u", &slot); + } + return slot; +} + static void RAWINPUT_AddDevice(HANDLE hDevice) { #define CHECK(expression) \ @@ -883,6 +897,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) device->version = (Uint16)rdi.hid.dwVersionNumber; device->is_xinput = SDL_TRUE; device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id); + device->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(device->vendor_id, device->product_id, dev_name); /* Get HID Top-Level Collection Preparsed Data */ size = 0; @@ -1189,6 +1204,11 @@ static const char *RAWINPUT_JoystickGetDevicePath(int device_index) return RAWINPUT_GetDeviceByIndex(device_index)->path; } +static int RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return RAWINPUT_GetDeviceByIndex(device_index)->steam_virtual_gamepad_slot; +} + static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -2198,6 +2218,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = { RAWINPUT_JoystickDetect, RAWINPUT_JoystickGetDeviceName, RAWINPUT_JoystickGetDevicePath, + RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot, RAWINPUT_JoystickGetDevicePlayerIndex, RAWINPUT_JoystickSetDevicePlayerIndex, RAWINPUT_JoystickGetDeviceGUID, diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 6ffbf8d976e8c..fe48b816fcc9e 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -58,6 +58,7 @@ typedef struct WindowsGamingInputControllerState char *name; SDL_JoystickGUID guid; SDL_JoystickType type; + int steam_virtual_gamepad_slot; } WindowsGamingInputControllerState; typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(PVOID *pCookie); @@ -356,6 +357,34 @@ static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FI return rc; } +static int GetSteamVirtualGamepadSlot(__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller, Uint16 vendor_id, Uint16 product_id) +{ + int slot = -1; + + if (vendor_id == USB_VENDOR_VALVE && + product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + __x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL; + HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2); + if (SUCCEEDED(hr)) { + HSTRING hString; + hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_NonRoamableId(controller2, &hString); + if (SUCCEEDED(hr)) { + PCWSTR string = wgi.WindowsGetStringRawBuffer(hString, NULL); + if (string) { + char *id = WIN_StringToUTF8W(string); + if (id) { + (void)SDL_sscanf(id, "{wgi/nrid/:steam-%*X&%*X&%*X#%d#%*u}", &slot); + SDL_free(id); + } + } + wgi.WindowsDeleteString(hString); + } + __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2); + } + } + return slot; +} + static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e) { HRESULT hr; @@ -464,6 +493,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde state->name = name; state->guid = guid; state->type = type; + state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller); @@ -664,6 +694,11 @@ static const char *WGI_JoystickGetDevicePath(int device_index) return NULL; } +static int WGI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + return wgi.controllers[device_index].steam_virtual_gamepad_slot; +} + static int WGI_JoystickGetDevicePlayerIndex(int device_index) { return -1; @@ -983,6 +1018,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = { WGI_JoystickDetect, WGI_JoystickGetDeviceName, WGI_JoystickGetDevicePath, + WGI_JoystickGetDeviceSteamVirtualGamepadSlot, WGI_JoystickGetDevicePlayerIndex, WGI_JoystickSetDevicePlayerIndex, WGI_JoystickGetDeviceGUID, diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 3ce542493f38a..1476d899a5be9 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -612,6 +612,23 @@ static const char *WINDOWS_JoystickGetDevicePath(int device_index) return device->path; } +static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + JoyStick_DeviceData *device = SYS_Joystick; + int index; + + for (index = device_index; index > 0; index--) { + device = device->pNext; + } + + if (device->bXInputDevice) { + /* The slot for XInput devices can change as controllers are seated */ + return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId); + } else { + return device->steam_virtual_gamepad_slot; + } +} + static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index) { JoyStick_DeviceData *device = SYS_Joystick; @@ -669,7 +686,6 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index) } /* allocate memory for system specific hardware data */ - joystick->instance_id = device->nInstanceID; joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata)); if (!joystick->hwdata) { return -1; @@ -792,6 +808,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = { WINDOWS_JoystickDetect, WINDOWS_JoystickGetDeviceName, WINDOWS_JoystickGetDevicePath, + WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot, WINDOWS_JoystickGetDevicePlayerIndex, WINDOWS_JoystickSetDevicePlayerIndex, WINDOWS_JoystickGetDeviceGUID, diff --git a/src/joystick/windows/SDL_windowsjoystick_c.h b/src/joystick/windows/SDL_windowsjoystick_c.h index 9cd70108ce01a..50c0786bccc1d 100644 --- a/src/joystick/windows/SDL_windowsjoystick_c.h +++ b/src/joystick/windows/SDL_windowsjoystick_c.h @@ -42,6 +42,7 @@ typedef struct JoyStick_DeviceData Uint8 XInputUserId; DIDEVICEINSTANCE dxdevice; char path[MAX_PATH]; + int steam_virtual_gamepad_slot; struct JoyStick_DeviceData *pNext; } JoyStick_DeviceData; diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 0a1baccf874f5..0949fe8030904 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -127,13 +127,31 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; } - *pVID = capabilities.VendorId; - *pPID = capabilities.ProductId; - *pVersion = capabilities.ProductVersion; - + if (pVID) { + *pVID = capabilities.VendorId; + } + if (pPID) { + *pPID = capabilities.ProductId; + } + if (pVersion) { + *pVersion = capabilities.ProductVersion; + } return SDL_TRUE; } +int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid) +{ + XINPUT_CAPABILITIES_EX capabilities; + + if (XINPUTGETCAPABILITIESEX && + XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) == ERROR_SUCCESS && + capabilities.VendorId == USB_VENDOR_VALVE && + capabilities.ProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { + return (int)capabilities.unk2; + } + return -1; +} + static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) { Uint16 vendor = 0; diff --git a/src/joystick/windows/SDL_xinputjoystick_c.h b/src/joystick/windows/SDL_xinputjoystick_c.h index 1ce467cb0576f..88b49c586989d 100644 --- a/src/joystick/windows/SDL_xinputjoystick_c.h +++ b/src/joystick/windows/SDL_xinputjoystick_c.h @@ -36,6 +36,7 @@ extern Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickQuit(void); +extern int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/test/testcontroller.c b/test/testcontroller.c index a18bb0b066228..74acff5f2d9b6 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1292,6 +1292,13 @@ static void DrawGamepadInfo(SDL_Renderer *renderer) SDL_SetRenderDrawColor(renderer, r, g, b, a); } + if (controller->joystick) { + SDL_snprintf(text, sizeof(text), "(%" SDL_PRIu32 ")", SDL_GetJoystickInstanceID(controller->joystick)); + x = (float)SCREEN_WIDTH - (FONT_CHARACTER_SIZE * SDL_strlen(text)) - 8.0f; + y = 8.0f; + SDLTest_DrawString(renderer, x, y, text); + } + if (controller_name && *controller_name) { x = title_area.x + title_area.w / 2 - (FONT_CHARACTER_SIZE * SDL_strlen(controller_name)) / 2; y = title_area.y + title_area.h / 2 - FONT_CHARACTER_SIZE / 2; @@ -1311,6 +1318,14 @@ static void DrawGamepadInfo(SDL_Renderer *renderer) SDLTest_DrawString(renderer, x, y, type); if (display_mode == CONTROLLER_MODE_TESTING) { + Uint64 steam_handle = SDL_GetGamepadSteamHandle(controller->gamepad); + if (steam_handle) { + SDL_snprintf(text, SDL_arraysize(text), "Steam: 0x%.16llx", (unsigned long long)steam_handle); + y = (float)SCREEN_HEIGHT - 2 * (8.0f + FONT_LINE_HEIGHT); + x = (float)SCREEN_WIDTH - 8.0f - (FONT_CHARACTER_SIZE * SDL_strlen(text)); + SDLTest_DrawString(renderer, x, y, text); + } + SDL_snprintf(text, SDL_arraysize(text), "VID: 0x%.4x PID: 0x%.4x", SDL_GetJoystickVendor(controller->joystick), SDL_GetJoystickProduct(controller->joystick)); @@ -1595,6 +1610,10 @@ static void loop(void *arg) HandleGamepadRemapped(event.gdevice.which); break; + case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED: + RefreshControllerName(); + break; + #ifdef VERBOSE_TOUCHPAD case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: From 2c4360ce8f4df20a02f8d68cd4ec68eb19babdac Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Wed, 20 Dec 2023 18:41:23 +0000 Subject: [PATCH 581/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_gamepad.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index d7da172763e17..40df9ca5a09c7 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -761,8 +761,8 @@ extern DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamepad); /** * Get the Steam Input handle of an opened gamepad, if available. * - * Returns an InputHandle_t for the gamepad that can be used with Steam Input API: - * https://partner.steamgames.com/doc/api/ISteamInput + * Returns an InputHandle_t for the gamepad that can be used with Steam Input + * API: https://partner.steamgames.com/doc/api/ISteamInput * * \param gamepad the gamepad object to query. * \returns the gamepad handle, or 0 if unavailable. From 3152b98e8702726170e052ede4d06364540386d0 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Wed, 20 Dec 2023 13:54:29 +0200 Subject: [PATCH 582/725] win32: minor fixup in WIN_UpdateKeymap() Remove unused defines in SDL_windowsevents.c --- src/video/windows/SDL_windowsevents.c | 9 --------- src/video/windows/SDL_windowskeyboard.c | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index c4e9cf86cfba0..3a8c89337f28a 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -51,15 +51,6 @@ /* #define HIGHDPI_DEBUG */ -/* Masks for processing the windows KEYDOWN and KEYUP messages */ -#define REPEATED_KEYMASK (1 << 30) -#define EXTENDED_KEYMASK (1 << 24) - -#define VK_ENTER 10 /* Keypad Enter ... no VKEY defined? */ -#ifndef VK_OEM_NEC_EQUAL -#define VK_OEM_NEC_EQUAL 0x92 -#endif - /* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */ #ifndef WM_XBUTTONDOWN #define WM_XBUTTONDOWN 0x020B diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index f84c1bdc954ca..9c5db83ee1052 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -120,7 +120,9 @@ void WIN_UpdateKeymap(SDL_bool send_event) WIN_ResetDeadKeys(); for (i = 0; i < SDL_arraysize(windows_scancode_table); i++) { - int vk; + Uint8 vk; + Uint16 sc; + /* Make sure this scancode is a valid character scancode */ scancode = windows_scancode_table[i]; if (scancode == SDL_SCANCODE_UNKNOWN) { @@ -133,7 +135,9 @@ void WIN_UpdateKeymap(SDL_bool send_event) continue; } - vk = MapVirtualKey(i, MAPVK_VSC_TO_VK); + /* Unpack the single byte index to make the scan code. */ + sc = MAKEWORD(i & 0x7f, (i & 0x80) ? 0xe0 : 0x00); + vk = LOBYTE(MapVirtualKey(sc, MAPVK_VSC_TO_VK)); if (!vk) { continue; } @@ -147,8 +151,8 @@ void WIN_UpdateKeymap(SDL_bool send_event) BYTE keyboardState[256] = { 0 }; WCHAR buffer[16] = { 0 }; Uint32 *ch = 0; - int result = ToUnicode(vk, i, keyboardState, buffer, 16, 0); - buffer[SDL_abs(result) + 1] = 0; + int result = ToUnicode(vk, sc, keyboardState, buffer, 16, 0); + buffer[SDL_abs(result)] = 0; /* Convert UTF-16 to UTF-32 code points */ ch = (Uint32 *)SDL_iconv_string("UTF-32LE", "UTF-16LE", (const char *)buffer, (SDL_abs(result) + 1) * sizeof(WCHAR)); @@ -196,21 +200,21 @@ void WIN_ResetDeadKeys() */ BYTE keyboardState[256]; WCHAR buffer[16]; - int keycode, scancode, result, i; + int vk, sc, result, i; if (!GetKeyboardState(keyboardState)) { return; } - keycode = VK_SPACE; - scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC); - if (scancode == 0) { + vk = VK_SPACE; + sc = MapVirtualKey(vk, MAPVK_VK_TO_VSC); + if (sc == 0) { /* the keyboard doesn't have this key */ return; } for (i = 0; i < 5; i++) { - result = ToUnicode(keycode, scancode, keyboardState, buffer, 16, 0); + result = ToUnicode(vk, sc, keyboardState, buffer, 16, 0); if (result > 0) { /* success */ return; From 72c366bf3d723c17a8662dc00b9684c1d5dd0ab8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 20 Dec 2023 06:51:59 -0800 Subject: [PATCH 583/725] Fixed whitespace --- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index 688e821691ab3..e27dd2a40f2c2 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -34,31 +34,31 @@ typedef enum { - STEAMDECK_LBUTTON_R2 = 0x00000001, - STEAMDECK_LBUTTON_L2 = 0x00000002, - STEAMDECK_LBUTTON_R = 0x00000004, - STEAMDECK_LBUTTON_L = 0x00000008, - STEAMDECK_LBUTTON_Y = 0x00000010, - STEAMDECK_LBUTTON_B = 0x00000020, - STEAMDECK_LBUTTON_X = 0x00000040, - STEAMDECK_LBUTTON_A = 0x00000080, - STEAMDECK_LBUTTON_DPAD_UP = 0x00000100, - STEAMDECK_LBUTTON_DPAD_RIGHT = 0x00000200, - STEAMDECK_LBUTTON_DPAD_LEFT = 0x00000400, - STEAMDECK_LBUTTON_DPAD_DOWN = 0x00000800, - STEAMDECK_LBUTTON_VIEW = 0x00001000, - STEAMDECK_LBUTTON_STEAM = 0x00002000, - STEAMDECK_LBUTTON_MENU = 0x00004000, - STEAMDECK_LBUTTON_L5 = 0x00008000, - STEAMDECK_LBUTTON_R5 = 0x00010000, - STEAMDECK_LBUTTON_LEFT_PAD = 0x00020000, - STEAMDECK_LBUTTON_RIGHT_PAD = 0x00040000, - STEAMDECK_LBUTTON_L3 = 0x00400000, - STEAMDECK_LBUTTON_R3 = 0x04000000, - - STEAMDECK_HBUTTON_L4 = 0x00000200, - STEAMDECK_HBUTTON_R4 = 0x00000400, - STEAMDECK_HBUTTON_QAM = 0x00040000, + STEAMDECK_LBUTTON_R2 = 0x00000001, + STEAMDECK_LBUTTON_L2 = 0x00000002, + STEAMDECK_LBUTTON_R = 0x00000004, + STEAMDECK_LBUTTON_L = 0x00000008, + STEAMDECK_LBUTTON_Y = 0x00000010, + STEAMDECK_LBUTTON_B = 0x00000020, + STEAMDECK_LBUTTON_X = 0x00000040, + STEAMDECK_LBUTTON_A = 0x00000080, + STEAMDECK_LBUTTON_DPAD_UP = 0x00000100, + STEAMDECK_LBUTTON_DPAD_RIGHT = 0x00000200, + STEAMDECK_LBUTTON_DPAD_LEFT = 0x00000400, + STEAMDECK_LBUTTON_DPAD_DOWN = 0x00000800, + STEAMDECK_LBUTTON_VIEW = 0x00001000, + STEAMDECK_LBUTTON_STEAM = 0x00002000, + STEAMDECK_LBUTTON_MENU = 0x00004000, + STEAMDECK_LBUTTON_L5 = 0x00008000, + STEAMDECK_LBUTTON_R5 = 0x00010000, + STEAMDECK_LBUTTON_LEFT_PAD = 0x00020000, + STEAMDECK_LBUTTON_RIGHT_PAD = 0x00040000, + STEAMDECK_LBUTTON_L3 = 0x00400000, + STEAMDECK_LBUTTON_R3 = 0x04000000, + + STEAMDECK_HBUTTON_L4 = 0x00000200, + STEAMDECK_HBUTTON_R4 = 0x00000400, + STEAMDECK_HBUTTON_QAM = 0x00040000, } SteamDeckButtons; typedef struct From 56f111dffc2828d67fd8e0402b0fe1193c48ce26 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 20 Dec 2023 09:40:09 +0100 Subject: [PATCH 584/725] Fix compilation / same as sdl2-compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit testautomation_platform.c:351:28: error: ‘%s’ directive argument is null [-Werror=format-overflow=] 351 | result = SDL_SetError("%s", testError); | ^~ /home/slvn/release/Release_SDL/sdl2-compat/test/testautomation_platform.c:364:64: error: ‘%s’ directive argument is null [-Werror=format-overflow=] 364 | "SDL_GetError(): expected message '%s', was message: '%s'", --- test/testautomation_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testautomation_platform.c b/test/testautomation_platform.c index dcb379b8763b8..0e1ddd1c53cfd 100644 --- a/test/testautomation_platform.c +++ b/test/testautomation_platform.c @@ -369,7 +369,7 @@ static int platform_testSetErrorEmptyInput(void *arg) static int platform_testSetErrorInvalidInput(void *arg) { int result; - const char *invalidError = NULL; + const char *invalidError = ""; const char *probeError = "Testing"; const char *lastError; size_t len; From 4bb5e1f0f99adcae7585f1d88c355a3a3bcf7470 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 20 Dec 2023 14:15:09 -0800 Subject: [PATCH 585/725] Added migration notes for migrating Steam Input support from SDL2 to SDL3 --- build-scripts/SDL_migration.cocci | 9 +++++++++ build-scripts/rename_api.py | 8 ++++++-- docs/README-migration.md | 2 ++ include/SDL3/SDL_oldnames.h | 8 ++++++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index fb27a66f644d1..0455147f408c7 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -2745,3 +2745,12 @@ expression w, i, s; - SDL_RenderFlush + SDL_FlushRenderer (...) +@@ +@@ +- SDL_CONTROLLERSTEAMHANDLEUPDATED ++ SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED +@@ +@@ +- SDL_GameControllerGetSteamHandle ++ SDL_GetGamepadSteamHandle + (...) diff --git a/build-scripts/rename_api.py b/build-scripts/rename_api.py index fe0ac67854a02..7c02b9e945869 100755 --- a/build-scripts/rename_api.py +++ b/build-scripts/rename_api.py @@ -36,6 +36,10 @@ def main(): if not header.exists(): raise Exception("Couldn't find header %s" % header) + header_name = header.name + if (header.name == "SDL_gamepad.h"): + header_name = "SDL_gamecontroller.h" + header_text = header.read_text() # Replace the symbols in source code @@ -62,8 +66,8 @@ def main(): oldname = args.args[i + 0] newname = args.args[i + 1] - add_symbol_to_oldnames(header.name, oldname, newname) - add_symbol_to_migration(header.name, args.type, oldname, newname) + add_symbol_to_oldnames(header_name, oldname, newname) + add_symbol_to_migration(header_name, args.type, oldname, newname) add_symbol_to_coccinelle(args.type, oldname, newname) i += 2 diff --git a/docs/README-migration.md b/docs/README-migration.md index 3b7a90a2f59a0..f3dfdacdd64bc 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -338,6 +338,7 @@ The following symbols have been renamed: * SDL_CONTROLLERDEVICEREMAPPED => SDL_EVENT_GAMEPAD_REMAPPED * SDL_CONTROLLERDEVICEREMOVED => SDL_EVENT_GAMEPAD_REMOVED * SDL_CONTROLLERSENSORUPDATE => SDL_EVENT_GAMEPAD_SENSOR_UPDATE +* SDL_CONTROLLERSTEAMHANDLEUPDATED => SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED * SDL_CONTROLLERTOUCHPADDOWN => SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN * SDL_CONTROLLERTOUCHPADMOTION => SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION * SDL_CONTROLLERTOUCHPADUP => SDL_EVENT_GAMEPAD_TOUCHPAD_UP @@ -459,6 +460,7 @@ The following functions have been renamed: * SDL_GameControllerGetSensorData() => SDL_GetGamepadSensorData() * SDL_GameControllerGetSensorDataRate() => SDL_GetGamepadSensorDataRate() * SDL_GameControllerGetSerial() => SDL_GetGamepadSerial() +* SDL_GameControllerGetSteamHandle() => SDL_GetGamepadSteamHandle() * SDL_GameControllerGetStringForAxis() => SDL_GetGamepadStringForAxis() * SDL_GameControllerGetStringForButton() => SDL_GetGamepadStringForButton() * SDL_GameControllerGetTouchpadFinger() => SDL_GetGamepadTouchpadFinger() diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index 5e5042d9e4dc4..d0fa5da1843ca 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -83,6 +83,7 @@ #define SDL_CONTROLLERDEVICEREMAPPED SDL_EVENT_GAMEPAD_REMAPPED #define SDL_CONTROLLERDEVICEREMOVED SDL_EVENT_GAMEPAD_REMOVED #define SDL_CONTROLLERSENSORUPDATE SDL_EVENT_GAMEPAD_SENSOR_UPDATE +#define SDL_CONTROLLERSTEAMHANDLEUPDATED SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED #define SDL_CONTROLLERTOUCHPADDOWN SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN #define SDL_CONTROLLERTOUCHPADMOTION SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION #define SDL_CONTROLLERTOUCHPADUP SDL_EVENT_GAMEPAD_TOUCHPAD_UP @@ -147,7 +148,7 @@ #define SDL_WINDOWEVENT_SIZE_CHANGED SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED #define SDL_WINDOWEVENT_TAKE_FOCUS SDL_EVENT_WINDOW_TAKE_FOCUS -/* ##SDL_gamepad.h */ +/* ##SDL_gamecontroller.h */ #define SDL_CONTROLLER_AXIS_INVALID SDL_GAMEPAD_AXIS_INVALID #define SDL_CONTROLLER_AXIS_LEFTX SDL_GAMEPAD_AXIS_LEFTX #define SDL_CONTROLLER_AXIS_LEFTY SDL_GAMEPAD_AXIS_LEFTY @@ -221,6 +222,7 @@ #define SDL_GameControllerGetSensorData SDL_GetGamepadSensorData #define SDL_GameControllerGetSensorDataRate SDL_GetGamepadSensorDataRate #define SDL_GameControllerGetSerial SDL_GetGamepadSerial +#define SDL_GameControllerGetSteamHandle SDL_GetGamepadSteamHandle #define SDL_GameControllerGetStringForAxis SDL_GetGamepadStringForAxis #define SDL_GameControllerGetStringForButton SDL_GetGamepadStringForButton #define SDL_GameControllerGetTouchpadFinger SDL_GetGamepadTouchpadFinger @@ -525,6 +527,7 @@ #define SDL_CONTROLLERDEVICEREMAPPED SDL_CONTROLLERDEVICEREMAPPED_renamed_SDL_EVENT_GAMEPAD_REMAPPED #define SDL_CONTROLLERDEVICEREMOVED SDL_CONTROLLERDEVICEREMOVED_renamed_SDL_EVENT_GAMEPAD_REMOVED #define SDL_CONTROLLERSENSORUPDATE SDL_CONTROLLERSENSORUPDATE_renamed_SDL_EVENT_GAMEPAD_SENSOR_UPDATE +#define SDL_CONTROLLERSTEAMHANDLEUPDATED SDL_CONTROLLERSTEAMHANDLEUPDATED_renamed_SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED #define SDL_CONTROLLERTOUCHPADDOWN SDL_CONTROLLERTOUCHPADDOWN_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN #define SDL_CONTROLLERTOUCHPADMOTION SDL_CONTROLLERTOUCHPADMOTION_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION #define SDL_CONTROLLERTOUCHPADUP SDL_CONTROLLERTOUCHPADUP_renamed_SDL_EVENT_GAMEPAD_TOUCHPAD_UP @@ -589,7 +592,7 @@ #define SDL_WINDOWEVENT_SIZE_CHANGED SDL_WINDOWEVENT_SIZE_CHANGED_renamed_SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED #define SDL_WINDOWEVENT_TAKE_FOCUS SDL_WINDOWEVENT_TAKE_FOCUS_renamed_SDL_EVENT_WINDOW_TAKE_FOCUS -/* ##SDL_gamepad.h */ +/* ##SDL_gamecontroller.h */ #define SDL_CONTROLLER_AXIS_INVALID SDL_CONTROLLER_AXIS_INVALID_renamed_SDL_GAMEPAD_AXIS_INVALID #define SDL_CONTROLLER_AXIS_LEFTX SDL_CONTROLLER_AXIS_LEFTX_renamed_SDL_GAMEPAD_AXIS_LEFTX #define SDL_CONTROLLER_AXIS_LEFTY SDL_CONTROLLER_AXIS_LEFTY_renamed_SDL_GAMEPAD_AXIS_LEFTY @@ -663,6 +666,7 @@ #define SDL_GameControllerGetSensorData SDL_GameControllerGetSensorData_renamed_SDL_GetGamepadSensorData #define SDL_GameControllerGetSensorDataRate SDL_GameControllerGetSensorDataRate_renamed_SDL_GetGamepadSensorDataRate #define SDL_GameControllerGetSerial SDL_GameControllerGetSerial_renamed_SDL_GetGamepadSerial +#define SDL_GameControllerGetSteamHandle SDL_GameControllerGetSteamHandle_renamed_SDL_GetGamepadSteamHandle #define SDL_GameControllerGetStringForAxis SDL_GameControllerGetStringForAxis_renamed_SDL_GetGamepadStringForAxis #define SDL_GameControllerGetStringForButton SDL_GameControllerGetStringForButton_renamed_SDL_GetGamepadStringForButton #define SDL_GameControllerGetTouchpadFinger SDL_GameControllerGetTouchpadFinger_renamed_SDL_GetGamepadTouchpadFinger From 1f1ee6f77c492e17a9691c367110c11529fab3fb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 20 Dec 2023 19:05:20 -0800 Subject: [PATCH 586/725] Use the original manufacturer and product strings for the joystick CRC This allows the most information possible for the CRC string, which is used to differentiate controllers with the same VID/PID. Fixes https://github.com/libsdl-org/SDL/issues/8724 --- src/joystick/SDL_joystick.c | 17 +++++++++------ src/joystick/SDL_joystick_c.h | 2 +- src/joystick/android/SDL_sysjoystick.c | 2 +- src/joystick/apple/SDL_mfijoystick.m | 2 +- src/joystick/bsd/SDL_bsdjoystick.c | 2 +- src/joystick/darwin/SDL_iokitjoystick.c | 2 +- src/joystick/hidapi/SDL_hidapijoystick.c | 21 ++++++++----------- src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 ++ src/joystick/linux/SDL_sysjoystick.c | 2 +- src/joystick/virtual/SDL_virtualjoystick.c | 2 +- src/joystick/windows/SDL_dinputjoystick.c | 4 ++-- src/joystick/windows/SDL_rawinputjoystick.c | 3 +-- .../windows/SDL_windows_gaming_input.c | 2 +- src/joystick/windows/SDL_xinputjoystick.c | 6 ++++-- 14 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index b555449e53fa7..b40f405c952d8 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2606,21 +2606,26 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n return name; } -SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) +SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *vendor_name, const char *product_name, Uint8 driver_signature, Uint8 driver_data) { SDL_JoystickGUID guid; Uint16 *guid16 = (Uint16 *)guid.data; + Uint16 crc = 0; SDL_zero(guid); - if (!name) { - name = ""; + if (vendor_name && *vendor_name && product_name && *product_name) { + SDL_crc16(crc, vendor_name, SDL_strlen(vendor_name)); + SDL_crc16(crc, " ", 1); + SDL_crc16(crc, product_name, SDL_strlen(product_name)); + } else if (product_name) { + SDL_crc16(crc, product_name, SDL_strlen(product_name)); } /* We only need 16 bits for each of these; space them out to fill 128. */ /* Byteswap so devices get same GUID on little/big endian platforms. */ *guid16++ = SDL_SwapLE16(bus); - *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + *guid16++ = SDL_SwapLE16(crc); if (vendor && product) { *guid16++ = SDL_SwapLE16(vendor); @@ -2638,14 +2643,14 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc guid.data[14] = driver_signature; guid.data[15] = driver_data; } - SDL_strlcpy((char *)guid16, name, available_space); + SDL_strlcpy((char *)guid16, product_name, available_space); } return guid; } SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name) { - return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0); + return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, NULL, name, 0, 0); } void SDL_SetJoystickGUIDVendor(SDL_JoystickGUID *guid, Uint16 vendor) diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 636b79ef5f42b..10dd13696a7b6 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -60,7 +60,7 @@ extern SDL_bool SDL_JoysticksOpened(void); extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name); /* Function to create a GUID for a joystick based on the VID/PID and name */ -extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data); +extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *vendor_name, const char *product_name, Uint8 driver_signature, Uint8 driver_data); /* Function to create a GUID for a joystick based on the name, with no VID/PID information */ extern SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name); diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 601053659e6ef..9eeed2384ac48 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -343,7 +343,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v nhats = 0; } - guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, desc, 0, 0); + guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, NULL, desc, 0, 0); /* Update the GUID with capability bits */ { diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 3923e87a0500f..1eb65697af10c 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -659,7 +659,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } else { signature = device->button_mask; } - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); + device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, NULL, name, 'm', subtype); if (SDL_ShouldIgnoreJoystick(name, device->guid)) { return SDL_FALSE; diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 4a04030767594..27276af08bfa7 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -425,7 +425,7 @@ static int MaybeAddDevice(const char *path) struct usb_device_info di; if (ioctl(hw->fd, USB_GET_DEVICEINFO, &di) != -1) { name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product); - guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name, 0, 0); + guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0); #ifdef SDL_JOYSTICK_HIDAPI if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) { diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index f5a7d76516a27..74a588be415c0 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -497,7 +497,7 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) } #endif - pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0); + pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0); pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 7f4558baa2718..ce06c11722673 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -661,7 +661,7 @@ void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name) void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 vendor_id, Uint16 product_id) { /* Don't set the device product ID directly, or we'll constantly re-enumerate this device */ - device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->name, 'h', 0); + device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0); } static void HIDAPI_UpdateJoystickSerial(SDL_HIDAPI_Device *device) @@ -894,18 +894,11 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf /* Need the device name before getting the driver to know whether to ignore this device */ { - char *manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string); - char *product_string = HIDAPI_ConvertString(info->product_string); char *serial_number = HIDAPI_ConvertString(info->serial_number); - device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string); - - if (manufacturer_string) { - SDL_free(manufacturer_string); - } - if (product_string) { - SDL_free(product_string); - } + device->manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string); + device->product_string = HIDAPI_ConvertString(info->product_string); + device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, device->manufacturer_string, device->product_string); if (serial_number && *serial_number) { device->serial = serial_number; @@ -914,6 +907,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf } if (!device->name) { + SDL_free(device->manufacturer_string); + SDL_free(device->product_string); SDL_free(device->serial); SDL_free(device->path); SDL_free(device); @@ -926,7 +921,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf } else { bus = SDL_HARDWARE_BUS_USB; } - device->guid = SDL_CreateJoystickGUID(bus, device->vendor_id, device->product_id, device->version, device->name, 'h', 0); + device->guid = SDL_CreateJoystickGUID(bus, device->vendor_id, device->product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0); device->joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD; device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol); @@ -996,6 +991,8 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device) device->magic = NULL; SDL_DestroyMutex(device->dev_lock); + SDL_free(device->manufacturer_string); + SDL_free(device->product_string); SDL_free(device->serial); SDL_free(device->name); SDL_free(device->path); diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index acca9a5c85bad..74f0b749c6f4d 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -53,6 +53,8 @@ typedef struct SDL_HIDAPI_Device { const void *magic; char *name; + char *manufacturer_string; + char *product_string; char *path; Uint16 vendor_id; Uint16 product_id; diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index aef90cba93771..660887a93a907 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -323,7 +323,7 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version); #endif - *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, name, 0, 0); + *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0); if (SDL_ShouldIgnoreJoystick(name, *guid)) { SDL_free(name); diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 6fcdde1a8213b..89b60d74eaa63 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -203,7 +203,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des } } - hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, name, 'v', (Uint8)hwdata->desc.type); + hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, NULL, name, 'v', (Uint8)hwdata->desc.type); /* Allocate fields for different control-types */ if (hwdata->desc.naxes > 0) { diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index 84cdae8104907..bc79a97736deb 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -509,9 +509,9 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta CHECK(pNewJoystick->joystickname); if (vendor && product) { - pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 0, 0); + pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 0, 0); } else { - pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, pNewJoystick->joystickname, 0, 0); + pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, NULL, name, 0, 0); } CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)); diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 221e15132527b..9c21352370b4b 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -922,6 +922,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) } device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string); + device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, manufacturer_string, product_string, 'r', 0); if (manufacturer_string) { SDL_free(manufacturer_string); @@ -931,8 +932,6 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) } } - device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'r', 0); - device->path = SDL_strdup(dev_name); CloseHandle(hFile); diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index fe48b816fcc9e..05efad4538e8d 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -473,7 +473,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde type = GetGameControllerType(game_controller); } - guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type); + guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type); if (SDL_ShouldIgnoreJoystick(name, guid)) { ignore_joystick = SDL_TRUE; diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 0949fe8030904..0e00de57985a0 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -154,6 +154,7 @@ int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid) static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) { + const char *name = NULL; Uint16 vendor = 0; Uint16 product = 0; Uint16 version = 0; @@ -205,16 +206,17 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC return; /* better luck next time? */ } + name = GetXInputName(userid, SubType); GetXInputDeviceInfo(userid, &vendor, &product, &version); pNewJoystick->bXInputDevice = SDL_TRUE; - pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType)); + pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name); if (!pNewJoystick->joystickname) { SDL_free(pNewJoystick); return; /* better luck next time? */ } (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%u", userid); if (!SDL_XInputUseOldJoystickMapping()) { - pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 'x', SubType); + pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 'x', SubType); } pNewJoystick->SubType = SubType; pNewJoystick->XInputUserId = userid; From f72d6a7fd9cd7c0a4aee3961be2a5497e1957e75 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 20 Dec 2023 17:33:46 -0800 Subject: [PATCH 587/725] Use more verbose names for properties, to match upcoming public property names --- src/render/SDL_render.c | 8 ++++---- src/video/SDL_video.c | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index f302440ffdede..7344d95a6e34a 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -43,7 +43,7 @@ this should probably be removed at some point in the future. --ryan. */ #define DONT_DRAW_WHILE_HIDDEN 0 #endif -#define SDL_WINDOWRENDERDATA "SDL.internal.window.renderer" +#define SDL_PROPERTY_WINDOW_RENDERER "SDL.internal.window.renderer" #define CHECK_RENDERER_MAGIC(renderer, retval) \ if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \ @@ -916,7 +916,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) renderer->hidden = SDL_FALSE; } - SDL_SetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, renderer); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, renderer); SDL_SetRenderViewport(renderer, NULL); @@ -999,7 +999,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) SDL_Renderer *SDL_GetRenderer(SDL_Window *window) { - return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, NULL); + return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, NULL); } SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) @@ -4139,7 +4139,7 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer->vertex_data); if (renderer->window) { - SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_WINDOWRENDERDATA); + SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_RENDERER); } /* It's no longer magical... */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 6e4d45f32b133..70221a29ceb65 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -195,7 +195,7 @@ static void SDL_SyncIfRequired(SDL_Window *window) /* Support for framebuffer emulation using an accelerated renderer */ -#define SDL_WINDOWTEXTUREDATA "SDL.internal.window.texturedata" +#define SDL_PROPERTY_WINDOW_TEXTUREDATA "SDL.internal.window.texturedata" typedef struct { @@ -239,7 +239,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U { SDL_RendererInfo info; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA, NULL); + SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_PROPERTY_WINDOW_TEXTUREDATA, NULL); const SDL_bool transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE; int i; int w, h; @@ -292,7 +292,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_DestroyRenderer(renderer); return -1; } - SDL_SetPropertyWithCleanup(props, SDL_WINDOWTEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); + SDL_SetPropertyWithCleanup(props, SDL_PROPERTY_WINDOW_TEXTUREDATA, data, SDL_CleanupWindowTextureData, NULL); data->renderer = renderer; } else { @@ -324,7 +324,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U SDL_TEXTUREACCESS_STREAMING, w, h); if (!data->texture) { - /* codechecker_false_positive [Malloc] Static analyzer doesn't realize allocated `data` is saved to SDL_WINDOWTEXTUREDATA and not leaked here. */ + /* codechecker_false_positive [Malloc] Static analyzer doesn't realize allocated `data` is saved to SDL_PROPERTY_WINDOW_TEXTUREDATA and not leaked here. */ return -1; /* NOLINT(clang-analyzer-unix.Malloc) */ } @@ -362,7 +362,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, SDL_GetWindowSizeInPixels(window, &w, &h); - data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_TEXTUREDATA, NULL); if (!data || !data->texture) { return SDL_SetError("No window texture data"); } @@ -387,14 +387,14 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, static void SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window *window) { - SDL_ClearProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA); + SDL_ClearProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_TEXTUREDATA); } int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync) { SDL_WindowTextureData *data; - data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL); + data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_TEXTUREDATA, NULL); if (!data) { return -1; } From 2ad50e96754f8ef40a9e1139648501cbeedec476 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 20 Dec 2023 17:35:43 -0800 Subject: [PATCH 588/725] Make the SDL3 surface ABI compatible with SDL2 We'll use properties for new data associated with a surface, which lets us preserve ABI compatibility with SDL2 and any surfaces created by applications and passed in to SDL functions. --- include/SDL3/SDL_surface.h | 18 +++++++------ src/video/SDL_surface.c | 52 ++++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index fcc8c1d2cf5ce..c6a3459b9b0e8 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -50,11 +50,12 @@ extern "C" { * Used internally (read-only). */ /* @{ */ -#define SDL_SWSURFACE 0 /**< Just here for compatibility */ -#define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ -#define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ -#define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ -#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ +#define SDL_SWSURFACE 0 /**< Just here for compatibility */ +#define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ +#define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ +#define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ +#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ +#define SDL_SURFACE_USES_PROPERTIES 0x00000010 /**< Surface uses properties */ /* @} *//* Surface flags */ /** @@ -104,7 +105,10 @@ typedef struct SDL_Surface void *pixels; /**< Read-write */ /** Application data associated with the surface */ - SDL_PropertiesID props; /**< Read-write */ + union { + void *reserved; /**< For ABI compatibility only, do not use */ + SDL_PropertiesID props; /**< Read-only */ + }; /** information needed for surfaces requiring locks */ int locked; /**< Read-only */ @@ -115,8 +119,6 @@ typedef struct SDL_Surface /** clipping information */ SDL_Rect clip_rect; /**< Read-only */ - SDL_ScaleMode scaleMode; /**< The scale mode */ - /** info for fast blit mapping to other surfaces */ SDL_BlitMap *map; /**< Private */ diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index a86f8e068af6b..0e9cd40ec55a0 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -257,8 +257,16 @@ SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface) return 0; } - if (surface->props == 0) { + if (!(surface->flags & SDL_SURFACE_USES_PROPERTIES)) { + if (surface->reserved != NULL) { + SDL_SetError("Surface has userdata, incompatible with properties"); + return 0; + } + surface->props = SDL_CreateProperties(); + if (surface->props) { + surface->flags |= SDL_SURFACE_USES_PROPERTIES; + } } return surface->props; } @@ -776,7 +784,12 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, int SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) { - return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, src->scaleMode); + SDL_ScaleMode scale_mode = SDL_SCALEMODE_NEAREST; + + if (SDL_GetSurfaceScaleMode(src, &scale_mode) < 0) { + return -1; + } + return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, scale_mode); } int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, @@ -944,7 +957,12 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect) { - return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, src->scaleMode); + SDL_ScaleMode scale_mode = SDL_SCALEMODE_NEAREST; + + if (SDL_GetSurfaceScaleMode(src, &scale_mode) < 0) { + return -1; + } + return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, scale_mode); } int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, @@ -1051,8 +1069,12 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr } } +#define SDL_PROPERTY_SURFACE_SCALEMODE "SDL.internal.surface.scale_mode" + int SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode) { + SDL_PropertiesID props; + if (!surface) { return SDL_InvalidParamError("surface"); } @@ -1061,13 +1083,15 @@ int SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode) return SDL_InvalidParamError("scaleMode"); } - if (scaleMode == SDL_SCALEMODE_NEAREST) { - surface->scaleMode = SDL_SCALEMODE_NEAREST; - } else { - surface->scaleMode = SDL_SCALEMODE_LINEAR; + props = SDL_GetSurfaceProperties(surface); + if (!props) { + return -1; } - return 0; + if (scaleMode != SDL_SCALEMODE_NEAREST) { + scaleMode = SDL_SCALEMODE_LINEAR; + } + return SDL_SetNumberProperty(props, SDL_PROPERTY_SURFACE_SCALEMODE, scaleMode); } int SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode) @@ -1077,9 +1101,12 @@ int SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode) } if (scaleMode) { - *scaleMode = surface->scaleMode; + if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { + *scaleMode = (SDL_ScaleMode)SDL_GetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROPERTY_SURFACE_SCALEMODE, SDL_SCALEMODE_NEAREST); + } else { + *scaleMode = SDL_SCALEMODE_NEAREST; + } } - return 0; } @@ -1595,7 +1622,10 @@ void SDL_DestroySurface(SDL_Surface *surface) return; } - SDL_DestroyProperties(surface->props); + if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { + SDL_DestroyProperties(surface->props); + } + SDL_InvalidateMap(surface->map); SDL_InvalidateAllBlitMap(surface); From a2e05480d63cac530269c846422e7de3b44e830f Mon Sep 17 00:00:00 2001 From: Lukas Senionis Date: Thu, 21 Dec 2023 15:11:32 +0200 Subject: [PATCH 589/725] Use crc16 return value when calculating GUID Fixes the regression introduced by 919cd56b20c59249bdde3bb005aeeb8f6550f3e3 --- src/joystick/SDL_joystick.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index b40f405c952d8..1948c3a942287 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2615,11 +2615,11 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc SDL_zero(guid); if (vendor_name && *vendor_name && product_name && *product_name) { - SDL_crc16(crc, vendor_name, SDL_strlen(vendor_name)); - SDL_crc16(crc, " ", 1); - SDL_crc16(crc, product_name, SDL_strlen(product_name)); + crc = SDL_crc16(crc, vendor_name, SDL_strlen(vendor_name)); + crc = SDL_crc16(crc, " ", 1); + crc = SDL_crc16(crc, product_name, SDL_strlen(product_name)); } else if (product_name) { - SDL_crc16(crc, product_name, SDL_strlen(product_name)); + crc = SDL_crc16(crc, product_name, SDL_strlen(product_name)); } /* We only need 16 bits for each of these; space them out to fill 128. */ From cb90653695aadb193f163ddde9a684b333298d14 Mon Sep 17 00:00:00 2001 From: Dimitriy Ryazantcev Date: Thu, 21 Dec 2023 14:47:56 +0200 Subject: [PATCH 590/725] win32: use USER_DEFAULT_SCREEN_DPI instead of explicit 96 value --- src/video/windows/SDL_windowsevents.c | 2 +- src/video/windows/SDL_windowsmodes.c | 4 ++-- src/video/windows/SDL_windowsmouse.c | 2 +- src/video/windows/SDL_windowswindow.c | 6 ++---- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 3a8c89337f28a..89e05cd502546 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -948,7 +948,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); UINT dpi; - dpi = 96; + dpi = USER_DEFAULT_SCREEN_DPI; size.top = 0; size.left = 0; size.bottom = h; diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index 1845c452bd4ff..8f01bf0060ab1 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -186,9 +186,9 @@ static float WIN_GetContentScale(SDL_VideoDevice *_this, HMONITOR hMonitor) } if (dpi == 0) { /* Safe default */ - dpi = 96; + dpi = USER_DEFAULT_SCREEN_DPI; } - return dpi / 96.0f; + return dpi / (float)USER_DEFAULT_SCREEN_DPI; } static SDL_bool WIN_GetDisplayMode(SDL_VideoDevice *_this, HMONITOR hMonitor, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *mode, SDL_DisplayOrientation *natural_orientation, SDL_DisplayOrientation *current_orientation) diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index a037407c925fd..9f0e6d2dccda6 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -508,7 +508,7 @@ static void WIN_SetEnhancedMouseScale(int mouse_speed) float xpoints[5]; float ypoints[5]; float scale_points[10]; - const int dpi = 96; // FIXME, how do we handle different monitors with different DPI? + const int dpi = USER_DEFAULT_SCREEN_DPI; // FIXME, how do we handle different monitors with different DPI? const float display_factor = 3.5f * (150.0f / dpi); if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\Mouse", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 07f6c9a2f00f2..78f6aeaff00fd 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -158,9 +158,6 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m { SDL_VideoData *videodata = SDL_GetVideoDevice() ? SDL_GetVideoDevice()->driverdata : NULL; RECT rect; -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) - UINT frame_dpi; -#endif /* Client rect, in points */ switch (rect_type) { @@ -202,8 +199,9 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of AdjustWindowRectEx. */ if (videodata) { + UINT frame_dpi; SDL_WindowData *data = window->driverdata; - frame_dpi = (data && videodata->GetDpiForWindow) ? videodata->GetDpiForWindow(data->hwnd) : 96; + frame_dpi = (data && videodata->GetDpiForWindow) ? videodata->GetDpiForWindow(data->hwnd) : USER_DEFAULT_SCREEN_DPI; if (videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, frame_dpi) == 0) { return WIN_SetError("AdjustWindowRectExForDpi()"); } From 57fcb9044c3ec12c2ac6a68f7172ea1b8e8fbc69 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 20 Dec 2023 17:45:07 -0500 Subject: [PATCH 591/725] video: Remove more assumptions about window state in the video layer Don't check the fullscreen flag when toggling resizable, bordered, always on top, minimum size and maximum size, as the flag doesn't reflect pending async changes that may be in progress. These properties can be made to be safely toggled while the window is in fullscreen mode and applied when returning to windowed mode, which ensures that requested window settings aren't lost if calling these functions while async fullscreen changes are in flight. --- src/video/SDL_video.c | 104 ++++++++-------- src/video/cocoa/SDL_cocoawindow.m | 26 ++-- src/video/wayland/SDL_waylandwindow.c | 18 ++- src/video/x11/SDL_x11events.c | 17 ++- src/video/x11/SDL_x11window.c | 163 +++++++++++++------------- src/video/x11/SDL_x11window.h | 2 + 6 files changed, 179 insertions(+), 151 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 70221a29ceb65..cbab78e823423 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2548,18 +2548,18 @@ int SDL_SetWindowBordered(SDL_Window *window, SDL_bool bordered) { CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const SDL_bool want = (bordered != SDL_FALSE); /* normalize the flag. */ - const SDL_bool have = !(window->flags & SDL_WINDOW_BORDERLESS); - if ((want != have) && (_this->SetWindowBordered)) { - if (want) { - window->flags &= ~SDL_WINDOW_BORDERLESS; - } else { - window->flags |= SDL_WINDOW_BORDERLESS; - } - _this->SetWindowBordered(_this, window, want); + + const SDL_bool want = (bordered != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = !(window->flags & SDL_WINDOW_BORDERLESS); + if ((want != have) && (_this->SetWindowBordered)) { + if (want) { + window->flags &= ~SDL_WINDOW_BORDERLESS; + } else { + window->flags |= SDL_WINDOW_BORDERLESS; } + _this->SetWindowBordered(_this, window, want); } + return 0; } @@ -2567,19 +2567,19 @@ int SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable) { CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const SDL_bool want = (resizable != SDL_FALSE); /* normalize the flag. */ - const SDL_bool have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0); - if ((want != have) && (_this->SetWindowResizable)) { - if (want) { - window->flags |= SDL_WINDOW_RESIZABLE; - } else { - window->flags &= ~SDL_WINDOW_RESIZABLE; - SDL_copyp(&window->windowed, &window->floating); - } - _this->SetWindowResizable(_this, window, want); + + const SDL_bool want = (resizable != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0); + if ((want != have) && (_this->SetWindowResizable)) { + if (want) { + window->flags |= SDL_WINDOW_RESIZABLE; + } else { + window->flags &= ~SDL_WINDOW_RESIZABLE; + SDL_copyp(&window->windowed, &window->floating); } + _this->SetWindowResizable(_this, window, want); } + return 0; } @@ -2587,18 +2587,18 @@ int SDL_SetWindowAlwaysOnTop(SDL_Window *window, SDL_bool on_top) { CHECK_WINDOW_MAGIC(window, -1); CHECK_WINDOW_NOT_POPUP(window, -1); - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - const SDL_bool want = (on_top != SDL_FALSE); /* normalize the flag. */ - const SDL_bool have = ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0); - if ((want != have) && (_this->SetWindowAlwaysOnTop)) { - if (want) { - window->flags |= SDL_WINDOW_ALWAYS_ON_TOP; - } else { - window->flags &= ~SDL_WINDOW_ALWAYS_ON_TOP; - } - _this->SetWindowAlwaysOnTop(_this, window, want); + + const SDL_bool want = (on_top != SDL_FALSE); /* normalize the flag. */ + const SDL_bool have = ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0); + if ((want != have) && (_this->SetWindowAlwaysOnTop)) { + if (want) { + window->flags |= SDL_WINDOW_ALWAYS_ON_TOP; + } else { + window->flags &= ~SDL_WINDOW_ALWAYS_ON_TOP; } + _this->SetWindowAlwaysOnTop(_this, window, want); } + return 0; } @@ -2716,6 +2716,8 @@ int SDL_GetWindowSizeInPixels(SDL_Window *window, int *w, int *h) int SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h) { + int w, h; + CHECK_WINDOW_MAGIC(window, -1); if (min_w < 0) { return SDL_InvalidParamError("min_w"); @@ -2732,19 +2734,14 @@ int SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h) window->min_w = min_w; window->min_h = min_h; - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - int w, h; - - if (_this->SetWindowMinimumSize) { - _this->SetWindowMinimumSize(_this, window); - } - - /* Ensure that window is not smaller than minimal size */ - w = window->min_w ? SDL_max(window->floating.w, window->min_w) : window->floating.w; - h = window->min_h ? SDL_max(window->floating.h, window->min_h) : window->floating.h; - return SDL_SetWindowSize(window, w, h); + if (_this->SetWindowMinimumSize) { + _this->SetWindowMinimumSize(_this, window); } - return 0; + + /* Ensure that window is not smaller than minimal size */ + w = window->min_w ? SDL_max(window->floating.w, window->min_w) : window->floating.w; + h = window->min_h ? SDL_max(window->floating.h, window->min_h) : window->floating.h; + return SDL_SetWindowSize(window, w, h); } int SDL_GetWindowMinimumSize(SDL_Window *window, int *min_w, int *min_h) @@ -2761,6 +2758,8 @@ int SDL_GetWindowMinimumSize(SDL_Window *window, int *min_w, int *min_h) int SDL_SetWindowMaximumSize(SDL_Window *window, int max_w, int max_h) { + int w, h; + CHECK_WINDOW_MAGIC(window, -1); if (max_w < 0) { return SDL_InvalidParamError("max_w"); @@ -2776,19 +2775,14 @@ int SDL_SetWindowMaximumSize(SDL_Window *window, int max_w, int max_h) window->max_w = max_w; window->max_h = max_h; - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - int w, h; - - if (_this->SetWindowMaximumSize) { - _this->SetWindowMaximumSize(_this, window); - } - - /* Ensure that window is not larger than maximal size */ - w = window->max_w ? SDL_min(window->floating.w, window->max_w) : window->floating.w; - h = window->max_h ? SDL_min(window->floating.h, window->max_h) : window->floating.h; - return SDL_SetWindowSize(window, w, h); + if (_this->SetWindowMaximumSize) { + _this->SetWindowMaximumSize(_this, window); } - return 0; + + /* Ensure that window is not larger than maximal size */ + w = window->max_w ? SDL_min(window->floating.w, window->max_w) : window->floating.w; + h = window->max_h ? SDL_min(window->floating.h, window->max_h) : window->floating.h; + return SDL_SetWindowSize(window, w, h); } int SDL_GetWindowMaximumSize(SDL_Window *window, int *max_w, int *max_h) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index a2482cf8a3808..75df071db839a 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2440,9 +2440,14 @@ void Cocoa_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered) { @autoreleasepool { - if (SetWindowStyle(window, GetWindowStyle(window))) { - if (bordered) { - Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */ + SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; + + /* If the window is in or transitioning to/from fullscreen, this will be set on leave. */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN) && ![data.listener isInFullscreenSpaceTransition]) { + if (SetWindowStyle(window, GetWindowStyle(window))) { + if (bordered) { + Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */ + } } } } @@ -2476,11 +2481,16 @@ void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bo void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top) { @autoreleasepool { - NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; - if (on_top) { - [nswindow setLevel:NSFloatingWindowLevel]; - } else { - [nswindow setLevel:kCGNormalWindowLevel]; + SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata; + NSWindow *nswindow = data.nswindow; + + /* If the window is in or transitioning to/from fullscreen, this will be set on leave. */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN) && ![data.listener isInFullscreenSpaceTransition]) { + if (on_top) { + [nswindow setLevel:NSFloatingWindowLevel]; + } else { + [nswindow setLevel:kCGNormalWindowLevel]; + } } } } diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 84bf2fb4fec49..a43766c43e910 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -741,8 +741,13 @@ static void handle_configure_xdg_toplevel(void *data, /* If we're a fixed-size window, we know our size for sure. * Always assume the configure is wrong. */ - width = window->windowed.w; - height = window->windowed.h; + if (floating) { + width = window->floating.w; + height = window->floating.h; + } else { + width = window->windowed.w; + height = window->windowed.h; + } } /* The content limits are only a hint, which the compositor is free to ignore, @@ -1007,8 +1012,13 @@ static void decoration_frame_configure(struct libdecor_frame *frame, } } else { if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - width = window->windowed.w; - height = window->windowed.h; + if (floating) { + width = window->floating.w; + height = window->floating.h; + } else { + width = window->windowed.w; + height = window->windowed.h; + } OverrideLibdecorLimits(window); } else { diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 26f5e060a519f..c5072eab6dcce 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1640,7 +1640,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); if (commit) { /* This was initiated by the compositor, or the mode was changed between the request and the window - * becoming fullscreen. Switch to the application requested mode if necessary. + * becoming fullscreen. Switch to the application requested mode if necessary. */ SDL_copyp(&data->window->current_fullscreen_mode, &data->window->requested_fullscreen_mode); SDL_UpdateFullscreenMode(data->window, SDL_TRUE, SDL_TRUE); @@ -1650,7 +1650,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } } else { SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); - SDL_UpdateFullscreenMode(data->window, SDL_FALSE, SDL_TRUE); + SDL_UpdateFullscreenMode(data->window, SDL_FALSE, SDL_FALSE); + + /* Need to restore or update any limits changed while the window was fullscreen. */ + X11_SetWindowMinMax(data->window, !!(flags & SDL_WINDOW_MAXIMIZED)); } if ((flags & SDL_WINDOW_FULLSCREEN) && @@ -1675,6 +1678,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) } else { data->disable_size_position_events = SDL_FALSE; data->previous_borders_nonzero = SDL_FALSE; + + if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { + data->toggle_borders = SDL_FALSE; + X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); + } } } if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { @@ -1737,6 +1745,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top); X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } + + if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { + data->toggle_borders = SDL_FALSE; + X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); + } } } } break; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 24aa08c0904d6..3ca21df70e3c7 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -1048,50 +1048,58 @@ static void X11_SetWMNormalHints(SDL_VideoDevice *_this, SDL_Window *window, XSi X11_XRaiseWindow(display, data->xwindow); } -void X11_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window) +void X11_SetWindowMinMax(SDL_Window *window, SDL_bool use_current) { SDL_WindowData *data = window->driverdata; Display *display = data->videodata->display; + XSizeHints *sizehints = X11_XAllocSizeHints(); + long hint_flags = 0; - if (window->flags & SDL_WINDOW_RESIZABLE) { - XSizeHints *sizehints = X11_XAllocSizeHints(); - long userhints; - - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); + X11_XGetWMNormalHints(display, data->xwindow, sizehints, &hint_flags); + sizehints->flags &= ~(PMinSize | PMaxSize); - sizehints->min_width = window->min_w; - sizehints->min_height = window->min_h; - sizehints->flags |= PMinSize; + if (data->window->flags & SDL_WINDOW_RESIZABLE) { + if (data->window->min_w || data->window->min_h) { + sizehints->flags |= PMinSize; + sizehints->min_width = data->window->min_w; + sizehints->min_height = data->window->min_h; + } + if (data->window->max_w || data->window->max_h) { + sizehints->flags |= PMaxSize; + sizehints->max_width = data->window->max_w; + sizehints->max_height = data->window->max_h; + } + } else { + /* Set the min/max to the same values to make the window non-resizable */ + sizehints->flags |= PMinSize | PMaxSize; + sizehints->min_width = sizehints->max_width = use_current ? data->window->floating.w : window->windowed.w; + sizehints->min_height = sizehints->max_height = use_current ? data->window->floating.h : window->windowed.h; + } - X11_SetWMNormalHints(_this, window, sizehints); + X11_XSetWMNormalHints(display, data->xwindow, sizehints); + X11_XFree(sizehints); +} - X11_XFree(sizehints); +void X11_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window) +{ + if (window->driverdata->pending_operation & X11_PENDING_OP_FULLSCREEN) { + X11_SyncWindow(_this, window); } - X11_XFlush(display); + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + X11_SetWindowMinMax(window, SDL_TRUE); + } } void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_WindowData *data = window->driverdata; - Display *display = data->videodata->display; - - if (window->flags & SDL_WINDOW_RESIZABLE) { - XSizeHints *sizehints = X11_XAllocSizeHints(); - long userhints; - - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); - - sizehints->max_width = window->max_w; - sizehints->max_height = window->max_h; - sizehints->flags |= PMaxSize; - - X11_SetWMNormalHints(_this, window, sizehints); - - X11_XFree(sizehints); + if (window->driverdata->pending_operation & X11_PENDING_OP_FULLSCREEN) { + X11_SyncWindow(_this, window); } - X11_XFlush(display); + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + X11_SetWindowMinMax(window, SDL_TRUE); + } } void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) @@ -1198,61 +1206,60 @@ void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool Display *display = data->videodata->display; XEvent event; - SetWindowBordered(display, displaydata->screen, data->xwindow, bordered); - X11_XFlush(display); + if (data->pending_operation & X11_PENDING_OP_FULLSCREEN) { + X11_SyncWindow(_this, window); + } - if (visible) { - XWindowAttributes attr; - do { - X11_XSync(display, False); - X11_XGetWindowAttributes(display, data->xwindow, &attr); - } while (attr.map_state != IsViewable); + /* If the window is fullscreen, the resize capability will be set/cleared when it is returned to windowed mode. */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + SetWindowBordered(display, displaydata->screen, data->xwindow, bordered); + X11_XFlush(display); + + if (visible) { + XWindowAttributes attr; + do { + X11_XSync(display, False); + X11_XGetWindowAttributes(display, data->xwindow, &attr); + } while (attr.map_state != IsViewable); - if (focused) { - X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime); + if (focused) { + X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime); + } } - } - /* make sure these don't make it to the real event queue if they fired here. */ - X11_XSync(display, False); - X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); - X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); + /* make sure these don't make it to the real event queue if they fired here. */ + X11_XSync(display, False); + X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); + X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); - /* Make sure the window manager didn't resize our window for the difference. */ - X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); - X11_XSync(display, False); + /* Turning the borders off doesn't send an extent event, so they must be cleared here. */ + if (bordered) { + X11_GetBorderValues(data); + } else { + data->border_top = data->border_left = data->border_bottom = data->border_right = 0; + } + + /* Make sure the window manager didn't resize our window for the difference. */ + X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); + X11_XSync(display, False); + } else { + /* If fullscreen, set a flag to toggle the borders when returning to windowed mode. */ + data->toggle_borders = SDL_TRUE; + } } void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable) { SDL_WindowData *data = window->driverdata; - Display *display = data->videodata->display; - - XSizeHints *sizehints = X11_XAllocSizeHints(); - long userhints; - - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); - if (resizable) { - /* FIXME: Is there a better way to get max window size from X? -flibit */ - const int maxsize = 0x7FFFFFFF; - sizehints->min_width = window->min_w; - sizehints->min_height = window->min_h; - sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w; - sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h; - } else { - sizehints->min_width = window->w; - sizehints->min_height = window->h; - sizehints->max_width = window->w; - sizehints->max_height = window->h; + if (data->pending_operation & X11_PENDING_OP_FULLSCREEN) { + X11_SyncWindow(_this, window); } - sizehints->flags |= PMinSize | PMaxSize; - X11_SetWMNormalHints(_this, window, sizehints); - - X11_XFree(sizehints); - - X11_XFlush(display); + /* If the window is fullscreen, the resize capability will be set/cleared when it is returned to windowed mode. */ + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + X11_SetWindowMinMax(window, SDL_TRUE); + } } void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top) @@ -1528,22 +1535,14 @@ static int X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *wind return 0; } - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + if (fullscreen && !(window->flags & SDL_WINDOW_RESIZABLE)) { /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we can be resized to the fullscreen resolution (or reset so we're not resizable again) */ XSizeHints *sizehints = X11_XAllocSizeHints(); long flags = 0; X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags); - /* set the resize flags on */ - if (fullscreen) { - /* we are going fullscreen so turn the flags off */ - sizehints->flags &= ~(PMinSize | PMaxSize); - } else { - /* Reset the min/max width height to make the window non-resizable again */ - sizehints->flags |= PMinSize | PMaxSize; - sizehints->min_width = sizehints->max_width = window->windowed.w; - sizehints->min_height = sizehints->max_height = window->windowed.h; - } + /* we are going fullscreen so turn the flags off */ + sizehints->flags &= ~(PMinSize | PMaxSize); X11_XSetWMNormalHints(display, data->xwindow, sizehints); X11_XFree(sizehints); } diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 01fd049995a96..5d1926187baa2 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -96,6 +96,7 @@ struct SDL_WindowData SDL_bool window_was_maximized; SDL_bool disable_size_position_events; SDL_bool previous_borders_nonzero; + SDL_bool toggle_borders; SDL_HitTestResult hit_test_result; }; @@ -137,5 +138,6 @@ extern int X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SD int SDL_X11_SetWindowTitle(Display *display, Window xwindow, char *title); void X11_UpdateWindowPosition(SDL_Window *window, SDL_bool use_current_position); +void X11_SetWindowMinMax(SDL_Window *window, SDL_bool use_current); #endif /* SDL_x11window_h_ */ From e66896406d6cf44d1770e6e11d5275c7c635dfa1 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 21 Dec 2023 11:47:16 -0500 Subject: [PATCH 592/725] cocoa: Set appropriate flags on fullscreen spaces windows Don't mark fullscreen windows as having a title bar if the window is borderless, or it can end up in a weird, pseudo-decorated state when leaving fullscreen if the borders were toggled back on while the window was fullscreen. Setting the window styling when about to leave fullscreen caused issues with this as well and is no longer needed, as it is ensured that the window's resizable state won't change while in a fullscreen space, or in a transition period. --- src/video/cocoa/SDL_cocoawindow.m | 36 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 75df071db839a..79f2c2843a853 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1140,8 +1140,19 @@ - (void)windowDidChangeScreen:(NSNotification *)aNotification - (void)windowWillEnterFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data.window; + NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; - SetWindowStyle(window, (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable)); + /* Don't set the titled flag on a fullscreen window if the windowed-mode window + * is borderless, or the window can wind up in a weird, pseudo-decorated state + * when leaving fullscreen if the border flag was toggled on. + */ + if (!(window->flags & SDL_WINDOW_BORDERLESS)) { + flags |= NSWindowStyleMaskTitled; + } else { + flags |= NSWindowStyleMaskBorderless; + } + + SetWindowStyle(window, flags); _data.was_zoomed = !!(window->flags & SDL_WINDOW_MAXIMIZED); @@ -1205,27 +1216,24 @@ - (void)windowWillExitFullScreen:(NSNotification *)aNotification isFullscreenSpace = NO; inFullscreenTransition = YES; - - /* As of macOS 10.11, the window seems to need to be resizable when exiting - a Space, in order for it to resize back to its windowed-mode size. - As of macOS 10.15, the window decorations can go missing sometimes after - certain fullscreen-desktop->exlusive-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) | NSWindowStyleMaskResizable); } - (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data.window; + NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; if (window->is_destroying) { return; } - SetWindowStyle(window, (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable)); + if (!(window->flags & SDL_WINDOW_BORDERLESS)) { + flags |= NSWindowStyleMaskTitled; + } else { + flags |= NSWindowStyleMaskBorderless; + } + + SetWindowStyle(window, flags); isFullscreenSpace = YES; inFullscreenTransition = NO; @@ -2456,7 +2464,7 @@ void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_boo void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable) { @autoreleasepool { - /* Don't set this if we're in a space! + /* Don't set this if we're in or transitioning to/from a space! * The window will get permanently stuck if resizable is false. * -flibit */ @@ -2464,7 +2472,7 @@ void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bo Cocoa_WindowListener *listener = data.listener; NSWindow *nswindow = data.nswindow; SDL_CocoaVideoData *videodata = data.videodata; - if (![listener isInFullscreenSpace]) { + if (![listener isInFullscreenSpace] && ![listener isInFullscreenSpaceTransition]) { SetWindowStyle(window, GetWindowStyle(window)); } if (videodata.allow_spaces) { From 5dba04b29bc25d11190fdc65bf0023d5480e1082 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 22 Dec 2023 10:28:17 +0100 Subject: [PATCH 593/725] Remove SDL_{Set,Get}SurfaceScale(). Add Scale parameter to SDL_BlitSurfaceScaled() and SDL_BlitSurfaceScaledUnchecked() (see #8732) --- WhatsNew.txt | 1 - build-scripts/SDL_migration.cocci | 12 ++--- docs/README-migration.md | 1 + include/SDL3/SDL_surface.h | 52 +++++-------------- src/dynapi/SDL_dynapi.sym | 2 - src/dynapi/SDL_dynapi_overrides.h | 2 - src/dynapi/SDL_dynapi_procs.h | 6 +-- src/render/SDL_sysrender.h | 3 -- src/render/software/SDL_render_sw.c | 8 +-- src/video/SDL_surface.c | 79 +++++------------------------ 10 files changed, 38 insertions(+), 128 deletions(-) diff --git a/WhatsNew.txt b/WhatsNew.txt index 18dfd84cbd62c..1b84c49b9b06d 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -30,4 +30,3 @@ General: * Added SDL_PlayAudioDevice() to start audio playback * Added SDL_ConvertAudioSamples() to convert audio samples from one format to another * Added the hint SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY to control re-creation of Android SDL activity. -* Added SDL_SetSurfaceScaleMode() and SDL_GetSurfaceScaleMode() to control scale mode using SDL_BlitSurfaceScaled() diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 0455147f408c7..9220d4d31f3c6 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -1924,10 +1924,10 @@ expression e2; + SDL_BlitSurfaceUnchecked (...) @@ +expression e1, e2, e3, e4; @@ -- SDL_LowerBlitScaled -+ SDL_BlitSurfaceUncheckedScaled - (...) +- SDL_LowerBlitScaled(e1, e2, e3, e4) ++ SDL_BlitSurfaceUncheckedScaled(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) @@ @@ - SDL_SetClipRect @@ -1944,10 +1944,10 @@ expression e2; + SDL_BlitSurface (...) @@ +expression e1, e2, e3, e4; @@ -- SDL_UpperBlitScaled -+ SDL_BlitSurfaceScaled - (...) +- SDL_UpperBlitScaled(e1, e2, e3, e4) ++ SDL_BlitSurfaceScaled(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) @@ @@ - SDL_RenderGetD3D11Device diff --git a/docs/README-migration.md b/docs/README-migration.md index f3dfdacdd64bc..a90e32511d7c1 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1158,6 +1158,7 @@ But if you're migrating your code which uses masks, you probably have a format i 0x0000F800 0x000007E0 0x0000001F 0x00000000 => SDL_PIXELFORMAT_RGB565 ``` +SDL_BlitSurfaceScaled() and SDL_BlitSurfaceUncheckedScaled() now take a scale paramater. The following functions have been renamed: * SDL_FillRect() => SDL_FillSurfaceRect() diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index c6a3459b9b0e8..42315073590b2 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -876,7 +876,6 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled - * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, @@ -898,7 +897,6 @@ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled - * \sa SDL_SetSurfaceScaleMode */ extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, @@ -916,17 +914,19 @@ extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface *src, * \param dstrect the SDL_Rect structure representing the target rectangle in * the destination surface, filled with the actual rectangle * used after clipping + * \param scaleMode scale algorithm to be used * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurface - * \sa SDL_SetSurfaceScaleMode */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled - (SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); +extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, + const SDL_Rect *srcrect, + SDL_Surface *dst, + SDL_Rect *dstrect, + SDL_ScaleMode scaleMode); /** * Perform low-level surface scaled blitting only. @@ -940,47 +940,19 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled * \param dst the SDL_Surface structure that is the blit target * \param dstrect the SDL_Rect structure representing the target rectangle in * the destination surface + * \param scaleMode scale algorithm to be used * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled - * \sa SDL_SetSurfaceScaleMode - */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled - (SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect); - -/** - * Set the scale mode used for surface scale operations. - * - * \param surface the surface to update. - * \param scaleMode the SDL_ScaleMode to use for scaling. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetSurfaceScaleMode - * \sa SDL_BlitSurfaceScaled - */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode); - -/** - * Get the scale mode used for surface scale operations. - * - * \param surface the surface to query. - * \param scaleMode a pointer filled in with the current scale mode. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetSurfaceScaleMode - * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode); +extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, + const SDL_Rect *srcrect, + SDL_Surface *dst, + const SDL_Rect *dstrect, + SDL_ScaleMode scaleMode); /** * Set the YUV conversion mode diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 9b22950ec927b..2392a31bba5de 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -963,8 +963,6 @@ SDL3_0.0.0 { SDL_strnstr; SDL_wcsnstr; SDL_SyncWindow; - SDL_SetSurfaceScaleMode; - SDL_GetSurfaceScaleMode; SDL_GetGamepadSteamHandle; # extra symbols go here (don't modify this line) local: *; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 4c3007636b177..8482314dcb0e1 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -988,6 +988,4 @@ #define SDL_strnstr SDL_strnstr_REAL #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_SyncWindow SDL_SyncWindow_REAL -#define SDL_SetSurfaceScaleMode SDL_SetSurfaceScaleMode_REAL -#define SDL_GetSurfaceScaleMode SDL_GetSurfaceScaleMode_REAL #define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 7c7993c6f50b3..9cb62f4ba41a5 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -119,9 +119,9 @@ SDL_DYNAPI_PROC(void,SDL_AtomicUnlock,(SDL_SpinLock *a),(a),) SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return) SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return) SDL_DYNAPI_PROC(int,SDL_BlitSurface,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUnchecked,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_BroadcastCondition,(SDL_Condition *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return) SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) @@ -1013,6 +1013,4 @@ SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode *b),(a,b),return) SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 01bf8ec29a931..51d58c384349d 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -310,9 +310,6 @@ extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode the next call, because it might be in an array that gets realloc()'d. */ extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset); -extern int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); -extern int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode); - /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 591bb89c2a2f9..bb2fe7558db04 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -302,7 +302,7 @@ static int Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *surf r.y = (int)((float)dstrect->y * scale_y); r.w = (int)((float)dstrect->w * scale_x); r.h = (int)((float)dstrect->h * scale_y); - retval = SDL_PrivateBlitSurfaceScaled(src, srcrect, surface, &r, scaleMode); + retval = SDL_BlitSurfaceScaled(src, srcrect, surface, &r, scaleMode); } else { retval = SDL_BlitSurface(src, srcrect, surface, dstrect); } @@ -404,7 +404,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex retval = -1; } else { SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); - retval = SDL_PrivateBlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode); + retval = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode); SDL_DestroySurface(src_clone); src_clone = src_scaled; src_scaled = NULL; @@ -843,7 +843,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo SDL_SetSurfaceColorMod(src, 255, 255, 255); SDL_SetSurfaceAlphaMod(src, 255); - SDL_PrivateBlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode); + SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode); SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod); SDL_SetSurfaceAlphaMod(tmp, alphaMod); @@ -854,7 +854,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo /* No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy() */ } } else { - SDL_PrivateBlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode); + SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode); } } break; diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 0e9cd40ec55a0..f4f0dbaea791b 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -782,18 +782,8 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, } int SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect) -{ - SDL_ScaleMode scale_mode = SDL_SCALEMODE_NEAREST; - - if (SDL_GetSurfaceScaleMode(src, &scale_mode) < 0) { - return -1; - } - return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, scale_mode); -} - -int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode) + SDL_Surface *dst, SDL_Rect *dstrect, + SDL_ScaleMode scaleMode) { double src_x0, src_y0, src_x1, src_y1; double dst_x0, dst_y0, dst_x1, dst_y1; @@ -947,7 +937,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, return 0; } - return SDL_PrivateBlitSurfaceUncheckedScaled(src, &final_src, dst, &final_dst, scaleMode); + return SDL_BlitSurfaceUncheckedScaled(src, &final_src, dst, &final_dst, scaleMode); } /** @@ -955,23 +945,21 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, * scaled blitting only. */ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect) -{ - SDL_ScaleMode scale_mode = SDL_SCALEMODE_NEAREST; - - if (SDL_GetSurfaceScaleMode(src, &scale_mode) < 0) { - return -1; - } - return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, scale_mode); -} - -int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode) + SDL_Surface *dst, const SDL_Rect *dstrect, + SDL_ScaleMode scaleMode) { static const Uint32 complex_copy_flags = (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY); + if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) { + return SDL_InvalidParamError("scaleMode"); + } + + if (scaleMode != SDL_SCALEMODE_NEAREST) { + scaleMode = SDL_SCALEMODE_LINEAR; + } + if (srcrect->w > SDL_MAX_UINT16 || srcrect->h > SDL_MAX_UINT16 || dstrect->w > SDL_MAX_UINT16 || dstrect->h > SDL_MAX_UINT16) { return SDL_SetError("Size too large for scaling"); @@ -1069,47 +1057,6 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr } } -#define SDL_PROPERTY_SURFACE_SCALEMODE "SDL.internal.surface.scale_mode" - -int SDL_SetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode scaleMode) -{ - SDL_PropertiesID props; - - if (!surface) { - return SDL_InvalidParamError("surface"); - } - - if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) { - return SDL_InvalidParamError("scaleMode"); - } - - props = SDL_GetSurfaceProperties(surface); - if (!props) { - return -1; - } - - if (scaleMode != SDL_SCALEMODE_NEAREST) { - scaleMode = SDL_SCALEMODE_LINEAR; - } - return SDL_SetNumberProperty(props, SDL_PROPERTY_SURFACE_SCALEMODE, scaleMode); -} - -int SDL_GetSurfaceScaleMode(SDL_Surface *surface, SDL_ScaleMode *scaleMode) -{ - if (!surface) { - return SDL_InvalidParamError("surface"); - } - - if (scaleMode) { - if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { - *scaleMode = (SDL_ScaleMode)SDL_GetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROPERTY_SURFACE_SCALEMODE, SDL_SCALEMODE_NEAREST); - } else { - *scaleMode = SDL_SCALEMODE_NEAREST; - } - } - return 0; -} - /* * Lock a surface to directly access the pixels */ From ffd82fb7c447ad47c0298083a0c6ca2bcd7b9066 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 22 Dec 2023 15:02:43 +0100 Subject: [PATCH 594/725] Add scaleMode to SDL_SoftStretch(), remove SDL_SoftStretchLinear(). --- build-scripts/SDL_migration.cocci | 10 ++++++++++ docs/README-migration.md | 5 +++++ include/SDL3/SDL_surface.h | 32 +++++++------------------------ src/dynapi/SDL_dynapi.sym | 1 - src/dynapi/SDL_dynapi_overrides.h | 1 - src/dynapi/SDL_dynapi_procs.h | 3 +-- src/render/SDL_yuv_sw.c | 2 +- src/video/SDL_stretch.c | 25 +++++++++++------------- src/video/SDL_surface.c | 8 ++++---- 9 files changed, 39 insertions(+), 48 deletions(-) diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 9220d4d31f3c6..6cb692f307990 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -2754,3 +2754,13 @@ expression w, i, s; - SDL_GameControllerGetSteamHandle + SDL_GetGamepadSteamHandle (...) +@@ +expression e1, e2, e3, e4; +@@ +- SDL_SoftStretch(e1, e2, e3, e4) ++ SDL_SoftStretch(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) +@@ +expression e1, e2, e3, e4; +@@ +- SDL_SoftStretchLinear(e1, e2, e3, e4) ++ SDL_SoftStretch(e1, e2, e3, e4, SDL_SCALEMODE_LINEAR) diff --git a/docs/README-migration.md b/docs/README-migration.md index a90e32511d7c1..7f554277a0434 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1160,6 +1160,8 @@ But if you're migrating your code which uses masks, you probably have a format i SDL_BlitSurfaceScaled() and SDL_BlitSurfaceUncheckedScaled() now take a scale paramater. +SDL_SoftStretch() now takes a scale paramater. + The following functions have been renamed: * SDL_FillRect() => SDL_FillSurfaceRect() * SDL_FillRects() => SDL_FillSurfaceRects() @@ -1175,6 +1177,9 @@ The following functions have been renamed: * SDL_UpperBlit() => SDL_BlitSurface() * SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled() +The following functions have been removed: +* SDL_SoftStretchLinear() - use SDL_SoftStretch() with SDL_SCALEMODE_LINEAR + ## SDL_system.h SDL_WindowsMessageHook has changed signatures so the message may be modified and it can block further message processing. diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 42315073590b2..e322d6ac0c0bb 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -861,29 +861,10 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked SDL_Surface *dst, const SDL_Rect *dstrect); /** - * Perform a fast, low quality, stretch blit between two surfaces of the same - * format. + * Perform stretch blit between two surfaces of the same format. * - * \param src the SDL_Surface structure to be copied from - * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied - * \param dst the SDL_Surface structure that is the blit target - * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_BlitSurfaceScaled - */ -extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, - const SDL_Rect *srcrect, - SDL_Surface *dst, - const SDL_Rect *dstrect); - -/** - * Perform bilinear scaling between two surfaces of the same format, 32BPP. + * Using SDL_SCALEMODE_NEAREST: fast, low quality. + * Using SDL_SCALEMODE_LINEAR: bilinear scaling, slower, better quality, only 32BPP. * * \param src the SDL_Surface structure to be copied from * \param srcrect the SDL_Rect structure representing the rectangle to be @@ -891,6 +872,7 @@ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, * \param dst the SDL_Surface structure that is the blit target * \param dstrect the SDL_Rect structure representing the target rectangle in * the destination surface + * \param scaleMode scale algorithm to be used * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * @@ -898,11 +880,11 @@ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, * * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface *src, +extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, - const SDL_Rect *dstrect); - + const SDL_Rect *dstrect, + SDL_ScaleMode scaleMode); /** * Perform a scaled surface copy to a destination surface. diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 2392a31bba5de..a72032cd281e7 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -613,7 +613,6 @@ SDL3_0.0.0 { SDL_ShowWindow; SDL_SignalCondition; SDL_SoftStretch; - SDL_SoftStretchLinear; SDL_StartTextInput; SDL_StopTextInput; SDL_SurfaceHasColorKey; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8482314dcb0e1..451fadbd96e1b 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -636,7 +636,6 @@ #define SDL_ShowWindow SDL_ShowWindow_REAL #define SDL_SignalCondition SDL_SignalCondition_REAL #define SDL_SoftStretch SDL_SoftStretch_REAL -#define SDL_SoftStretchLinear SDL_SoftStretchLinear_REAL #define SDL_StartTextInput SDL_StartTextInput_REAL #define SDL_StopTextInput SDL_StopTextInput_REAL #define SDL_SurfaceHasColorKey SDL_SurfaceHasColorKey_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 9cb62f4ba41a5..5b3cb2d2025ed 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -677,8 +677,7 @@ SDL_DYNAPI_PROC(int,SDL_ShowMessageBox,(const SDL_MessageBoxData *a, int *b),(a, SDL_DYNAPI_PROC(int,SDL_ShowSimpleMessageBox,(Uint32 a, const char *b, const char *c, SDL_Window *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_ShowWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SignalCondition,(SDL_Condition *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SoftStretch,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SoftStretchLinear,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_SoftStretch,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_StartTextInput,(void),(),) SDL_DYNAPI_PROC(void,SDL_StopTextInput,(void),(),) SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return) diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index 9a4cc3ac2a3b7..5761bcc580698 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -382,7 +382,7 @@ int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, } if (stretch) { SDL_Rect rect = *srcrect; - SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL); + SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL, SDL_SCALEMODE_NEAREST); } return 0; } diff --git a/src/video/SDL_stretch.c b/src/video/SDL_stretch.c index 3b628c262b10f..1bc8c74f1fca1 100644 --- a/src/video/SDL_stretch.c +++ b/src/video/SDL_stretch.c @@ -24,22 +24,10 @@ static int SDL_LowerSoftStretchNearest(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); static int SDL_LowerSoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); -static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); int SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect) -{ - return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); -} - -int SDL_SoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect) -{ - return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR); -} - -static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode) + SDL_Surface *dst, const SDL_Rect *dstrect, + SDL_ScaleMode scaleMode) { int ret; int src_locked; @@ -47,11 +35,20 @@ static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Rect full_src; SDL_Rect full_dst; + if (src->format->format != dst->format->format) { return SDL_SetError("Only works with same format surfaces"); } + if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) { + return SDL_InvalidParamError("scaleMode"); + } + if (scaleMode != SDL_SCALEMODE_NEAREST) { + scaleMode = SDL_SCALEMODE_LINEAR; + } + + if (scaleMode == SDL_SCALEMODE_LINEAR) { if (src->format->BytesPerPixel != 4 || src->format->format == SDL_PIXELFORMAT_ARGB2101010) { return SDL_SetError("Wrong format"); } diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index f4f0dbaea791b..b0a57d4e6e5bf 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -974,7 +974,7 @@ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, if (!(src->map->info.flags & complex_copy_flags) && src->format->format == dst->format->format && !SDL_ISPIXELFORMAT_INDEXED(src->format->format)) { - return SDL_SoftStretch(src, srcrect, dst, dstrect); + return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); } else { return SDL_BlitSurfaceUnchecked(src, srcrect, dst, dstrect); } @@ -985,7 +985,7 @@ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, src->format->BytesPerPixel == 4 && src->format->format != SDL_PIXELFORMAT_ARGB2101010) { /* fast path */ - return SDL_SoftStretchLinear(src, srcrect, dst, dstrect); + return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR); } else { /* Use intermediate surface(s) */ SDL_Surface *tmp1 = NULL; @@ -1035,7 +1035,7 @@ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, if (is_complex_copy_flags || src->format->format != dst->format->format) { SDL_Rect tmprect; SDL_Surface *tmp2 = SDL_CreateSurface(dstrect->w, dstrect->h, src->format->format); - SDL_SoftStretchLinear(src, &srcrect2, tmp2, NULL); + SDL_SoftStretch(src, &srcrect2, tmp2, NULL, SDL_SCALEMODE_LINEAR); SDL_SetSurfaceColorMod(tmp2, r, g, b); SDL_SetSurfaceAlphaMod(tmp2, alpha); @@ -1048,7 +1048,7 @@ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, ret = SDL_BlitSurfaceUnchecked(tmp2, &tmprect, dst, dstrect); SDL_DestroySurface(tmp2); } else { - ret = SDL_SoftStretchLinear(src, &srcrect2, dst, dstrect); + ret = SDL_SoftStretch(src, &srcrect2, dst, dstrect, SDL_SCALEMODE_LINEAR); } SDL_DestroySurface(tmp1); From 07e9603398ff8f7d4823fc37769ce30d7a9eaf1e Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Fri, 22 Dec 2023 17:14:22 +0000 Subject: [PATCH 595/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_surface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index e322d6ac0c0bb..37e5b15251d29 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -863,8 +863,8 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked /** * Perform stretch blit between two surfaces of the same format. * - * Using SDL_SCALEMODE_NEAREST: fast, low quality. - * Using SDL_SCALEMODE_LINEAR: bilinear scaling, slower, better quality, only 32BPP. + * Using SDL_SCALEMODE_NEAREST: fast, low quality. Using SDL_SCALEMODE_LINEAR: + * bilinear scaling, slower, better quality, only 32BPP. * * \param src the SDL_Surface structure to be copied from * \param srcrect the SDL_Rect structure representing the rectangle to be From 199f7cc3b119bfe5184703054dd1814eaac6898e Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 22 Dec 2023 12:17:06 -0500 Subject: [PATCH 596/725] x11: Ignore border extents when the border hint is unset Old extent events can arrive after the border hint has been unset. Ignore the reported values in this case to avoid reporting bogus border sizes. --- src/video/x11/SDL_x11events.c | 33 +++++++++++++++++++-------------- src/video/x11/SDL_x11window.c | 6 +----- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index c5072eab6dcce..7906c12dfd5f9 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -884,18 +884,24 @@ void X11_GetBorderValues(SDL_WindowData *data) int format; unsigned long nitems, bytes_after; unsigned char *property; - if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) { - if (type != None && nitems == 4) { - data->border_left = (int)((long *)property)[0]; - data->border_right = (int)((long *)property)[1]; - data->border_top = (int)((long *)property)[2]; - data->border_bottom = (int)((long *)property)[3]; - } - X11_XFree(property); + + /* Some compositors will send extents even when the border hint is turned off. Ignore them in this case. */ + if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { + if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) { + if (type != None && nitems == 4) { + data->border_left = (int)((long *)property)[0]; + data->border_right = (int)((long *)property)[1]; + data->border_top = (int)((long *)property)[2]; + data->border_bottom = (int)((long *)property)[3]; + } + X11_XFree(property); #ifdef DEBUG_XEVENTS - printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom); + printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom); #endif + } + } else { + data->border_left = data->border_top = data->border_right = data->border_bottom = 0; } } @@ -1745,11 +1751,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top); X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h); } - - if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { - data->toggle_borders = SDL_FALSE; - X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); - } + } + if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { + data->toggle_borders = SDL_FALSE; + X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); } } } break; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 3ca21df70e3c7..ddb8f26aa6ea7 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -1233,11 +1233,7 @@ void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); /* Turning the borders off doesn't send an extent event, so they must be cleared here. */ - if (bordered) { - X11_GetBorderValues(data); - } else { - data->border_top = data->border_left = data->border_bottom = data->border_right = 0; - } + X11_GetBorderValues(data); /* Make sure the window manager didn't resize our window for the difference. */ X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); From 312f98c2a1edaf9590fc06d10f201996c059d869 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Sat, 23 Dec 2023 21:30:09 +0100 Subject: [PATCH 597/725] Make sure the string is terminated, fixed invalid read in SDL_PrivateParseGamepadConfigString() --- src/joystick/SDL_gamepad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index c911183da8499..e1e5b89f03cce 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1282,12 +1282,14 @@ static int SDL_PrivateParseGamepadConfigString(SDL_Gamepad *gamepad, const char } else if (bGameButton) { if (i >= sizeof(szGameButton)) { + szGameButton[sizeof(szGameButton) - 1] = '\0'; return SDL_SetError("Button name too large: %s", szGameButton); } szGameButton[i] = *pchPos; i++; } else { if (i >= sizeof(szJoystickButton)) { + szJoystickButton[sizeof(szJoystickButton) - 1] = '\0'; return SDL_SetError("Joystick button name too large: %s", szJoystickButton); } szJoystickButton[i] = *pchPos; From bb0e0ae0809c42e5a20f7e13aad8a34b8e7145cf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 06:50:42 -0800 Subject: [PATCH 598/725] Added a runtime check for BLUETOOTH_CONNECT in addition to BLUETOOTH (thanks @perepujal!) Fixes https://github.com/libsdl-org/SDL/issues/8731 --- .../app/src/main/java/org/libsdl/app/HIDDeviceManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 42e669471f1df..1a9d1c652bc06 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -359,6 +359,12 @@ private void connectHIDDeviceUSB(UsbDevice usbDevice) { private void initializeBluetooth() { Log.d(TAG, "Initializing Bluetooth"); + if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ && + mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT"); + return; + } + if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ && mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH"); From 4914e5bb78f12079e14a89b58a12b9bf33faf41f Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Sun, 24 Dec 2023 14:49:23 +0000 Subject: [PATCH 599/725] PS2 use WaitSemaEx for waiting for semaphore with timeout --- src/thread/ps2/SDL_syssem.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index ceb191181ee77..09a846d7a71b0 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include @@ -35,11 +35,6 @@ struct SDL_Semaphore s32 semid; }; -static void usercb(struct timer_alarm_t *alarm, void *arg) -{ - iReleaseWaitThread((int)arg); -} - /* Create a semaphore */ SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value) { @@ -80,8 +75,8 @@ void SDL_DestroySemaphore(SDL_Semaphore *sem) int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) { int ret; - struct timer_alarm_t alarm; - InitializeTimerAlarm(&alarm); + u64 timeout_usec; + u64 *timeout_ptr; if (!sem) { return SDL_InvalidParamError("sem"); @@ -94,12 +89,14 @@ int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS) return 0; } + timeout_ptr = NULL; + if (timeoutNS != -1) { // -1 == wait indefinitely. - SetTimerAlarm(&alarm, MSec2TimerBusClock(SDL_NS_TO_MS(timeoutNS)), &usercb, (void *)GetThreadId()); + timeout_usec = SDL_NS_TO_US(timeoutNS); + timeout_ptr = &timeout_usec; } - ret = WaitSema(sem->semid); - StopTimerAlarm(&alarm); + ret = WaitSemaEx(sem->semid, 1, timeout_ptr); if (ret < 0) { return SDL_MUTEX_TIMEDOUT; From 10a8b750a03b9c8af968b0be9a1b65ddcf0e79cc Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Sun, 24 Dec 2023 14:44:33 +0000 Subject: [PATCH 600/725] Use common generic syscond for platforms with no cond implementation --- CMakeLists.txt | 3 +- src/thread/psp/SDL_syscond.c | 202 ---------------------------------- src/thread/vita/SDL_syscond.c | 202 ---------------------------------- 3 files changed, 2 insertions(+), 405 deletions(-) delete mode 100644 src/thread/psp/SDL_syscond.c delete mode 100644 src/thread/vita/SDL_syscond.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8af562830bdb6..74c2102b6163e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2470,7 +2470,7 @@ elseif(VITA) "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_sysmutex.c" "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_syssem.c" "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_systhread.c" - "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_syscond.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" ) @@ -2601,6 +2601,7 @@ elseif(PSP) if(SDL_THREADS) set(SDL_THREAD_PSP 1) sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" "${SDL3_SOURCE_DIR}/src/thread/psp/*.c" diff --git a/src/thread/psp/SDL_syscond.c b/src/thread/psp/SDL_syscond.c deleted file mode 100644 index bfe4f42bac527..0000000000000 --- a/src/thread/psp/SDL_syscond.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifdef SDL_THREAD_PSP - -/* An implementation of condition variables using semaphores and mutexes */ -/* - This implementation borrows heavily from the BeOS condition variable - implementation, written by Christopher Tate and Owen Smith. Thanks! - */ - -struct SDL_Condition -{ - SDL_Mutex *lock; - int waiting; - int signals; - SDL_Semaphore *wait_sem; - SDL_Semaphore *wait_done; -}; - -/* Create a condition variable */ -SDL_Condition *SDL_CreateCondition(void) -{ - SDL_Condition *cond; - - cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition)); - if (cond) { - cond->lock = SDL_CreateMutex(); - cond->wait_sem = SDL_CreateSemaphore(0); - cond->wait_done = SDL_CreateSemaphore(0); - cond->waiting = cond->signals = 0; - if (!cond->lock || !cond->wait_sem || !cond->wait_done) { - SDL_DestroyCondition(cond); - cond = NULL; - } - } - return cond; -} - -/* Destroy a condition variable */ -void SDL_DestroyCondition(SDL_Condition *cond) -{ - if (cond) { - if (cond->wait_sem) { - SDL_DestroySemaphore(cond->wait_sem); - } - if (cond->wait_done) { - SDL_DestroySemaphore(cond->wait_done); - } - if (cond->lock) { - SDL_DestroyMutex(cond->lock); - } - SDL_free(cond); - } -} - -/* Restart one of the threads that are waiting on the condition variable */ -int SDL_SignalCondition(SDL_Condition *cond) -{ - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - SDL_LockMutex(cond->lock); - if (cond->waiting > cond->signals) { - ++cond->signals; - SDL_PostSemaphore(cond->wait_sem); - SDL_UnlockMutex(cond->lock); - SDL_WaitSemaphore(cond->wait_done); - } else { - SDL_UnlockMutex(cond->lock); - } - - return 0; -} - -/* Restart all threads that are waiting on the condition variable */ -int SDL_BroadcastCondition(SDL_Condition *cond) -{ - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - SDL_LockMutex(cond->lock); - if (cond->waiting > cond->signals) { - int i, num_waiting; - - num_waiting = (cond->waiting - cond->signals); - cond->signals = cond->waiting; - for (i = 0; i < num_waiting; ++i) { - SDL_PostSemaphore(cond->wait_sem); - } - /* Now all released threads are blocked here, waiting for us. - Collect them all (and win fabulous prizes!) :-) - */ - SDL_UnlockMutex(cond->lock); - for (i = 0; i < num_waiting; ++i) { - SDL_WaitSemaphore(cond->wait_done); - } - } else { - SDL_UnlockMutex(cond->lock); - } - - return 0; -} - -/* Wait on the condition variable for at most 'timeoutNS' nanoseconds. - The mutex must be locked before entering this function! - The mutex is unlocked during the wait, and locked again after the wait. - -Typical use: - -Thread A: - SDL_LockMutex(lock); - while ( ! condition ) { - SDL_WaitCondition(cond, lock); - } - SDL_UnlockMutex(lock); - -Thread B: - SDL_LockMutex(lock); - ... - condition = true; - ... - SDL_SignalCondition(cond); - SDL_UnlockMutex(lock); - */ -int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS) -{ - int retval; - - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* Obtain the protection mutex, and increment the number of waiters. - This allows the signal mechanism to only perform a signal if there - are waiting threads. - */ - SDL_LockMutex(cond->lock); - ++cond->waiting; - SDL_UnlockMutex(cond->lock); - - /* Unlock the mutex, as is required by condition variable semantics */ - SDL_UnlockMutex(mutex); - - /* Wait for a signal */ - retval = SDL_WaitSemaphoreTimeout(cond->wait_sem, timeoutNS); - - /* Let the signaler know we have completed the wait, otherwise - the signaler can race ahead and get the condition semaphore - if we are stopped between the mutex unlock and semaphore wait, - giving a deadlock. See the following URL for details: - http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html - */ - SDL_LockMutex(cond->lock); - if (cond->signals > 0) { - /* If we timed out, we need to eat a condition signal */ - if (retval > 0) { - SDL_WaitSemaphore(cond->wait_sem); - } - /* We always notify the signal thread that we are done */ - SDL_PostSemaphore(cond->wait_done); - - /* Signal handshake complete */ - --cond->signals; - } - --cond->waiting; - SDL_UnlockMutex(cond->lock); - - /* Lock the mutex, as is required by condition variable semantics */ - SDL_LockMutex(mutex); - - return retval; -} - -#endif /* SDL_THREAD_PSP */ diff --git a/src/thread/vita/SDL_syscond.c b/src/thread/vita/SDL_syscond.c deleted file mode 100644 index fc8e1c9e36d5c..0000000000000 --- a/src/thread/vita/SDL_syscond.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifdef SDL_THREAD_VITA - -/* An implementation of condition variables using semaphores and mutexes */ -/* - This implementation borrows heavily from the BeOS condition variable - implementation, written by Christopher Tate and Owen Smith. Thanks! - */ - -struct SDL_Condition -{ - SDL_Mutex *lock; - int waiting; - int signals; - SDL_Semaphore *wait_sem; - SDL_Semaphore *wait_done; -}; - -/* Create a condition variable */ -SDL_Condition *SDL_CreateCondition(void) -{ - SDL_Condition *cond; - - cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition)); - if (cond) { - cond->lock = SDL_CreateMutex(); - cond->wait_sem = SDL_CreateSemaphore(0); - cond->wait_done = SDL_CreateSemaphore(0); - cond->waiting = cond->signals = 0; - if (!cond->lock || !cond->wait_sem || !cond->wait_done) { - SDL_DestroyCondition(cond); - cond = NULL; - } - } - return cond; -} - -/* Destroy a condition variable */ -void SDL_DestroyCondition(SDL_Condition *cond) -{ - if (cond) { - if (cond->wait_sem) { - SDL_DestroySemaphore(cond->wait_sem); - } - if (cond->wait_done) { - SDL_DestroySemaphore(cond->wait_done); - } - if (cond->lock) { - SDL_DestroyMutex(cond->lock); - } - SDL_free(cond); - } -} - -/* Restart one of the threads that are waiting on the condition variable */ -int SDL_SignalCondition(SDL_Condition *cond) -{ - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - SDL_LockMutex(cond->lock); - if (cond->waiting > cond->signals) { - ++cond->signals; - SDL_PostSemaphore(cond->wait_sem); - SDL_UnlockMutex(cond->lock); - SDL_WaitSemaphore(cond->wait_done); - } else { - SDL_UnlockMutex(cond->lock); - } - - return 0; -} - -/* Restart all threads that are waiting on the condition variable */ -int SDL_BroadcastCondition(SDL_Condition *cond) -{ - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - SDL_LockMutex(cond->lock); - if (cond->waiting > cond->signals) { - int i, num_waiting; - - num_waiting = (cond->waiting - cond->signals); - cond->signals = cond->waiting; - for (i = 0; i < num_waiting; ++i) { - SDL_PostSemaphore(cond->wait_sem); - } - /* Now all released threads are blocked here, waiting for us. - Collect them all (and win fabulous prizes!) :-) - */ - SDL_UnlockMutex(cond->lock); - for (i = 0; i < num_waiting; ++i) { - SDL_WaitSemaphore(cond->wait_done); - } - } else { - SDL_UnlockMutex(cond->lock); - } - - return 0; -} - -/* Wait on the condition variable for at most 'timeoutNS' nanoseconds. - The mutex must be locked before entering this function! - The mutex is unlocked during the wait, and locked again after the wait. - -Typical use: - -Thread A: - SDL_LockMutex(lock); - while ( ! condition ) { - SDL_WaitCondition(cond, lock); - } - SDL_UnlockMutex(lock); - -Thread B: - SDL_LockMutex(lock); - ... - condition = true; - ... - SDL_SignalCondition(cond); - SDL_UnlockMutex(lock); - */ -int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS) -{ - int retval; - - if (!cond) { - return SDL_InvalidParamError("cond"); - } - - /* Obtain the protection mutex, and increment the number of waiters. - This allows the signal mechanism to only perform a signal if there - are waiting threads. - */ - SDL_LockMutex(cond->lock); - ++cond->waiting; - SDL_UnlockMutex(cond->lock); - - /* Unlock the mutex, as is required by condition variable semantics */ - SDL_UnlockMutex(mutex); - - /* Wait for a signal */ - retval = SDL_WaitSemaphoreTimeoutNS(cond->wait_sem, timeoutNS); - - /* Let the signaler know we have completed the wait, otherwise - the signaler can race ahead and get the condition semaphore - if we are stopped between the mutex unlock and semaphore wait, - giving a deadlock. See the following URL for details: - http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html - */ - SDL_LockMutex(cond->lock); - if (cond->signals > 0) { - /* If we timed out, we need to eat a condition signal */ - if (retval > 0) { - SDL_WaitSemaphore(cond->wait_sem); - } - /* We always notify the signal thread that we are done */ - SDL_PostSemaphore(cond->wait_done); - - /* Signal handshake complete */ - --cond->signals; - } - --cond->waiting; - SDL_UnlockMutex(cond->lock); - - /* Lock the mutex, as is required by condition variable semantics */ - SDL_LockMutex(mutex); - - return retval; -} - -#endif /* SDL_THREAD_VITA */ From c3d84c3342f61b808462c7437784af5df4906273 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 08:12:14 -0800 Subject: [PATCH 601/725] Record the initial input report mode and only restore simple mode if that's what we started with Fixes https://github.com/libsdl-org/SDL/issues/8108 Closes https://github.com/libsdl-org/SDL/pull/8115 --- src/joystick/hidapi/SDL_hidapi_switch.c | 56 ++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 5a4b109df4246..b4f2d9a9c91a2 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -269,6 +269,8 @@ typedef struct SDL_bool m_bSyncWrite; int m_nMaxWriteAttempts; ESwitchDeviceInfoControllerType m_eControllerType; + Uint8 m_nInitialInputMode; + Uint8 m_nCurrentInputMode; Uint8 m_rgucMACAddress[6]; Uint8 m_nCommandNumber; SwitchCommonOutputPacket_t m_RumblePacket; @@ -643,7 +645,13 @@ static SDL_bool SetVibrationEnabled(SDL_DriverSwitch_Context *ctx, Uint8 enabled } static SDL_bool SetInputMode(SDL_DriverSwitch_Context *ctx, Uint8 input_mode) { - return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, sizeof(input_mode), NULL); + if (input_mode == ctx->m_nCurrentInputMode) { + return SDL_TRUE; + } else { + ctx->m_nCurrentInputMode = input_mode; + + return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, sizeof(input_mode), NULL); + } } static SDL_bool SetHomeLED(SDL_DriverSwitch_Context *ctx, Uint8 brightness) @@ -712,15 +720,29 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c } } +static Uint8 GetInitialInputMode(SDL_DriverSwitch_Context *ctx) +{ + Uint8 input_mode = 0; + + if (ReadInput(ctx) > 0) { + input_mode = ctx->m_rgucReadBuffer[0]; + } + return input_mode; +} + static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx) { Uint8 input_mode; /* Determine the desired input mode */ - if (ctx->device->is_bluetooth) { - input_mode = k_eSwitchInputReportIDs_SimpleControllerState; + if (ctx->m_nInitialInputMode) { + input_mode = ctx->m_nInitialInputMode; } else { - input_mode = k_eSwitchInputReportIDs_FullControllerState; + if (ctx->device->is_bluetooth) { + input_mode = k_eSwitchInputReportIDs_SimpleControllerState; + } else { + input_mode = k_eSwitchInputReportIDs_FullControllerState; + } } /* The official Nintendo Switch Pro Controller supports FullControllerState over Bluetooth @@ -734,6 +756,20 @@ static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx) return input_mode; } +static Uint8 GetSensorInputMode(SDL_DriverSwitch_Context *ctx) +{ + Uint8 input_mode; + + /* Determine the desired input mode */ + if (!ctx->m_nInitialInputMode || + ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) { + input_mode = k_eSwitchInputReportIDs_FullControllerState; + } else { + input_mode = ctx->m_nInitialInputMode; + } + return input_mode; +} + static SDL_bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, SDL_bool enabled) { Uint8 imu_data = enabled ? 1 : 0; @@ -1305,6 +1341,9 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ ctx->m_bSyncWrite = SDL_TRUE; if (!ctx->m_bInputOnly) { + ctx->m_nInitialInputMode = GetInitialInputMode(ctx); + ctx->m_nCurrentInputMode = ctx->m_nInitialInputMode; + /* Initialize rumble data */ SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]); SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]); @@ -1590,7 +1629,7 @@ static int HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *devi Uint8 input_mode; if (enabled) { - input_mode = k_eSwitchInputReportIDs_FullControllerState; + input_mode = GetSensorInputMode(ctx); } else { input_mode = GetDefaultInputMode(ctx); } @@ -2176,6 +2215,8 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) if (ctx->m_bInputOnly) { HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]); } else { + ctx->m_nCurrentInputMode = ctx->m_rgucReadBuffer[0]; + switch (ctx->m_rgucReadBuffer[0]) { case k_eSwitchInputReportIDs_SimpleControllerState: HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]); @@ -2242,7 +2283,10 @@ static void HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joy if (!ctx->m_bInputOnly) { /* Restore simple input mode for other applications */ - SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState); + if (!ctx->m_nInitialInputMode || + ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) { + SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState); + } } if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft || From 0e5ea3cc4b98d061688a098836254ab6470b07e8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 11:19:16 -0800 Subject: [PATCH 602/725] Fixed infinite recursion when adding an accelerometer as joystick on iOS Fixes https://github.com/libsdl-org/SDL/issues/8716 --- src/joystick/SDL_gamepad.c | 20 ++++++++++---------- src/joystick/apple/SDL_mfijoystick.m | 3 +++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index e1e5b89f03cce..0543b9dbbca91 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -156,7 +156,7 @@ static SDL_vidpid_list SDL_ignored_gamepads = { static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_bool *existing, SDL_GamepadMappingPriority priority); static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t *pGamepadMapping); -static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id); +static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id, SDL_bool create_mapping); static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadAxis axis, Sint16 value); static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadButton button, Uint8 state); @@ -504,7 +504,7 @@ static void PushMappingChangeTracking(void) return; } for (i = 0; i < num_joysticks; ++i) { - tracker->joystick_mappings[i] = SDL_PrivateGetGamepadMapping(tracker->joysticks[i]); + tracker->joystick_mappings[i] = SDL_PrivateGetGamepadMapping(tracker->joysticks[i], SDL_FALSE); } } @@ -562,7 +562,7 @@ static void PopMappingChangeTracking(void) /* Looking up the new mapping might create one and associate it with the gamepad (and generate events) */ SDL_JoystickID joystick = tracker->joysticks[i]; SDL_Gamepad *gamepad = SDL_GetGamepadFromInstanceID(joystick); - GamepadMapping_t *new_mapping = SDL_PrivateGetGamepadMapping(joystick); + GamepadMapping_t *new_mapping = SDL_PrivateGetGamepadMapping(joystick, SDL_FALSE); GamepadMapping_t *old_mapping = gamepad ? gamepad->mapping : tracker->joystick_mappings[i]; if (new_mapping && !old_mapping) { @@ -1770,7 +1770,7 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * return SDL_PrivateAddMappingForGUID(guid, mapping, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT); } -static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id) +static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id, SDL_bool create_mapping) { const char *name; SDL_JoystickGUID guid; @@ -1781,7 +1781,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id name = SDL_GetJoystickInstanceName(instance_id); guid = SDL_GetJoystickInstanceGUID(instance_id); mapping = SDL_PrivateGetGamepadMappingForNameAndGUID(name, guid); - if (!mapping) { + if (!mapping && create_mapping) { SDL_GamepadMapping raw_map; SDL_zero(raw_map); @@ -2338,7 +2338,7 @@ const char *SDL_GetGamepadInstanceName(SDL_JoystickID instance_id) SDL_LockJoysticks(); { - GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); + GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE); if (mapping) { if (SDL_strcmp(mapping->name, "*") == 0) { retval = SDL_GetJoystickInstanceName(instance_id); @@ -2388,7 +2388,7 @@ SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id) SDL_LockJoysticks(); { - GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); + GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE); if (mapping) { char *type_string, *comma; @@ -2437,7 +2437,7 @@ char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id) SDL_LockJoysticks(); { - GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id); + GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE); if (mapping) { char pchGUID[33]; const SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id); @@ -2478,7 +2478,7 @@ SDL_bool SDL_IsGamepad(SDL_JoystickID instance_id) SDL_LockJoysticks(); { - if (SDL_PrivateGetGamepadMapping(instance_id) != NULL) { + if (SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE) != NULL) { retval = SDL_TRUE; } else { retval = SDL_FALSE; @@ -2584,7 +2584,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id) } /* Find a gamepad mapping */ - pSupportedGamepad = SDL_PrivateGetGamepadMapping(instance_id); + pSupportedGamepad = SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE); if (!pSupportedGamepad) { SDL_SetError("Couldn't find mapping for device (%" SDL_PRIu32 ")", instance_id); SDL_UnlockJoysticks(); diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 1eb65697af10c..8ce2ac3d66b60 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1826,6 +1826,9 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi if (device == NULL) { return SDL_FALSE; } + if (device->accelerometer) { + return SDL_FALSE; + } if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { int axis = 0; From 69e60e0f1bb095aa0377ba6fcb59ee9638e5c74f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 16:24:22 -0800 Subject: [PATCH 603/725] Fixed setting fullscreen mode on iOS Needed to update the actual window flags based on the requested state (@Kontrabant) --- src/video/uikit/SDL_uikitwindow.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index efc21da164b14..8623bcf5b4cf2 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -305,6 +305,11 @@ static void UIKit_UpdateWindowBorder(SDL_VideoDevice *_this, SDL_Window *window) void UIKit_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered) { @autoreleasepool { + if (bordered) { + window->flags &= ~SDL_WINDOW_BORDERLESS; + } else { + window->flags |= SDL_WINDOW_BORDERLESS; + } UIKit_UpdateWindowBorder(_this, window); } } @@ -312,6 +317,11 @@ void UIKit_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_boo int UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { @autoreleasepool { + if (fullscreen) { + window->flags &= ~SDL_WINDOW_FULLSCREEN; + } else { + window->flags |= SDL_WINDOW_FULLSCREEN; + } UIKit_UpdateWindowBorder(_this, window); } return 0; From 278e3f91848c6ed5a9d829bcfda49d88994a1477 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 17:12:01 -0800 Subject: [PATCH 604/725] Whoops, fixed setting fullscreen flag --- src/video/uikit/SDL_uikitwindow.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 8623bcf5b4cf2..82229a5a0559b 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -318,9 +318,9 @@ int UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vi { @autoreleasepool { if (fullscreen) { - window->flags &= ~SDL_WINDOW_FULLSCREEN; - } else { window->flags |= SDL_WINDOW_FULLSCREEN; + } else { + window->flags &= ~SDL_WINDOW_FULLSCREEN; } UIKit_UpdateWindowBorder(_this, window); } From e3b5999bb4fe9bc8413630215d928f90347073d1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 17:14:16 -0800 Subject: [PATCH 605/725] Use the application requested size to determine automatic orientation on iOS Fixes https://github.com/libsdl-org/SDL/issues/8201 --- src/video/uikit/SDL_uikitwindow.m | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 82229a5a0559b..7e510bf517ae1 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -113,14 +113,6 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow #if !TARGET_OS_TV && !TARGET_OS_XR if (displaydata.uiscreen == [UIScreen mainScreen]) { - /* SDL_CreateWindow sets the window w&h to the display's bounds if the - * fullscreen flag is set. But the display bounds orientation might not - * match what we want, and GetSupportedOrientations call below uses the - * window w&h. They're overridden below anyway, so we'll just set them - * to the requested size for the purposes of determining orientation. */ - window->w = window->windowed.w; - window->h = window->windowed.h; - NSUInteger orients = UIKit_GetSupportedOrientations(window); BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0; BOOL supportsPortrait = (orients & (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown)) != 0; @@ -441,10 +433,10 @@ void UIKit_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int } if (orientationMask == 0) { - if (window->w >= window->h) { + if (window->floating.w >= window->floating.h) { orientationMask |= UIInterfaceOrientationMaskLandscape; } - if (window->h >= window->w) { + if (window->floating.h >= window->floating.w) { orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); } } From 1bf78ed544b624add24aef5646ef9bb8cd3e7a88 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 24 Dec 2023 17:45:35 -0800 Subject: [PATCH 606/725] We get a resize event when the view enters fullscreen mode on iOS The call stack is: We want to use this instead of the desktop mode because the view may be in a different orientation than the device orientation, which the desktop mode is based on. --- src/video/uikit/SDL_uikitvideo.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index d7548baefc6b2..22f5251fd1ca7 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -131,6 +131,8 @@ static void UIKit_DeleteDevice(SDL_VideoDevice *device) device->Metal_GetLayer = UIKit_Metal_GetLayer; #endif + device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; + device->gl_config.accelerated = 1; return device; From 6daf2e943f086d57ba85ad873cfde16756d3c1d2 Mon Sep 17 00:00:00 2001 From: Tyson Whitehead Date: Wed, 29 Nov 2023 18:19:03 -0500 Subject: [PATCH 607/725] Try SDL_UDEV_deviceclass to detect joysticks even if in a container The udev container issue is mostly to do with device notifications and netlink. The device classification stuff just pokes file in /sys and /run/udev. Doesn't hurt to try it first for classifying joysticks and then fall to the guess heuristics if it fails. --- src/core/linux/SDL_udev.c | 50 +++++++++++++++++++--------- src/core/linux/SDL_udev.h | 2 +- src/joystick/linux/SDL_sysjoystick.c | 12 ++++--- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 59d37d0e9fdd9..a2d5bb62f009c 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -42,6 +42,9 @@ static SDL_UDEV_PrivateData *_this = NULL; static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr); static int SDL_UDEV_load_syms(void); static SDL_bool SDL_UDEV_hotplug_update_available(void); +static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len); +static int guess_device_class(struct udev_device *dev); +static int device_class(struct udev_device *dev); static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev); static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr) @@ -218,7 +221,7 @@ int SDL_UDEV_Scan(void) return 0; } -SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version) +SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class) { struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devs = NULL; @@ -246,6 +249,7 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 existing_path = _this->syms.udev_device_get_devnode(dev); if (existing_path && SDL_strcmp(device_path, existing_path) == 0) { + int class_temp; found = SDL_TRUE; val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID"); @@ -262,6 +266,11 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 if (val) { *version = (Uint16)SDL_strtol(val, NULL, 16); } + + class_temp = device_class(dev); + if (class_temp) { + *class = class_temp; + } } _this->syms.udev_device_unref(dev); } @@ -393,29 +402,23 @@ static int guess_device_class(struct udev_device *dev) &bitmask_rel[0]); } -static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) +static int device_class(struct udev_device *dev) { const char *subsystem; const char *val = NULL; int devclass = 0; - const char *path; - SDL_UDEV_CallbackList *item; - - path = _this->syms.udev_device_get_devnode(dev); - if (!path) { - return; - } subsystem = _this->syms.udev_device_get_subsystem(dev); + if (!subsystem) { + return 0; + } if (SDL_strcmp(subsystem, "sound") == 0) { devclass = SDL_UDEV_DEVICE_SOUND; } else if (SDL_strcmp(subsystem, "video4linux") == 0) { - devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE; - val = _this->syms.udev_device_get_property_value(dev, "ID_V4L_CAPABILITIES"); - if (!val || !SDL_strcasestr(val, "capture")) { - return; + if (val && SDL_strcasestr(val, "capture")) { + devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE; } } else if (SDL_strcmp(subsystem, "input") == 0) { /* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */ @@ -467,18 +470,33 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) devclass = SDL_UDEV_DEVICE_MOUSE; } else if (SDL_strcmp(val, "kbd") == 0) { devclass = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD; - } else { - return; } } else { /* We could be linked with libudev on a system that doesn't have udev running */ devclass = guess_device_class(dev); } } - } else { + } + + return devclass; +} + +static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) +{ + int devclass = 0; + const char *path; + SDL_UDEV_CallbackList *item; + + path = _this->syms.udev_device_get_devnode(dev); + if (!path) { return; } + devclass = device_class(dev); + if (!devclass) { + return; + } + /* Process callbacks */ for (item = _this->first; item; item = item->next) { item->callback(type, devclass, path); diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h index ff6399e40f416..60bef169c35f8 100644 --- a/src/core/linux/SDL_udev.h +++ b/src/core/linux/SDL_udev.h @@ -102,7 +102,7 @@ extern void SDL_UDEV_UnloadLibrary(void); extern int SDL_UDEV_LoadLibrary(void); extern void SDL_UDEV_Poll(void); extern int SDL_UDEV_Scan(void); -extern SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version); +extern SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class); extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb); extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb); extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 660887a93a907..6d55e9cc419dd 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -282,18 +282,20 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend struct input_id inpid; char *name; char product_string[128]; + int class = 0; - if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) { - SDL_zero(inpid); + SDL_zero(inpid); #ifdef SDL_USE_LIBUDEV - SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version); + SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class); #endif - } else { + if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 0) { /* When udev is enabled we only get joystick devices here, so there's no need to test them */ - if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) { + if (enumeration_method != ENUMERATION_LIBUDEV && + !(class & SDL_UDEV_DEVICE_JOYSTICK) && ( class || !GuessIsJoystick(fd))) { return 0; } + /* Could have vendor and product already from udev, but should agree with evdev */ if (ioctl(fd, EVIOCGID, &inpid) < 0) { return 0; } From a28ac29aa00f221515e93f09e0e75b490111ec2f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 25 Dec 2023 23:02:02 +0100 Subject: [PATCH 608/725] Add missing cursor types The flowing assert would trip: SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS) --- test/testwm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testwm.c b/test/testwm.c index 6efcb80276eb6..25b9d22f4f598 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -34,6 +34,14 @@ static const char *cursorNames[] = { "sizeALL", "NO", "hand", + "window top left", + "window top", + "window top right", + "window right", + "window bottom right", + "window bottom", + "window bottom left", + "window left" }; static int system_cursor = -1; static SDL_Cursor *cursor = NULL; From bbdd41f28729250fbc919d7985f09c2244cf5dd1 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 17:51:43 +0100 Subject: [PATCH 609/725] Fix windows touch using wrong axis for normalisation Regressed with 9302d7732dfbb3c6364da142efd06ea9846206c1 --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 89e05cd502546..cb23252e3ba46 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1230,7 +1230,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) for (i = 0; i < num_inputs; ++i) { PTOUCHINPUT input = &inputs[i]; const int w = (rect.right - rect.left); - const int h = (rect.right - rect.left); + const int h = (rect.bottom - rect.top); const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource); From d6fb0d91d8bbca01bd9e7ef0276f2014feba4f78 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 26 Dec 2023 09:54:39 -0800 Subject: [PATCH 610/725] Added testpen to the Visual Studio solution --- VisualC/SDL.sln | 11 ++ VisualC/tests/testpen/testpen.vcxproj | 204 ++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 VisualC/tests/testpen/testpen.vcxproj diff --git a/VisualC/SDL.sln b/VisualC/SDL.sln index ff6a2b463bb70..67484805ddbe6 100644 --- a/VisualC/SDL.sln +++ b/VisualC/SDL.sln @@ -50,6 +50,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsensor", "tests\testsen EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsurround", "tests\testsurround\testsurround.vcxproj", "{70B894A9-E306-49E8-ABC2-932A952A5E5F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpen", "tests\testpen\testpen.vcxproj", "{C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -250,6 +252,14 @@ Global {70B894A9-E306-49E8-ABC2-932A952A5E5F}.Release|Win32.Build.0 = Release|Win32 {70B894A9-E306-49E8-ABC2-932A952A5E5F}.Release|x64.ActiveCfg = Release|x64 {70B894A9-E306-49E8-ABC2-932A952A5E5F}.Release|x64.Build.0 = Release|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Debug|Win32.ActiveCfg = Debug|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Debug|Win32.Build.0 = Debug|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Debug|x64.ActiveCfg = Debug|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Debug|x64.Build.0 = Debug|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Release|Win32.ActiveCfg = Release|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Release|Win32.Build.0 = Release|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Release|x64.ActiveCfg = Release|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -277,6 +287,7 @@ Global {40FB7794-D3C3-4CFE-BCF4-A80C97635682} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {70B894A9-E306-49E8-ABC2-932A952A5E5F} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C320C9F2-1A8F-41D7-B02B-6338F872BCAD} diff --git a/VisualC/tests/testpen/testpen.vcxproj b/VisualC/tests/testpen/testpen.vcxproj new file mode 100644 index 0000000000000..dc1a28e0b7f1e --- /dev/null +++ b/VisualC/tests/testpen/testpen.vcxproj @@ -0,0 +1,204 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C4E04D18-EF76-4B42-B4C2-16A1BACDC1A3} + testpower + 10.0 + + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/testpower.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/testpower.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/testpower.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/testpower.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} + false + false + true + + + {da956fd3-e143-46f2-9fe5-c77bebc56b1a} + false + false + true + + + + + + + + + \ No newline at end of file From 74418e1aa814d0023bf6679678403d9d68f97370 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 26 Dec 2023 09:57:11 -0800 Subject: [PATCH 611/725] Made the cursor list check a compile time assert instead of a runtime one This will catch this being out of date more quickly in the future --- test/testwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testwm.c b/test/testwm.c index 25b9d22f4f598..72e77ef294512 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -43,6 +43,8 @@ static const char *cursorNames[] = { "window bottom left", "window left" }; +SDL_COMPILE_TIME_ASSERT(cursorNames, SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS); + static int system_cursor = -1; static SDL_Cursor *cursor = NULL; static SDL_bool relative_mode = SDL_FALSE; @@ -266,8 +268,6 @@ int main(int argc, char *argv[]) /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); - SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS); - if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { SDLTest_CommonQuit(state); return 1; From cae657140c9436a18dac94356efeb7b2a60208a0 Mon Sep 17 00:00:00 2001 From: Alynne Date: Tue, 26 Dec 2023 00:32:10 -0500 Subject: [PATCH 612/725] Add Access Controller --- src/joystick/controller_list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 5a631ba8f20bf..63175ac47f2e7 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -151,6 +151,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x054c, 0x0ce6 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Controller { MAKE_CONTROLLER_ID( 0x054c, 0x0df2 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Edge Controller + { MAKE_CONTROLLER_ID( 0x054c, 0x0e5f ), k_eControllerType_PS5Controller, NULL }, // Access Controller for PS5 { MAKE_CONTROLLER_ID( 0x0e6f, 0x0209 ), k_eControllerType_PS5Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS5 mode) { MAKE_CONTROLLER_ID( 0x0f0d, 0x0163 ), k_eControllerType_PS5Controller, NULL }, // HORI Fighting Commander OCTA { MAKE_CONTROLLER_ID( 0x0f0d, 0x0184 ), k_eControllerType_PS5Controller, NULL }, // Hori Fighting Stick α From 50e309bb1745efc6f19841567f6dd25bcc998c93 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 26 Dec 2023 10:11:48 -0800 Subject: [PATCH 613/725] Include SDL_events.h in SDL_main.h Applications shouldn't need to include it separately if they want to process events using the main callbacks. Fixes https://github.com/libsdl-org/SDL/issues/8746 --- include/SDL3/SDL_main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 05ae074b964ee..e914415193c72 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -23,6 +23,7 @@ #define SDL_main_h_ #include +#include /* * For details on how SDL_main works, and how to use it, please refer to: @@ -157,10 +158,9 @@ extern "C" { #endif -union SDL_Event; typedef int (SDLCALL *SDL_AppInit_func)(int argc, char *argv[]); typedef int (SDLCALL *SDL_AppIterate_func)(void); -typedef int (SDLCALL *SDL_AppEvent_func)(const union SDL_Event *event); +typedef int (SDLCALL *SDL_AppEvent_func)(const SDL_Event *event); typedef void (SDLCALL *SDL_AppQuit_func)(void); /** From a3b5eb07b22824fc8e902067dc2f668ba947b615 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 26 Dec 2023 10:19:22 -0800 Subject: [PATCH 614/725] Removed extern "C" linkage from main() declaration According to the C++ spec, main() should not have any linkage specifier: https://en.cppreference.com/w/cpp/language/main_function Fixes https://github.com/libsdl-org/SDL/issues/8738 --- include/SDL3/SDL_main_impl.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index dd35dbd52c0a3..8eb8bb54952a4 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -72,12 +72,6 @@ int SDL_main(int argc, char **argv) #define WINAPI __stdcall #endif -#include - -#ifdef __cplusplus -extern "C" { -#endif - typedef struct HINSTANCE__ * HINSTANCE; typedef char* LPSTR; typedef wchar_t* PWSTR; @@ -119,12 +113,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) return SDL_RunApp(0, NULL, SDL_main, NULL); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#include - /* end of __WIN32__ and __GDK__ impls */ #elif defined(__WINRT__) @@ -196,23 +184,11 @@ TInt E32Main() #else /* platforms that use a standard main() and just call SDL_RunApp(), like iOS and 3DS */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - int main(int argc, char *argv[]) { return SDL_RunApp(argc, argv, SDL_main, NULL); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#include - /* end of impls for standard-conforming platforms */ #endif /* __WIN32__ etc */ From a961066d0bd3540d9c6bdc1f93f69bf6a400e639 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 20:16:05 +0100 Subject: [PATCH 615/725] Add basic touch/finger support to `testpen.c` Reuses the pen code as much as possible. Seems like the right place, see https://github.com/libsdl-org/SDL/pull/8749#issuecomment-1869671334. --- test/testpen.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/testpen.c b/test/testpen.c index aa92f7f54de6a..a193e0840856b 100644 --- a/test/testpen.c +++ b/test/testpen.c @@ -308,6 +308,15 @@ static void update_axes(float *axes) last_rotation = axes[SDL_PEN_AXIS_ROTATION]; } +static void update_axes_from_touch(const float pressure) +{ + last_xtilt = 0; + last_ytilt = 0; + last_pressure = pressure; + last_distance = 0; + last_rotation = 0; +} + static void process_event(SDL_Event event) { SDLTest_CommonEvent(state, &event, &quitting); @@ -341,7 +350,7 @@ static void process_event(SDL_Event event) } } #endif - if (event.motion.which != SDL_PEN_MOUSEID) { + if (event.motion.which != SDL_PEN_MOUSEID && event.motion.which != SDL_TOUCH_MOUSEID) { SDL_ShowCursor(); } break; @@ -444,6 +453,31 @@ static void process_event(SDL_Event event) break; #endif + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_MOTION: + case SDL_EVENT_FINGER_UP: + { + SDL_TouchFingerEvent *ev = &event.tfinger; + int w, h; + SDL_HideCursor(); + SDL_GetWindowSize(SDL_GetWindowFromID(ev->windowID), &w, &h); + last_x = ev->x * w; + last_y = ev->y * h; + update_axes_from_touch(ev->pressure); + last_was_eraser = SDL_FALSE; + last_button = 0; + last_touching = (ev->type != SDL_EVENT_FINGER_UP); +#if VERBOSE + SDL_Log("[%lu] finger %s: %s (touchId: %" SDL_PRIs64 ", fingerId: %" SDL_PRIs64 ") at (%.4f, %.4f); pressure=%.3f\n", + (unsigned long) ev->timestamp, + ev->type == SDL_EVENT_FINGER_DOWN ? "down" : (ev->type == SDL_EVENT_FINGER_MOTION ? "motion" : "up"), + SDL_GetTouchDeviceName(ev->touchId), + ev->touchId, + ev->fingerId, + last_x, last_y, last_pressure); +#endif + } break; + default: break; } From d747daf03d3210a794d609b8cc662f28beaedaf6 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 21:08:51 +0100 Subject: [PATCH 616/725] Use correct touch check flag Matches the one in `GetMouseMessageSource()`. From my testing on Windows 11, the lower 8 bits in touch events cycle trough the values 0x8c-0x95 in order. --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index cb23252e3ba46..efb22db0d2e01 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -668,7 +668,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_MouseID mouseID; RAWMOUSE *rawmouse; if (SDL_TouchDevicesAvailable() && - (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x82) == 0x82)) { + (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x80) == 0x80)) { break; } /* We do all of our mouse state checking against mouse ID 0 From a3c8f2f6cb7626f28f8bb880f1c8e6510f2e9510 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 21:15:58 +0100 Subject: [PATCH 617/725] Consolidate mouse-touch event checking logic Saves one `GetMessageExtraInfo()` syscall when handling WM_INPUT events. Will provide consistent results across various event types. --- src/video/windows/SDL_windowsevents.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index efb22db0d2e01..eadbe0a39478b 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -421,6 +421,11 @@ static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource() return SDL_MOUSE_EVENT_SOURCE_PEN; } } + /* Sometimes WM_INPUT events won't have the correct touch signature, + so we have to rely purely on the touch bit being set. */ + if (SDL_TouchDevicesAvailable() && extrainfo & 0x80) { + return SDL_MOUSE_EVENT_SOURCE_TOUCH; + } return SDL_MOUSE_EVENT_SOURCE_MOUSE; } #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ @@ -667,8 +672,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (inp.header.dwType == RIM_TYPEMOUSE) { SDL_MouseID mouseID; RAWMOUSE *rawmouse; - if (SDL_TouchDevicesAvailable() && - (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x80) == 0x80)) { + if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH) { break; } /* We do all of our mouse state checking against mouse ID 0 From c2a55cd2c501ebb491773171d19f5f06d94ca258 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 21:18:02 +0100 Subject: [PATCH 618/725] Add missing `(void)` in functions params --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index eadbe0a39478b..3a950a26a0245 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -406,7 +406,7 @@ typedef enum SDL_MOUSE_EVENT_SOURCE_PEN, } SDL_MOUSE_EVENT_SOURCE; -static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource() +static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource(void) { LPARAM extrainfo = GetMessageExtraInfo(); /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ From e0df963ef0ffd517d7ed09b4acd335177ceede0d Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 21:21:17 +0100 Subject: [PATCH 619/725] Fix wrong bit count in comment If we're counting bits from 0, then the MSB is bit 31! --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 3a950a26a0245..36a042c80e944 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -411,7 +411,7 @@ static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource(void) LPARAM extrainfo = GetMessageExtraInfo(); /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ /* Versions below Vista will set the low 7 bits to the Mouse ID and don't use bit 7: - Check bits 8-32 for the signature (which will indicate a Tablet PC Pen or Touch Device). + Check bits 8-31 for the signature (which will indicate a Tablet PC Pen or Touch Device). Only check bit 7 when Vista and up(Cleared=Pen, Set=Touch(which we need to filter out)), when the signature is set. The Mouse ID will be zero for an actual mouse. */ if (IsTouchEvent(extrainfo)) { From 5d6d1498620240abe0c063b9772dfc78e8e8b46a Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 26 Dec 2023 21:46:56 +0100 Subject: [PATCH 620/725] Allow passing in `extrainfo` value to `GetMouseMessageSource()` This saves a syscall in WM_INPUT handling --- src/video/windows/SDL_windowsevents.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 36a042c80e944..166053244f6cf 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -406,9 +406,8 @@ typedef enum SDL_MOUSE_EVENT_SOURCE_PEN, } SDL_MOUSE_EVENT_SOURCE; -static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource(void) +static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource(ULONG extrainfo) { - LPARAM extrainfo = GetMessageExtraInfo(); /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ /* Versions below Vista will set the low 7 bits to the Mouse ID and don't use bit 7: Check bits 8-31 for the signature (which will indicate a Tablet PC Pen or Touch Device). @@ -620,7 +619,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (!mouse->relative_mode || mouse->relative_mode_warp) { /* Only generate mouse events for real mouse */ - if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH && + if (GetMouseMessageSource((ULONG)GetMessageExtraInfo()) != SDL_MOUSE_EVENT_SOURCE_TOUCH && lParam != data->last_pointer_update) { SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, 0, 0, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam)); } @@ -642,7 +641,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { SDL_Mouse *mouse = SDL_GetMouse(); if (!mouse->relative_mode || mouse->relative_mode_warp) { - if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH && + if (GetMouseMessageSource((ULONG)GetMessageExtraInfo()) != SDL_MOUSE_EVENT_SOURCE_TOUCH && lParam != data->last_pointer_update) { WIN_CheckWParamMouseButtons(wParam, data, 0); } @@ -672,7 +671,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (inp.header.dwType == RIM_TYPEMOUSE) { SDL_MouseID mouseID; RAWMOUSE *rawmouse; - if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH) { + if (GetMouseMessageSource(inp.data.mouse.ulExtraInformation) == SDL_MOUSE_EVENT_SOURCE_TOUCH) { break; } /* We do all of our mouse state checking against mouse ID 0 From 4ce935b9106a0311436e41c5f28f00db30a93de1 Mon Sep 17 00:00:00 2001 From: Reilly Brogan Date: Tue, 26 Dec 2023 17:58:21 -0600 Subject: [PATCH 621/725] Fix static build with libdecor 0.2.0 --- src/video/wayland/SDL_waylandsym.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h index 513f77a6b6232..bc178d014cc78 100644 --- a/src/video/wayland/SDL_waylandsym.h +++ b/src/video/wayland/SDL_waylandsym.h @@ -221,10 +221,10 @@ SDL_WAYLAND_SYM(int, libdecor_dispatch, (struct libdecor *, int)) #if defined(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR) || defined(SDL_HAVE_LIBDECOR_VER_0_2_0) /* Only found in libdecor 0.1.1 or higher, so failure to load them is not fatal. */ -SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_min_content_size, (struct libdecor_frame *,\ +SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_min_content_size, (const struct libdecor_frame *,\ int *,\ int *)) -SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_max_content_size, (struct libdecor_frame *,\ +SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_max_content_size, (const struct libdecor_frame *,\ int *,\ int *)) #endif From 0dfdf1f3f2a1f62e579527ef3abe63543af7e6da Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 27 Dec 2023 11:25:54 -0800 Subject: [PATCH 622/725] Fixed crash if joystick functions are passed a NULL joystick --- src/joystick/SDL_joystick.c | 46 +++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 1948c3a942287..5e21dd95d8dd3 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1521,13 +1521,17 @@ const char *SDL_GetJoystickName(SDL_Joystick *joystick) const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); - info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); - if (info) { - retval = info->name; - } else { + { CHECK_JOYSTICK_MAGIC(joystick, NULL); - retval = joystick->name; + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + retval = info->name; + } else { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + retval = joystick->name; + } } SDL_UnlockJoysticks(); @@ -3247,13 +3251,17 @@ Uint16 SDL_GetJoystickVendor(SDL_Joystick *joystick) const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); - info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); - if (info) { - vendor = info->vendor_id; - } else { - SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + vendor = info->vendor_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + + SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); + } } SDL_UnlockJoysticks(); @@ -3266,13 +3274,17 @@ Uint16 SDL_GetJoystickProduct(SDL_Joystick *joystick) const SDL_SteamVirtualGamepadInfo *info; SDL_LockJoysticks(); - info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); - if (info) { - product = info->product_id; - } else { - SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); + info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id); + if (info) { + product = info->product_id; + } else { + SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick); + + SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); + } } SDL_UnlockJoysticks(); From 5df3eac925af8491259032ed275c1ec3e0e8e80b Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Wed, 27 Dec 2023 20:21:11 +0000 Subject: [PATCH 623/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_filesystem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 996030662ea0e..79024d2168f5e 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -64,7 +64,7 @@ extern "C" { * directory of the application as it is uncommon to store resources outside * the executable. As such it is not a writable directory. * - * The returned path is guaranteed to end with a path separator ('\' on + * The returned path is guaranteed to end with a path separator ('\\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the @@ -120,7 +120,7 @@ extern DECLSPEC char *SDLCALL SDL_GetBasePath(void); * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. * - * The returned path is guaranteed to end with a path separator ('\' on + * The returned path is guaranteed to end with a path separator ('\\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the From 9c3e831e33062b605f6ee85bb790a3be99bb52e5 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 27 Dec 2023 17:08:46 -0500 Subject: [PATCH 624/725] uikit: Send fullscreen enter/leave events Send fullscreen enter/leave events, which will implicitly update the fullscreen flag. Manually setting the flag will suppress attempts to send the events later, as the flag is used for deduplication purposes in the event code. --- src/video/uikit/SDL_uikitwindow.m | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 7e510bf517ae1..8f515e10c72e5 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -309,11 +309,7 @@ void UIKit_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_boo int UIKit_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) { @autoreleasepool { - if (fullscreen) { - window->flags |= SDL_WINDOW_FULLSCREEN; - } else { - window->flags &= ~SDL_WINDOW_FULLSCREEN; - } + SDL_SendWindowEvent(window, fullscreen ? SDL_EVENT_WINDOW_ENTER_FULLSCREEN : SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); UIKit_UpdateWindowBorder(_this, window); } return 0; From ce329d60e469f9653b18ddcd317e1aede50933ac Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 09:33:02 -0800 Subject: [PATCH 625/725] Added support for alpha blending using palette alpha Fixes https://github.com/libsdl-org/SDL_image/issues/409 --- src/video/SDL_blit_1.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/video/SDL_blit_1.c b/src/video/SDL_blit_1.c index 2c54a2e84a516..1a398da6a252a 100644 --- a/src/video/SDL_blit_1.c +++ b/src/video/SDL_blit_1.c @@ -435,7 +435,7 @@ static void Blit1toNAlpha(SDL_BlitInfo *info) const SDL_Color *srcpal = info->src_fmt->palette->colors; int dstbpp; Uint32 pixel; - unsigned sR, sG, sB; + unsigned sR, sG, sB, sA; unsigned dR, dG, dB, dA; const unsigned A = info->a; @@ -449,8 +449,9 @@ static void Blit1toNAlpha(SDL_BlitInfo *info) sR = srcpal[*src].r; sG = srcpal[*src].g; sB = srcpal[*src].b; + sA = (srcpal[*src].a * A) / 255; DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); - ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); + ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); src++; dst += dstbpp; @@ -475,7 +476,7 @@ static void Blit1toNAlphaKey(SDL_BlitInfo *info) Uint32 ckey = info->colorkey; int dstbpp; Uint32 pixel; - unsigned sR, sG, sB; + unsigned sR, sG, sB, sA; unsigned dR, dG, dB, dA; const unsigned A = info->a; @@ -490,8 +491,9 @@ static void Blit1toNAlphaKey(SDL_BlitInfo *info) sR = srcpal[*src].r; sG = srcpal[*src].g; sB = srcpal[*src].b; + sA = (srcpal[*src].a * A) / 255; DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); - ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); + ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA); ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); } src++; @@ -531,8 +533,10 @@ SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface *surface) return one_blitkey[which]; case SDL_COPY_COLORKEY | SDL_COPY_BLEND: /* this is not super-robust but handles a specific case we found sdl12-compat. */ - return (surface->map->info.a == 255) ? one_blitkey[which] : (SDL_BlitFunc)NULL; + return (surface->map->info.a == 255) ? one_blitkey[which] : + which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc)NULL; + case SDL_COPY_BLEND: case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: /* Supporting 8bpp->8bpp alpha is doable but requires lots of tables which consume space and takes time to precompute, From 70ba3f2830bdadd330ac189a6e4905b4645fd1da Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 27 Dec 2023 11:28:27 -0800 Subject: [PATCH 626/725] Report the D-Pad for HIDAPI gamepads as a hat This makes it easier for games that don't use the gamepad API to handle D-Pad navigation, and is consistent with many other non-HIDAPI mappings. Fixes https://github.com/libsdl-org/SDL/issues/8754 --- src/joystick/SDL_gamepad.c | 50 ++++---- src/joystick/SDL_gamepad_db.h | 4 +- src/joystick/hidapi/SDL_hidapi_luna.c | 77 +++++------- src/joystick/hidapi/SDL_hidapi_ps3.c | 138 ++++++++++---------- src/joystick/hidapi/SDL_hidapi_ps4.c | 44 +++---- src/joystick/hidapi/SDL_hidapi_ps5.c | 94 ++++++-------- src/joystick/hidapi/SDL_hidapi_shield.c | 89 ++++++------- src/joystick/hidapi/SDL_hidapi_stadia.c | 44 +++---- src/joystick/hidapi/SDL_hidapi_steam.c | 37 ++++-- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 47 ++++--- src/joystick/hidapi/SDL_hidapi_switch.c | 139 ++++++++++++--------- src/joystick/hidapi/SDL_hidapi_xbox360.c | 23 +++- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 20 ++- src/joystick/hidapi/SDL_hidapi_xboxone.c | 75 ++++++----- 14 files changed, 454 insertions(+), 427 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 0543b9dbbca91..e8fe5fdf85edf 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -721,26 +721,26 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid guid.data[15] == k_eSwitchDeviceInfoControllerType_JoyConRight)) { switch (guid.data[15]) { case k_eSwitchDeviceInfoControllerType_HVCLeft: - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_HVCRight: - SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_NESLeft: case k_eSwitchDeviceInfoControllerType_NESRight: - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_SNES: - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_N64: - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: - SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,rightshoulder:b10,righttrigger:a5,start:b6,misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,rightshoulder:b10,righttrigger:a5,start:b6,misc1:b11,", sizeof(mapping_string)); break; case k_eWiiExtensionControllerType_None: - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,x:b2,y:b3,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,start:b6,x:b2,y:b3,", sizeof(mapping_string)); break; case k_eWiiExtensionControllerType_Nunchuk: { @@ -757,67 +757,67 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, SDL_FALSE)) { /* Vertical mode */ if (guid.data[15] == k_eSwitchDeviceInfoControllerType_JoyConLeft) { - SDL_strlcat(mapping_string, "back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,paddle2:b17,paddle4:b19,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle2:b13,paddle4:b15,", sizeof(mapping_string)); } else { - SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,paddle1:b16,paddle3:b18,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,paddle1:b12,paddle3:b14,", sizeof(mapping_string)); } } else { /* Mini gamepad mode */ if (guid.data[15] == k_eSwitchDeviceInfoControllerType_JoyConLeft) { - SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,paddle2:b17,paddle4:b19,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,paddle2:b13,paddle4:b15,", sizeof(mapping_string)); } else { - SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,paddle1:b16,paddle3:b18,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,paddle1:b12,paddle3:b14,", sizeof(mapping_string)); } } break; } } else { /* All other gamepads have the standard set of 19 buttons and 6 axes */ - SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string)); if (SDL_IsJoystickXboxSeriesX(vendor, product)) { /* XBox Series X Controllers have a share button under the guide button */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickXboxOneElite(vendor, product)) { /* XBox One Elite Controllers have 4 back paddle buttons */ - SDL_strlcat(mapping_string, "paddle1:b15,paddle2:b17,paddle3:b16,paddle4:b18,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,", sizeof(mapping_string)); } else if (SDL_IsJoystickSteamController(vendor, product)) { /* Steam controllers have 2 back paddle buttons */ - SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "paddle1:b12,paddle2:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickNintendoSwitchJoyConPair(vendor, product)) { /* The Nintendo Switch Joy-Con combined controllers has a share button and paddles */ - SDL_strlcat(mapping_string, "misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,", sizeof(mapping_string)); } else if (SDL_IsJoystickAmazonLunaController(vendor, product)) { /* Amazon Luna Controller has a mic button under the guide button */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickGoogleStadiaController(vendor, product)) { /* The Google Stadia controller has a share button and a Google Assistant button */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickNVIDIASHIELDController(vendor, product)) { /* The NVIDIA SHIELD controller has a share button between back and start buttons */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); if (product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103) { /* The original SHIELD controller has a touchpad as well */ - SDL_strlcat(mapping_string, "touchpad:b16,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "touchpad:b12,", sizeof(mapping_string)); } } else if (SDL_IsJoystickPS4(vendor, product)) { /* PS4 controllers have an additional touchpad button */ - SDL_strlcat(mapping_string, "touchpad:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "touchpad:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickPS5(vendor, product)) { /* PS5 controllers have a microphone button and an additional touchpad button */ - SDL_strlcat(mapping_string, "touchpad:b15,misc1:b16,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "touchpad:b11,misc1:b12,", sizeof(mapping_string)); /* DualSense Edge controllers have paddles */ if (SDL_IsJoystickDualSenseEdge(vendor, product)) { - SDL_strlcat(mapping_string, "paddle1:b20,paddle2:b19,paddle3:b18,paddle4:b17,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string)); } } else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) || SDL_IsJoystickNintendoSwitchProInputOnly(vendor, product)) { /* Nintendo Switch Pro controllers have a screenshot button */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (vendor == 0 && product == 0) { /* This is a Bluetooth Nintendo Switch Pro controller */ - SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } } diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 1cbfde1a0a82d..886d7a93416c2 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -557,7 +557,7 @@ static const char *s_GamepadMappings[] = { "030000000d0f00008500000010010000,HORI Fighting Commander,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:a3,start:b9,x:b0,y:b3,", "030000000d0f00008800000011010000,HORI Fighting Stick mini 4 (PS3),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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,", "030000000d0f00008700000011010000,HORI Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,", - "030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", + "030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "030000000d0f00006e00000011010000,HORIPAD 4 (PS3),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:a3,start:b9,x:b0,y:b3,", "030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -726,8 +726,8 @@ static const char *s_GamepadMappings[] = { "05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "03000000de2800000512000000016800,Steam Deck,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,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,", - "03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,misc1:b15,paddle1:b16,paddle2:b17,paddle3:b18,paddle4:b19,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b6,leftstick:b13,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:+a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 4e02b5f1a2a44..27476ab34586a 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -38,8 +38,8 @@ enum { - SDL_CONTROLLER_BUTTON_LUNA_MIC = 15, - SDL_CONTROLLER_NUM_LUNA_BUTTONS, + SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE = 11, + SDL_GAMEPAD_NUM_LUNA_BUTTONS, }; typedef struct @@ -100,8 +100,9 @@ static SDL_bool HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ - joystick->nbuttons = SDL_CONTROLLER_NUM_LUNA_BUTTONS; + joystick->nbuttons = SDL_GAMEPAD_NUM_LUNA_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL; return SDL_TRUE; @@ -179,53 +180,44 @@ static void HIDAPI_DriverLuna_HandleUSBStatePacket(SDL_Joystick *joystick, SDL_D } if (ctx->last_state[2] != data[2]) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_LUNA_MIC, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); } if (ctx->last_state[3] != data[3]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; - switch (data[3] & 0xf) { + switch (data[3] & 0x0f) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } #define READ_STICK_AXIS(offset) \ @@ -287,47 +279,38 @@ static void HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick, } if (ctx->last_state[13] != data[13]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; - switch (data[13] & 0xf) { + switch (data[13] & 0x0f) { case 1: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 2: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 3: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 4: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 5: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 6: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 7: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 8: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (ctx->last_state[14] != data[14]) { @@ -345,7 +328,7 @@ static void HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick, } if (ctx->last_state[16] != data[16]) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_LUNA_MIC, (data[16] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE, (data[16] & 0x02) ? SDL_PRESSED : SDL_RELEASED); } #define READ_STICK_AXIS(offset) \ diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 7ff706eb07bdf..aee477df601f6 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -240,8 +240,9 @@ static SDL_bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy ctx->player_index = SDL_GetJoystickPlayerIndex(joystick); /* Initialize the joystick capabilities */ - joystick->nbuttons = 15; + joystick->nbuttons = 11; joystick->naxes = 16; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); @@ -314,47 +315,38 @@ static void HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_D Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[4] != data[4]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[4] & 0x0f) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED); @@ -391,14 +383,26 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[2] != data[2]) { + Uint8 hat = 0; + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + + if (data[2] & 0x10) { + hat |= SDL_HAT_UP; + } + if (data[2] & 0x20) { + hat |= SDL_HAT_RIGHT; + } + if (data[2] & 0x40) { + hat |= SDL_HAT_DOWN; + } + if (data[2] & 0x80) { + hat |= SDL_HAT_LEFT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (ctx->last_state[3] != data[3]) { @@ -639,8 +643,9 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *devic SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ - joystick->nbuttons = 15; + joystick->nbuttons = 11; joystick->naxes = 16; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; return SDL_TRUE; @@ -691,10 +696,7 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic } if (ctx->last_state[1] != data[1]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); @@ -703,40 +705,34 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic switch (data[1] >> 4) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } axis = ((int)data[16] * 257) - 32768; @@ -813,53 +809,55 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic if (ctx->device->vendor_id == USB_VENDOR_SAITEK && ctx->device->product_id == USB_PRODUCT_SAITEK_CYBORG_V3) { /* Cyborg V.3 Rumble Pad doesn't set the dpad bits as expected, so use the axes instead */ - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, data[10] ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, data[9] ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, data[7] ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, data[8] ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data[7]) { + hat |= SDL_HAT_RIGHT; + } + if (data[8]) { + hat |= SDL_HAT_LEFT; + } + if (data[9]) { + hat |= SDL_HAT_UP; + } + if (data[10]) { + hat |= SDL_HAT_DOWN; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } else { if (ctx->last_state[2] != data[2]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[2] & 0x0f) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } } diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index e7d76c463724d..550da29085796 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -50,6 +50,11 @@ (((Uint32)(C)) << 16) | \ (((Uint32)(D)) << 24)) +enum +{ + SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD = 11 +}; + typedef enum { k_EPS4ReportIdUsbState = 1, @@ -820,8 +825,12 @@ static SDL_bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy ctx->player_index = SDL_GetJoystickPlayerIndex(joystick); /* Initialize the joystick capabilities */ - joystick->nbuttons = ctx->touchpad_supported ? 16 : 15; + joystick->nbuttons = 11; + if (ctx->touchpad_supported) { + joystick->nbuttons += 1; + } joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; if (device->is_bluetooth) { /* We'll update this once we're in enhanced mode */ joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; @@ -985,48 +994,39 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); } { + Uint8 hat; Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F); - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; switch (data) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } } @@ -1054,7 +1054,7 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); } axis = ((int)packet->ucTriggerLeft * 257) - 32768; diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index af66d21389995..add062d442f99 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -51,11 +51,12 @@ enum { - SDL_CONTROLLER_BUTTON_PS5_TOUCHPAD = SDL_GAMEPAD_BUTTON_MISC1 + 1, - SDL_CONTROLLER_BUTTON_PS5_LEFT_FUNCTION, - SDL_CONTROLLER_BUTTON_PS5_RIGHT_FUNCTION, - SDL_CONTROLLER_BUTTON_PS5_LEFT_PADDLE, - SDL_CONTROLLER_BUTTON_PS5_RIGHT_PADDLE + SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD = 11, + SDL_GAMEPAD_BUTTON_PS5_MICROPHONE, + SDL_GAMEPAD_BUTTON_PS5_LEFT_FUNCTION, + SDL_GAMEPAD_BUTTON_PS5_RIGHT_FUNCTION, + SDL_GAMEPAD_BUTTON_PS5_LEFT_PADDLE, + SDL_GAMEPAD_BUTTON_PS5_RIGHT_PADDLE }; typedef enum @@ -945,13 +946,14 @@ static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy /* Initialize the joystick capabilities */ if (SDL_IsJoystickDualSenseEdge(device->vendor_id, device->product_id)) { - joystick->nbuttons = 21; + joystick->nbuttons = 17; /* paddles and touchpad and microphone */ } else if (ctx->touchpad_supported) { - joystick->nbuttons = 17; + joystick->nbuttons = 13; /* touchpad and microphone */ } else { - joystick->nbuttons = 15; + joystick->nbuttons = 11; } joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; if (device->is_bluetooth) { /* We'll update this once we're in enhanced mode */ joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; @@ -1139,47 +1141,38 @@ static void HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL } { Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F); - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } } @@ -1198,7 +1191,7 @@ static void HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); } if (packet->ucTriggerLeft == 0 && (packet->rgucButtonsHatAndCounter[1] & 0x04)) { @@ -1240,47 +1233,38 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL } { Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F); - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } } @@ -1299,12 +1283,12 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL Uint8 data = packet->rgucButtonsAndHat[2]; SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_TOUCHPAD, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_LEFT_FUNCTION, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_RIGHT_FUNCTION, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_LEFT_PADDLE, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_RIGHT_PADDLE, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_MICROPHONE, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_LEFT_FUNCTION, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_RIGHT_FUNCTION, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_LEFT_PADDLE, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_RIGHT_PADDLE, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); } if (packet->ucTriggerLeft == 0 && (packet->rgucButtonsAndHat[1] & 0x04)) { diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 71ee72c767b87..5d38727f81392 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -46,12 +46,13 @@ enum { - SDL_CONTROLLER_BUTTON_SHIELD_V103_TOUCHPAD = SDL_GAMEPAD_BUTTON_MISC1 + 1, - SDL_CONTROLLER_BUTTON_SHIELD_V103_MINUS, - SDL_CONTROLLER_BUTTON_SHIELD_V103_PLUS, - SDL_CONTROLLER_NUM_SHIELD_V103_BUTTONS, + SDL_GAMEPAD_BUTTON_SHIELD_SHARE = 11, + SDL_GAMEPAD_BUTTON_SHIELD_V103_TOUCHPAD, + SDL_GAMEPAD_BUTTON_SHIELD_V103_MINUS, + SDL_GAMEPAD_BUTTON_SHIELD_V103_PLUS, + SDL_GAMEPAD_NUM_SHIELD_V103_BUTTONS, - SDL_CONTROLLER_NUM_SHIELD_V104_BUTTONS = SDL_GAMEPAD_BUTTON_MISC1 + 1, + SDL_GAMEPAD_NUM_SHIELD_V104_BUTTONS = SDL_GAMEPAD_BUTTON_SHIELD_SHARE + 1, }; typedef enum @@ -180,14 +181,16 @@ static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ /* Initialize the joystick capabilities */ if (device->product_id == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103) { - joystick->nbuttons = SDL_CONTROLLER_NUM_SHIELD_V103_BUTTONS; + joystick->nbuttons = SDL_GAMEPAD_NUM_SHIELD_V103_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; SDL_PrivateJoystickAddTouchpad(joystick, 1); } else { - joystick->nbuttons = SDL_CONTROLLER_NUM_SHIELD_V104_BUTTONS; + joystick->nbuttons = SDL_GAMEPAD_NUM_SHIELD_V104_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; } @@ -288,47 +291,38 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[3] != data[3]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[3]) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (ctx->last_state[1] != data[1]) { @@ -344,11 +338,11 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD if (ctx->last_state[2] != data[2]) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_PLUS, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_MINUS, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_PLUS, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_MINUS, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_SHARE, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); } SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_SwapLE16(*(Sint16 *)&data[4]) - 0x8000); @@ -372,7 +366,7 @@ static void HIDAPI_DriverShield_HandleTouchPacketV103(SDL_Joystick *joystick, SD float touchpad_x, touchpad_y; Uint64 timestamp = SDL_GetTicksNS(); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_TOUCHPAD, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_TOUCHPAD, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); /* It's a triangular pad, but just use the center as the usable touch area */ touchpad_state = !(data[1] & 0x80) ? SDL_PRESSED : SDL_RELEASED; @@ -390,47 +384,38 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD } if (ctx->last_state[2] != data[2]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[2]) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (ctx->last_state[3] != data[3]) { @@ -458,7 +443,7 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, SDL_SwapLE16(*(Sint16 *)&data[21]) - 0x8000); if (ctx->last_state[17] != data[17]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[17] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_SHARE, (data[17] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[17] & 0x02) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[17] & 0x04) ? SDL_PRESSED : SDL_RELEASED); } diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index e4883862cc80f..50d2dd1dbe7c6 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -33,9 +33,9 @@ enum { - SDL_CONTROLLER_BUTTON_STADIA_SHARE = 15, - SDL_CONTROLLER_BUTTON_STADIA_GOOGLE_ASSISTANT, - SDL_CONTROLLER_NUM_STADIA_BUTTONS, + SDL_GAMEPAD_BUTTON_STADIA_SHARE = 11, + SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, + SDL_GAMEPAD_NUM_STADIA_BUTTONS, }; typedef struct @@ -106,8 +106,9 @@ static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ - joystick->nbuttons = SDL_CONTROLLER_NUM_STADIA_BUTTONS; + joystick->nbuttons = SDL_GAMEPAD_NUM_STADIA_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; return SDL_TRUE; @@ -178,47 +179,38 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr } if (ctx->last_state[1] != data[1]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[1]) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (ctx->last_state[2] != data[2]) { @@ -226,8 +218,8 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); } if (ctx->last_state[3] != data[3]) { diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 2825a529549b5..bbc5f70227e55 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -36,6 +36,13 @@ #include "steam/controller_constants.h" #include "steam/controller_structs.h" +enum +{ + SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE = 11, + SDL_GAMEPAD_BUTTON_STEAM_LEFT_PADDLE, + SDL_GAMEPAD_NUM_STEAM_BUTTONS, +}; + typedef struct SteamControllerStateInternal_t { // Controller Type for this Controller State @@ -1018,8 +1025,9 @@ static SDL_bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_J InitializeSteamControllerPacketAssembler(&ctx->m_assembler); /* Initialize the joystick capabilities */ - joystick->nbuttons = 17; + joystick->nbuttons = SDL_GAMEPAD_NUM_STEAM_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz); SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz); @@ -1114,6 +1122,8 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) Uint64 timestamp = SDL_GetTicksNS(); if (ctx->m_state.ulButtons != ctx->m_last_state.ulButtons) { + Uint8 hat = 0; + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED); @@ -1143,19 +1153,24 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (ctx->m_state.ulButtons & STEAM_JOYSTICK_BUTTON_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1 + 0, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_LEFT_PADDLE, (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1 + 1, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE, (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, - (ctx->m_state.ulButtons & STEAM_TOUCH_0_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, - (ctx->m_state.ulButtons & STEAM_TOUCH_3_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, - (ctx->m_state.ulButtons & STEAM_TOUCH_2_MASK) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - (ctx->m_state.ulButtons & STEAM_TOUCH_1_MASK) ? SDL_PRESSED : SDL_RELEASED); + if (ctx->m_state.ulButtons & STEAM_TOUCH_0_MASK) { + hat |= SDL_HAT_UP; + } + if (ctx->m_state.ulButtons & STEAM_TOUCH_3_MASK) { + hat |= SDL_HAT_DOWN; + } + if (ctx->m_state.ulButtons & STEAM_TOUCH_2_MASK) { + hat |= SDL_HAT_LEFT; + } + if (ctx->m_state.ulButtons & STEAM_TOUCH_1_MASK) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (int)ctx->m_state.sTriggerL * 2 - 32768); diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index e27dd2a40f2c2..7b606b8bf8bb6 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -32,6 +32,16 @@ #include "steam/controller_constants.h" #include "steam/controller_structs.h" +enum +{ + SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM = 11, + SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1, + SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1, + SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2, + SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2, + SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS, +}; + typedef enum { STEAMDECK_LBUTTON_R2 = 0x00000001, @@ -248,6 +258,8 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) Uint64 timestamp = SDL_GetTicksNS(); if (pInReport->payload.deckState.ulButtons != ctx->last_button_state) { + Uint8 hat = 0; + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_A) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, @@ -268,7 +280,7 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MENU) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STEAM) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM, (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_QAM) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, @@ -276,23 +288,29 @@ static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R3) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1, (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_R4) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1, (pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_L4) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R5) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2, (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L5) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_DOWN) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_LEFT) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_RIGHT) ? SDL_PRESSED : SDL_RELEASED); + if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) { + hat |= SDL_HAT_UP; + } + if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_DOWN) { + hat |= SDL_HAT_DOWN; + } + if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_LEFT) { + hat |= SDL_HAT_LEFT; + } + if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_RIGHT) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + ctx->last_button_state = pInReport->payload.deckState.ulButtons; } @@ -333,8 +351,9 @@ static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, S SDL_AssertJoysticksLocked(); // Initialize the joystick capabilities - joystick->nbuttons = 20; + joystick->nbuttons = SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz); SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz); diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index b4f2d9a9c91a2..62c61562fa51d 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -63,6 +63,16 @@ #define SWITCH_ACCEL_SCALE_OFFSET 16384.0f #define SWITCH_ACCEL_SCALE_MULT 4.0f +enum +{ + SDL_GAMEPAD_BUTTON_SWITCH_SHARE = 11, + SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, + SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, + SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, + SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, + SDL_GAMEPAD_NUM_SWITCH_BUTTONS, +}; + typedef enum { k_eSwitchInputReportIDs_SubcommandReply = 0x21, @@ -1433,8 +1443,9 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ SDL_PlayerLEDHintChanged, ctx); /* Initialize the joystick capabilities */ - joystick->nbuttons = 20; + joystick->nbuttons = SDL_GAMEPAD_NUM_SWITCH_BUTTONS; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = device->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED; /* Set up for input */ @@ -1671,51 +1682,42 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); } if (packet->ucStickHat != ctx->m_lastInputOnlyState.ucStickHat) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (packet->ucStickHat) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } if (packet->rgucJoystickLeft[0] != ctx->m_lastInputOnlyState.rgucJoystickLeft[0]) { @@ -1769,51 +1771,42 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); } if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (packet->ucStickHat) { case 0: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 1: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 2: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 3: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 4: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 5: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 6: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 7: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } axis = ApplySimpleStickCalibration(ctx, 0, 0, packet->sJoystickLeft[0]); @@ -1882,17 +1875,29 @@ static void HandleCombinedControllerStateL(Uint64 timestamp, SDL_Joystick *joyst Uint8 data = packet->controllerState.rgucButtons[1]; SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); } if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) { Uint8 data = packet->controllerState.rgucButtons[2]; - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data & 0x01) { + hat |= SDL_HAT_DOWN; + } + if (data & 0x02) { + hat |= SDL_HAT_UP; + } + if (data & 0x04) { + hat |= SDL_HAT_RIGHT; + } + if (data & 0x08) { + hat |= SDL_HAT_LEFT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); axis = (data & 0x80) ? 32767 : -32768; SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); @@ -1926,8 +1931,8 @@ static void HandleMiniControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); } axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8); @@ -1949,8 +1954,8 @@ static void HandleCombinedControllerStateR(Uint64 timestamp, SDL_Joystick *joyst SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); axis = (data & 0x80) ? 32767 : -32768; SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); @@ -1984,8 +1989,8 @@ static void HandleMiniControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED); } if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) { @@ -2042,15 +2047,27 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED); } if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) { Uint8 data = packet->controllerState.rgucButtons[2]; - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data & 0x01) { + hat |= SDL_HAT_DOWN; + } + if (data & 0x02) { + hat |= SDL_HAT_UP; + } + if (data & 0x04) { + hat |= SDL_HAT_RIGHT; + } + if (data & 0x08) { + hat |= SDL_HAT_LEFT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED); axis = (data & 0x80) ? 32767 : -32768; SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index c71ea3b329a2a..bcccbc7dbb9f1 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -187,8 +187,9 @@ static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL SDL_PlayerLEDHintChanged, ctx); /* Initialize the joystick capabilities */ - joystick->nbuttons = 15; + joystick->nbuttons = 11; joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; return SDL_TRUE; @@ -269,10 +270,22 @@ static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_D Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[2] != data[2]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data[2] & 0x01) { + hat |= SDL_HAT_UP; + } + if (data[2] & 0x02) { + hat |= SDL_HAT_DOWN; + } + if (data[2] & 0x04) { + hat |= SDL_HAT_LEFT; + } + if (data[2] & 0x08) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 411f5ae3b5b4e..b7e69b7c94803 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -236,10 +236,22 @@ static void HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_ Uint64 timestamp = SDL_GetTicksNS(); if (ctx->last_state[2] != data[2]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data[2] & 0x01) { + hat |= SDL_HAT_UP; + } + if (data[2] & 0x02) { + hat |= SDL_HAT_DOWN; + } + if (data[2] & 0x04) { + hat |= SDL_HAT_LEFT; + } + if (data[2] & 0x08) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED); diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 5cf5deda8ee1a..096bff1ed6d4c 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -49,6 +49,11 @@ #define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689 #define XINPUT_GAMEPAD_TRIGGER_THRESHOLD -25058 /* Uint8 30 scaled to Sint16 full range */ +enum +{ + SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON = 11 +}; + /* Power on */ static const Uint8 xbox_init_power_on[] = { 0x05, 0x20, 0x00, 0x01, 0x00 @@ -417,7 +422,7 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ - joystick->nbuttons = 15; + joystick->nbuttons = 11; if (ctx->has_share_button) { joystick->nbuttons += 1; } @@ -425,6 +430,7 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL joystick->nbuttons += 4; } joystick->naxes = SDL_GAMEPAD_AXIS_MAX; + joystick->nhats = 1; if (!device->is_bluetooth) { joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; @@ -630,7 +636,7 @@ static void HIDAPI_DriverXboxOne_HandleUnmappedStatePacket(SDL_Joystick *joystic } if (ctx->last_paddle_state != data[paddle_index]) { - Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_MISC1 + ctx->has_share_button); /* Next available button */ + Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON + ctx->has_share_button); /* Next available button */ SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED); @@ -665,10 +671,22 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D } if (ctx->last_state[1] != data[1]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + Uint8 hat = 0; + + if (data[2] & 0x01) { + hat |= SDL_HAT_UP; + } + if (data[2] & 0x02) { + hat |= SDL_HAT_DOWN; + } + if (data[2] & 0x04) { + hat |= SDL_HAT_LEFT; + } + if (data[2] & 0x08) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + if (ctx->vendor_id == USB_VENDOR_RAZER && ctx->product_id == USB_PRODUCT_RAZER_ATROX) { /* The Razer Atrox has the right and left shoulder bits reversed */ SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED); @@ -690,19 +708,19 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D */ if (size < 44) { if (ctx->last_state[14] != data[14]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } } else if (size == 44) { if (ctx->last_state[18] != data[18]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[18] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[18] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } } else if (size == 46) { if (ctx->last_state[28] != data[28]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[28] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[28] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } } else if (size == 60) { if (ctx->last_state[42] != data[42]) { - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[42] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[42] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } } } @@ -785,7 +803,7 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D } if (ctx->last_paddle_state != data[paddle_index]) { - Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_MISC1 + ctx->has_share_button); /* Next available button */ + Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON + ctx->has_share_button); /* Next available button */ SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED); @@ -893,7 +911,7 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Jo if (ctx->has_share_button) { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } else { SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[15] & 0x04) || (data[16] & 0x01)) ? SDL_PRESSED : SDL_RELEASED); } @@ -952,7 +970,7 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Jo } if (ctx->last_paddle_state != data[paddle_index]) { - Uint8 nButton = SDL_GAMEPAD_BUTTON_MISC1; /* Next available button */ + Uint8 nButton = SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON; /* Next available button */ SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED); @@ -980,47 +998,38 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joysti } if (ctx->last_state[13] != data[13]) { - SDL_bool dpad_up = SDL_FALSE; - SDL_bool dpad_down = SDL_FALSE; - SDL_bool dpad_left = SDL_FALSE; - SDL_bool dpad_right = SDL_FALSE; + Uint8 hat; switch (data[13]) { case 1: - dpad_up = SDL_TRUE; + hat = SDL_HAT_UP; break; case 2: - dpad_up = SDL_TRUE; - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHTUP; break; case 3: - dpad_right = SDL_TRUE; + hat = SDL_HAT_RIGHT; break; case 4: - dpad_right = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_RIGHTDOWN; break; case 5: - dpad_down = SDL_TRUE; + hat = SDL_HAT_DOWN; break; case 6: - dpad_left = SDL_TRUE; - dpad_down = SDL_TRUE; + hat = SDL_HAT_LEFTDOWN; break; case 7: - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFT; break; case 8: - dpad_up = SDL_TRUE; - dpad_left = SDL_TRUE; + hat = SDL_HAT_LEFTUP; break; default: + hat = SDL_HAT_CENTERED; break; } - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left); + SDL_SendJoystickHat(timestamp, joystick, 0, hat); } axis = ((int)SDL_SwapLE16(*(Sint16 *)(&data[9])) * 64) - 32768; From c24b33d8d946a4e6af78604fd1c562f4eff72478 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 15:14:34 -0800 Subject: [PATCH 627/725] Fixed building with older Windows SDK --- src/video/windows/SDL_windowsvideo.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index 2be8eba3eb085..b5a380038d3df 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -52,6 +52,10 @@ #include "SDL_windowswindow.h" +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif + #if WINVER < 0x0601 /* Touch input definitions */ #define TWF_FINETOUCH 1 From 61704b5862e3cfd9bb452701f1e7d0363bbd9027 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 15:21:49 -0800 Subject: [PATCH 628/725] Removed an assertion it's possible to hit --- test/testcontroller.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index 74acff5f2d9b6..8c360972dad0e 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -967,8 +967,6 @@ static void HandleGamepadAdded(SDL_JoystickID id, SDL_bool verbose) int i; i = FindController(id); - - SDL_assert(i >= 0); if (i < 0) { return; } From 43c40d30a28664220db02ca2381781c7c1deee0d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 15:22:12 -0800 Subject: [PATCH 629/725] Added comment for the BDA Pro Ex controller --- src/joystick/controller_list.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 63175ac47f2e7..5678db4a4b79b 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -66,7 +66,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x1a34, 0x0836 ), k_eControllerType_PS3Controller, NULL }, // Afterglow PS3 { MAKE_CONTROLLER_ID( 0x20bc, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // ShanWan PS3 { MAKE_CONTROLLER_ID( 0x20d6, 0x576d ), k_eControllerType_PS3Controller, NULL }, // Power A PS3 - { MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // From SDL + { MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // BDA Pro Ex { MAKE_CONTROLLER_ID( 0x2563, 0x0523 ), k_eControllerType_PS3Controller, NULL }, // Digiflip GP006 { MAKE_CONTROLLER_ID( 0x2563, 0x0575 ), k_eControllerType_PS3Controller, NULL }, // From SDL { MAKE_CONTROLLER_ID( 0x25f0, 0x83c3 ), k_eControllerType_PS3Controller, NULL }, // gioteck vx2 From ffb8515c211dcafc156473c63f247125233b6de6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 15:41:02 -0800 Subject: [PATCH 630/725] Use the Valve code name for the Steam Deck controller --- src/joystick/SDL_joystick.c | 2 +- src/joystick/controller_list.h | 2 +- src/joystick/controller_type.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 5e21dd95d8dd3..1d71653b21726 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -3002,7 +3002,7 @@ SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); - return eType == k_eControllerType_SteamDeck; + return eType == k_eControllerType_SteamControllerNeptune; } SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 5678db4a4b79b..c8ba2c0cebe7e 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -598,5 +598,5 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller { MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB) { MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB) - { MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamDeck, NULL }, // Valve Steam Deck Builtin Controller + { MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamControllerNeptune, NULL }, // Valve Steam Deck Builtin Controller }; diff --git a/src/joystick/controller_type.h b/src/joystick/controller_type.h index 78c595586301f..155c8ad11e159 100644 --- a/src/joystick/controller_type.h +++ b/src/joystick/controller_type.h @@ -37,7 +37,7 @@ typedef enum k_eControllerType_UnknownSteamController = 1, k_eControllerType_SteamController = 2, k_eControllerType_SteamControllerV2 = 3, - k_eControllerType_SteamDeck = 4, + k_eControllerType_SteamControllerNeptune = 4, // Other Controllers k_eControllerType_UnknownNonSteamController = 30, From 3976bbef2ad3896c4411c4fcd5bfc5e3bd64bb4b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 15:56:37 -0800 Subject: [PATCH 631/725] Added documentation for getting the X11 window from an SDL window --- docs/README-migration.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 7f554277a0434..fb30e16c7c3ea 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1199,22 +1199,40 @@ The Windows and X11 events are now available via callbacks which you can set wit The information previously available in SDL_GetWindowWMInfo() is now available as window properties, e.g. ```c - HWND hwnd = NULL; SDL_SysWMinfo info; SDL_VERSION(&info.version); + +#if defined(__WIN32__) + HWND hwnd = NULL; if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { hwnd = info.info.win.window; } if (hwnd) { ... } +#elif defined(__LINUX__) + Window xwin = 0; + if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_X11) { + xwin = info.info.x11.window; + } + if (xwin) { + ... + } +#endif ``` becomes: ```c - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd"); +#if defined(__WIN32__) + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL); if (hwnd) { ... } +#elif defined(__LINUX__) + Window xwin = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); + if (xwin) { + ... + } +#endif ``` ## SDL_thread.h From 327d31a5d9ea4156a5a5b5afc305a180ca30f1a9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 16:09:59 -0800 Subject: [PATCH 632/725] Added documentation for getting the NSWindow from an SDL window --- docs/README-migration.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index fb30e16c7c3ea..ccf3734b86ceb 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1210,12 +1210,20 @@ The information previously available in SDL_GetWindowWMInfo() is now available a if (hwnd) { ... } +#elif defined(__MACOSX__) + NSWindow *nswindow = NULL; + if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_COCOA) { + nswindow = (__bridge NSWindow *)info.info.cocoa.window; + } + if (nswindow) { + ... + } #elif defined(__LINUX__) - Window xwin = 0; + Window xwindow = 0; if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_X11) { - xwin = info.info.x11.window; + xwindow = info.info.x11.window; } - if (xwin) { + if (xwindow) { ... } #endif @@ -1227,9 +1235,14 @@ becomes: if (hwnd) { ... } +#elif defined(__MACOS__) + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL); + if (nswindow) { + ... + } #elif defined(__LINUX__) - Window xwin = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); - if (xwin) { + Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); + if (xwindow) { ... } #endif From ce4fe32ce37e8c38d966058b2e253675140c7bdb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 16:26:55 -0800 Subject: [PATCH 633/725] Added documentation for getting the X11 display from an SDL window --- docs/README-migration.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index ccf3734b86ceb..c2a58f185faa2 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1219,11 +1219,13 @@ The information previously available in SDL_GetWindowWMInfo() is now available a ... } #elif defined(__LINUX__) + Display *xdisplay = NULL; Window xwindow = 0; if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_X11) { + xdisplay = info.info.x11.display; xwindow = info.info.x11.window; } - if (xwindow) { + if (xdisplay && xwindow) { ... } #endif @@ -1241,8 +1243,9 @@ becomes: ... } #elif defined(__LINUX__) + Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.x11.display", NULL); Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); - if (xwindow) { + if (xdisplay && xwindow) { ... } #endif From dc450ba90802005f12aec82857eef97d582cff96 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 16:34:13 -0800 Subject: [PATCH 634/725] Added an example of creating a window with position --- docs/README-migration.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index c2a58f185faa2..f25731691a547 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1323,7 +1323,21 @@ Rather than iterating over displays using display index, there is a new function } ``` -SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it. +SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it, e.g. +```c + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetStringProperty(props, title); + SDL_SetNumberProperty(props, "x", x); + SDL_SetNumberProperty(props, "y", y); + SDL_SetNumberProperty(props, "width", width); + SDL_SetNumberProperty(props, "height", height); + SDL_SetNumberProperty(props, "flags", flags); + pWindow = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); + if (window) { + ... + } +``` The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. From 39e24e52c8d4d0986e21f878a9190b9b7784c556 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 16:35:31 -0800 Subject: [PATCH 635/725] Fixed example of creating a window with properties --- docs/README-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index f25731691a547..b462d36cf876c 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1326,7 +1326,7 @@ Rather than iterating over displays using display index, there is a new function SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it, e.g. ```c SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetStringProperty(props, title); + SDL_SetStringProperty(props, "title", title); SDL_SetNumberProperty(props, "x", x); SDL_SetNumberProperty(props, "y", y); SDL_SetNumberProperty(props, "width", width); From b6a92c113faebb713a4f14f82c41ca252443f759 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 29 Dec 2023 08:59:45 -0500 Subject: [PATCH 636/725] wayland: Don't apply old libdecor window dimensions Don't overwrite the current dimensions unless they've actually changed, or programmatically set dimensions can be overwritten. --- src/video/wayland/SDL_waylandwindow.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index a43766c43e910..288ec96dd21b1 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1087,8 +1087,6 @@ static void decoration_frame_configure(struct libdecor_frame *frame, window->state_not_floating = tiled; /* Calculate the new window geometry */ - wind->requested_window_width = width; - wind->requested_window_height = height; ConfigureWindowGeometry(window); /* ... then commit the changes on the libdecor side. */ From d71454da1703586f2e9377145fba11c35884b976 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 08:17:06 -0800 Subject: [PATCH 637/725] Store the surface properties in the reserved pointer of a surface This prevents us from exposing the properties publicly and allows us to repurpose the pointer later if necessary. Fixes https://github.com/libsdl-org/SDL/issues/8758 --- include/SDL3/SDL_surface.h | 6 +----- src/video/SDL_surface.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 37e5b15251d29..8742cd1b78303 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -104,11 +104,7 @@ typedef struct SDL_Surface int pitch; /**< Read-only */ void *pixels; /**< Read-write */ - /** Application data associated with the surface */ - union { - void *reserved; /**< For ABI compatibility only, do not use */ - SDL_PropertiesID props; /**< Read-only */ - }; + void *reserved; /**< Private */ /** information needed for surfaces requiring locks */ int locked; /**< Read-only */ diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index b0a57d4e6e5bf..dec18df53d8e3 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -252,23 +252,28 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface) { + SDL_PropertiesID props; + if (!surface) { SDL_InvalidParamError("surface"); return 0; } - if (!(surface->flags & SDL_SURFACE_USES_PROPERTIES)) { + if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { + props = (SDL_PropertiesID)(uintptr_t)surface->reserved; + } else { if (surface->reserved != NULL) { SDL_SetError("Surface has userdata, incompatible with properties"); return 0; } - surface->props = SDL_CreateProperties(); - if (surface->props) { + props = SDL_CreateProperties(); + if (props) { + surface->reserved = (void *)(uintptr_t)props; surface->flags |= SDL_SURFACE_USES_PROPERTIES; } } - return surface->props; + return props; } int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette) @@ -1570,7 +1575,8 @@ void SDL_DestroySurface(SDL_Surface *surface) } if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { - SDL_DestroyProperties(surface->props); + SDL_PropertiesID props = (SDL_PropertiesID)(uintptr_t)surface->reserved; + SDL_DestroyProperties(props); } SDL_InvalidateMap(surface->map); From 61db102da90227b5dbc52c03dc9848228591e49d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:23:47 -0800 Subject: [PATCH 638/725] Fixed signed/unsigned warnings with Visual Studio when comparing SDL_bool with boolean expressions --- include/SDL3/SDL_stdinc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index a257513f3aea4..90cf90530bced 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -133,7 +133,7 @@ char *alloca(); */ #define SDL_FALSE 0 #define SDL_TRUE 1 -typedef unsigned int SDL_bool; +typedef int SDL_bool; /** * A signed 8-bit integer type. From 7f376277e53e67652e8547e1543af260bf9744ee Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:24:22 -0800 Subject: [PATCH 639/725] Fixed warning C4244: 'initializing': conversion from 'SDL_bool' to 'Uint8', possible loss of data --- src/joystick/hidapi/SDL_hidapi_wii.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index ee8b8ce9868c9..bd9b26e3bee4f 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -551,7 +551,7 @@ static EWiiInputReportIDs GetButtonPacketType(SDL_DriverWii_Context *ctx) static SDL_bool RequestButtonPacketType(SDL_DriverWii_Context *ctx, EWiiInputReportIDs type) { Uint8 data[3]; - Uint8 tt = ctx->m_bRumbleActive; + Uint8 tt = (Uint8)ctx->m_bRumbleActive; /* Continuous reporting off, tt & 4 == 0 */ if (ENABLE_CONTINUOUS_REPORTING) { @@ -615,7 +615,7 @@ static void UpdateSlotLED(SDL_DriverWii_Context *ctx) Uint8 data[2]; /* The lowest bit needs to have the rumble status */ - leds = ctx->m_bRumbleActive; + leds = (Uint8)ctx->m_bRumbleActive; if (ctx->m_bPlayerLights) { /* Use the same LED codes as Smash 8-player for 5-7 */ @@ -809,7 +809,7 @@ static int HIDAPI_DriverWii_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joysti Uint8 data[2]; data[0] = k_eWiiOutputReportIDs_Rumble; - data[1] = active; + data[1] = (Uint8)active; WriteOutput(ctx, data, sizeof(data), SDL_FALSE); ctx->m_bRumbleActive = active; @@ -1541,7 +1541,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device) Uint8 data[2]; data[0] = k_eWiiOutputReportIDs_StatusRequest; - data[1] = ctx->m_bRumbleActive; + data[1] = (Uint8)ctx->m_bRumbleActive; WriteOutput(ctx, data, sizeof(data), SDL_FALSE); ctx->m_ulLastStatus = now; From dce626f469c6eb12483d34b546a7101ad9256ad9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:24:52 -0800 Subject: [PATCH 640/725] Fixed warning C4244: 'function': conversion from 'int' to 'Uint16', possible loss of data --- src/joystick/hidapi/SDL_hidapi_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 62c61562fa51d..cf931b444c6ca 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -1075,7 +1075,7 @@ static SDL_bool HasHomeLED(SDL_DriverSwitch_Context *ctx) return SDL_TRUE; } -static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType) +static SDL_bool AlwaysUsesLabels(Uint16 vendor_id, Uint16 product_id, ESwitchDeviceInfoControllerType eControllerType) { /* Some controllers don't have a diamond button configuration, so should always use labels */ if (SDL_IsJoystickGameCube(vendor_id, product_id)) { From e813c72b3c3a7e84ea81c7fc0cc787685079ecc5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:25:57 -0800 Subject: [PATCH 641/725] Fixed warning C4245: 'return': conversion from 'int' to 'SDL_JoystickID', signed/unsigned mismatch --- src/joystick/virtual/SDL_virtualjoystick.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 89b60d74eaa63..b15177ec30558 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -125,7 +125,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); if (!hwdata) { VIRTUAL_FreeHWData(hwdata); - return -1; + return 0; } SDL_memcpy(&hwdata->desc, desc, sizeof(*desc)); @@ -210,7 +210,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata->axes = SDL_calloc(hwdata->desc.naxes, sizeof(Sint16)); if (!hwdata->axes) { VIRTUAL_FreeHWData(hwdata); - return -1; + return 0; } /* Trigger axes are at minimum value at rest */ @@ -225,14 +225,14 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des hwdata->buttons = SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8)); if (!hwdata->buttons) { VIRTUAL_FreeHWData(hwdata); - return -1; + return 0; } } if (hwdata->desc.nhats > 0) { hwdata->hats = SDL_calloc(hwdata->desc.nhats, sizeof(Uint8)); if (!hwdata->hats) { VIRTUAL_FreeHWData(hwdata); - return -1; + return 0; } } From dc1c27885e6a4d1abe64a4076bb19f069c09769a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:26:36 -0800 Subject: [PATCH 642/725] Fixed warning C4389: '!=': signed/unsigned mismatch in SDL_blit.c --- src/video/SDL_blit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index 759d005b8b236..09030265d4a2f 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -79,7 +79,7 @@ typedef struct Uint32 src_format; Uint32 dst_format; int flags; - int cpu; + unsigned int cpu; SDL_BlitFunc func; } SDL_BlitFuncEntry; From ebd7f9adbdc0975f6c7584738609028abb3cce6e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:28:28 -0800 Subject: [PATCH 643/725] Fixed warning C4245: 'initializing': conversion from 'int' to 'Uint32', signed/unsigned mismatch in SDL_video.c --- docs/README-migration.md | 3 ++- include/SDL3/SDL_video.h | 50 +++++++++++++++++-------------------- test/testautomation_video.c | 6 ++--- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index b462d36cf876c..5eb8b506d8c15 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1408,7 +1408,8 @@ The following functions have been removed: * SDL_SetWindowData() - use SDL_GetWindowProperties() instead * SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window -SDL_Window id type is named SDL_WindowID +The SDL_Window id type is named SDL_WindowID +The SDL_WindowFlags enum should be replaced with Uint32 The following symbols have been renamed: * SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index ab7682001b14b..755bbac31f06c 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -125,33 +125,29 @@ typedef struct SDL_Window SDL_Window; * * \sa SDL_GetWindowFlags */ -typedef enum -{ - SDL_WINDOW_FULLSCREEN = 0x00000001, /**< window is in fullscreen mode */ - SDL_WINDOW_OPENGL = 0x00000002, /**< window usable with OpenGL context */ - SDL_WINDOW_OCCLUDED = 0x00000004, /**< window is occluded */ - SDL_WINDOW_HIDDEN = 0x00000008, /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible */ - SDL_WINDOW_BORDERLESS = 0x00000010, /**< no window decoration */ - SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */ - SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */ - SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */ - SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */ - SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */ - SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */ - SDL_WINDOW_EXTERNAL = 0x00000800, /**< window not created by SDL */ - SDL_WINDOW_HIGH_PIXEL_DENSITY = 0x00002000, /**< window uses high pixel density back buffer if possible */ - SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ - SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */ - SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window, not showing in the task bar and window list */ - SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */ - SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */ - SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */ - SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */ - SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */ - SDL_WINDOW_TRANSPARENT = 0x40000000, /**< window with transparent buffer */ - SDL_WINDOW_NOT_FOCUSABLE = 0x80000000, /**< window should not be focusable */ - -} SDL_WindowFlags; +#define SDL_WINDOW_FULLSCREEN 0x00000001U /**< window is in fullscreen mode */ +#define SDL_WINDOW_OPENGL 0x00000002U /**< window usable with OpenGL context */ +#define SDL_WINDOW_OCCLUDED 0x00000004U /**< window is occluded */ +#define SDL_WINDOW_HIDDEN 0x00000008U /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible */ +#define SDL_WINDOW_BORDERLESS 0x00000010U /**< no window decoration */ +#define SDL_WINDOW_RESIZABLE 0x00000020U /**< window can be resized */ +#define SDL_WINDOW_MINIMIZED 0x00000040U /**< window is minimized */ +#define SDL_WINDOW_MAXIMIZED 0x00000080U /**< window is maximized */ +#define SDL_WINDOW_MOUSE_GRABBED 0x00000100U /**< window has grabbed mouse input */ +#define SDL_WINDOW_INPUT_FOCUS 0x00000200U /**< window has input focus */ +#define SDL_WINDOW_MOUSE_FOCUS 0x00000400U /**< window has mouse focus */ +#define SDL_WINDOW_EXTERNAL 0x00000800U /**< window not created by SDL */ +#define SDL_WINDOW_HIGH_PIXEL_DENSITY 0x00002000U /**< window uses high pixel density back buffer if possible */ +#define SDL_WINDOW_MOUSE_CAPTURE 0x00004000U /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ +#define SDL_WINDOW_ALWAYS_ON_TOP 0x00008000U /**< window should always be above others */ +#define SDL_WINDOW_UTILITY 0x00020000U /**< window should be treated as a utility window, not showing in the task bar and window list */ +#define SDL_WINDOW_TOOLTIP 0x00040000U /**< window should be treated as a tooltip */ +#define SDL_WINDOW_POPUP_MENU 0x00080000U /**< window should be treated as a popup menu */ +#define SDL_WINDOW_KEYBOARD_GRABBED 0x00100000U /**< window has grabbed keyboard input */ +#define SDL_WINDOW_VULKAN 0x10000000U /**< window usable for Vulkan surface */ +#define SDL_WINDOW_METAL 0x20000000U /**< window usable for Metal view */ +#define SDL_WINDOW_TRANSPARENT 0x40000000U /**< window with transparent buffer */ +#define SDL_WINDOW_NOT_FOCUSABLE 0x80000000U /**< window should not be focusable */ /** * Used to indicate that you don't care what the window position is. diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 7a3c95d7766fd..524dc198d8f83 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -15,7 +15,7 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) SDL_Window *window; SDL_Event event; int w, h; - SDL_WindowFlags flags; + Uint32 flags; SDL_bool needs_renderer = SDL_FALSE; SDL_bool needs_events_pumped = SDL_FALSE; @@ -197,7 +197,7 @@ static int video_createWindowVariousFlags(void *arg) const char *title = "video_createWindowVariousFlags Test Window"; int w, h; int fVariation; - SDL_WindowFlags flags; + Uint32 flags; /* Standard window */ w = SDLTest_RandomIntegerInRange(320, 1024); @@ -269,7 +269,7 @@ static int video_getWindowFlags(void *arg) { SDL_Window *window; const char *title = "video_getWindowFlags Test Window"; - SDL_WindowFlags flags; + Uint32 flags; Uint32 actualFlags; /* Reliable flag set always set in test window */ From 9906d6d3bc05bd11d09d524cbf26f25329ecb7a9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 09:29:29 -0800 Subject: [PATCH 644/725] Fixed warning C4244: '=': conversion from 'SDL_bool' to 'Uint8', possible loss of data --- src/joystick/windows/SDL_rawinputjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 9c21352370b4b..b5f6113f2053c 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -1802,7 +1802,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick) } } if (!ctx->wgi_correlated) { - SDL_bool new_correlation_count = 0; + Uint8 new_correlation_count = 0; if (RAWINPUT_MissingWindowsGamingInputSlot()) { Uint8 correlation_id = 0; WindowsGamingInputGamepadState *slot_idx = NULL; From 530b41d5317d75f3c4da721d7e15729dd4d565bf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 10:20:30 -0800 Subject: [PATCH 645/725] Fixed warnings in SDL_pen.c --- src/events/SDL_pen.c | 70 +++++++++++++++++++++--------------------- src/events/SDL_pen_c.h | 2 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index e3f55482f7af6..ba5d1098ea226 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -318,9 +318,9 @@ SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities) { if (capabilities & SDL_PEN_ERASER_MASK) { - pen->header.flags &= ~SDL_PEN_INK_MASK; + pen->header.flags &= ~SDL_PEN_INK_MASK; } else if (capabilities & SDL_PEN_INK_MASK) { - pen->header.flags &= ~SDL_PEN_ERASER_MASK; + pen->header.flags &= ~SDL_PEN_ERASER_MASK; } pen->header.flags |= (capabilities & PEN_FLAGS_CAPABILITIES); } @@ -485,7 +485,7 @@ static void event_setup(const SDL_Pen *pen, const SDL_Window *window, Uint64 tim event->pmotion.timestamp = timestamp; event->pmotion.windowID = window ? window->id : 0; event->pmotion.which = pen->header.id; - event->pmotion.pen_state = (Uint16)last_buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); + event->pmotion.pen_state = last_buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); event->pmotion.x = status->x; event->pmotion.y = status->y; SDL_memcpy(event->pmotion.axes, status->axes, SDL_PEN_NUM_AXES * sizeof(float)); @@ -545,7 +545,7 @@ int SDL_SendPenMotion(Uint64 timestamp, } if (SDL_EventEnabled(SDL_EVENT_PEN_MOTION)) { - event_setup(pen, window, timestamp, status, &event); + event_setup(pen, window, timestamp, status, &event); event.pmotion.type = SDL_EVENT_PEN_MOTION; posted = SDL_PushEvent(&event) > 0; @@ -563,7 +563,7 @@ int SDL_SendPenMotion(Uint64 timestamp, case PEN_MOUSE_STATELESS: /* Report mouse event but don't update mouse state */ if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) { - event.motion.windowID = event.pmotion.windowID; + event.motion.windowID = window->id; event.motion.timestamp = timestamp; event.motion.which = SDL_PEN_MOUSEID; event.motion.type = SDL_EVENT_MOUSE_MOTION; @@ -589,7 +589,7 @@ int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) SDL_Event event; SDL_bool posted = SDL_FALSE; SDL_PenStatusInfo *last = &pen->last; - int mouse_button = SDL_BUTTON_LEFT; + Uint8 mouse_button = SDL_BUTTON_LEFT; SDL_Window *window; if (!pen) { @@ -602,17 +602,17 @@ int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) } if (state == SDL_PRESSED) { - event.pbutton.type = SDL_EVENT_PEN_DOWN; - pen->header.flags |= SDL_PEN_DOWN_MASK; + event.pbutton.type = SDL_EVENT_PEN_DOWN; + pen->header.flags |= SDL_PEN_DOWN_MASK; } else { - event.pbutton.type = SDL_EVENT_PEN_UP; - pen->header.flags &= ~SDL_PEN_DOWN_MASK; + event.pbutton.type = SDL_EVENT_PEN_UP; + pen->header.flags &= ~SDL_PEN_DOWN_MASK; } if (SDL_EventEnabled(event.ptip.type)) { - event_setup(pen, window, timestamp, &pen->last, &event); + event_setup(pen, window, timestamp, &pen->last, &event); - /* Used as eraser? Report eraser event, otherwise ink event */ + /* Used as eraser? Report eraser event, otherwise ink event */ event.ptip.tip = (pen->header.flags & SDL_PEN_ERASER_MASK) ? SDL_PEN_TIP_ERASER : SDL_PEN_TIP_INK; event.ptip.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; @@ -626,10 +626,10 @@ int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) /* Mouse emulation */ if (pen_delay_mouse_button_mode) { /* Send button events when pen touches / leaves surface */ - mouse_button = pen->last_mouse_button; - if (0 == mouse_button) { - mouse_button = SDL_BUTTON_LEFT; /* No current button? Instead report left mouse button */ - } + mouse_button = pen->last_mouse_button; + if (mouse_button == 0) { + mouse_button = SDL_BUTTON_LEFT; /* No current button? Instead report left mouse button */ + } } switch (pen_mouse_emulation_mode) { @@ -668,7 +668,7 @@ int SDL_SendPenButton(Uint64 timestamp, SDL_Event event; SDL_bool posted = SDL_FALSE; SDL_PenStatusInfo *last = &pen->last; - int mouse_button = button + 1; /* For mouse emulation, PEN_DOWN counts as button 1, so the first actual button is mouse button 2 */ + Uint8 mouse_button = button + 1; /* For mouse emulation, PEN_DOWN counts as button 1, so the first actual button is mouse button 2 */ SDL_Window *window; if (!pen) { @@ -681,15 +681,15 @@ int SDL_SendPenButton(Uint64 timestamp, } if (state == SDL_PRESSED) { - event.pbutton.type = SDL_EVENT_PEN_BUTTON_DOWN; - pen->last.buttons |= (1 << (button - 1)); + event.pbutton.type = SDL_EVENT_PEN_BUTTON_DOWN; + pen->last.buttons |= (1 << (button - 1)); } else { - event.pbutton.type = SDL_EVENT_PEN_BUTTON_UP; - pen->last.buttons &= ~(1 << (button - 1)); + event.pbutton.type = SDL_EVENT_PEN_BUTTON_UP; + pen->last.buttons &= ~(1 << (button - 1)); } if (SDL_EventEnabled(event.pbutton.type)) { - event_setup(pen, window, timestamp, &pen->last, &event); + event_setup(pen, window, timestamp, &pen->last, &event); event.pbutton.button = button; event.pbutton.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; @@ -705,14 +705,14 @@ int SDL_SendPenButton(Uint64 timestamp, if (pen_delay_mouse_button_mode) { /* Can only change active mouse button while not touching the surface */ if (!(pen->header.flags & SDL_PEN_DOWN_MASK)) { - if (state == SDL_RELEASED) { - pen->last_mouse_button = 0; - } else { - pen->last_mouse_button = mouse_button; - } - } - /* Defer emulation event */ - return SDL_TRUE; + if (state == SDL_RELEASED) { + pen->last_mouse_button = 0; + } else { + pen->last_mouse_button = mouse_button; + } + } + /* Defer emulation event */ + return SDL_TRUE; } switch (pen_mouse_emulation_mode) { @@ -1043,9 +1043,9 @@ void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint3 int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags) { const char *name = NULL; - int num_buttons; - int tool_type; - int axes; + int num_buttons = 0; + int tool_type = 0; + int axes = 0; #if SDL_PEN_DEBUG_UNKNOWN_WACOM wacom_devicetype_id = PEN_WACOM_ID_INVALID; /* force detection to fail */ @@ -1079,14 +1079,14 @@ int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *ax /* Override defaults */ if (pen->info.num_buttons == SDL_PEN_INFO_UNKNOWN) { - pen->info.num_buttons = num_buttons; + pen->info.num_buttons = (Sint8)SDL_min(num_buttons, SDL_MAX_SINT8); } if (pen->type == SDL_PEN_TYPE_PEN) { pen->type = (SDL_PenSubtype)tool_type; } if (pen->info.max_tilt == SDL_PEN_INFO_UNKNOWN) { /* supposedly: 64 degrees left, 63 right, as reported by the Wacom X11 driver */ - pen->info.max_tilt = 64.0f; + pen->info.max_tilt = 64.0f; } pen->info.wacom_id = wacom_devicetype_id; if (0 == pen->name[0]) { diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h index 70b1b7fefd1ef..255ec0516ee5a 100644 --- a/src/events/SDL_pen_c.h +++ b/src/events/SDL_pen_c.h @@ -53,7 +53,7 @@ typedef struct SDL_PenStatusInfo { float x, y; float axes[SDL_PEN_NUM_AXES]; - Uint32 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */ + Uint16 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */ } SDL_PenStatusInfo; /** From 5d0c8937233233953835e2edcdb4ccda06717a58 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 29 Dec 2023 14:18:55 -0500 Subject: [PATCH 646/725] wayland: Remove bitfield specifiers from boolean values If SDL_bool is no longer unsigned, this won't work as the valid values are only 1 and -1. --- src/video/wayland/SDL_waylandwindow.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index c1c8a3986ba59..f3d1dd4bae4a4 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -120,13 +120,13 @@ struct SDL_WindowData int system_min_required_height; SDL_DisplayID last_displayID; int fullscreen_deadline_count; - SDL_bool floating : 1; - SDL_bool suspended : 1; - SDL_bool active : 1; - SDL_bool is_fullscreen : 1; - SDL_bool drop_fullscreen_requests : 1; - SDL_bool fullscreen_was_positioned : 1; - SDL_bool show_hide_sync_required : 1; + SDL_bool floating; + SDL_bool suspended; + SDL_bool active; + SDL_bool is_fullscreen; + SDL_bool drop_fullscreen_requests; + SDL_bool fullscreen_was_positioned; + SDL_bool show_hide_sync_required; SDL_HitTestResult hit_test_result; }; From 8f94102b046337e448619d4aa792ad8710680a7f Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 29 Dec 2023 14:41:38 -0500 Subject: [PATCH 647/725] tests: Use unsigned format specifiers for printing flags --- test/testautomation_video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testautomation_video.c b/test/testautomation_video.c index 524dc198d8f83..beaeee5fd03cf 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -25,7 +25,7 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title) flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS; window = SDL_CreateWindow(title, w, h, flags); - SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d)", w, h, flags); + SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%" SDL_PRIu32 ")", w, h, flags); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); /* Wayland and XWayland windows require that a frame be presented before they are fully mapped and visible onscreen. @@ -252,7 +252,7 @@ static int video_createWindowVariousFlags(void *arg) } window = SDL_CreateWindow(title, w, h, flags); - SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d)", w, h, flags); + SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%" SDL_PRIu32 ")", w, h, flags); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); /* Clean up */ @@ -280,7 +280,7 @@ static int video_getWindowFlags(void *arg) if (window != NULL) { actualFlags = SDL_GetWindowFlags(window); SDLTest_AssertPass("Call to SDL_GetWindowFlags()"); - SDLTest_AssertCheck((flags & actualFlags) == flags, "Verify returned value has flags %d set, got: %" SDL_PRIu32, flags, actualFlags); + SDLTest_AssertCheck((flags & actualFlags) == flags, "Verify returned value has flags %" SDL_PRIu32 " set, got: %" SDL_PRIu32, flags, actualFlags); } /* Clean up */ From 7681695875db9cada1e50db859a035e6c7d7a4c5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 17:11:54 -0800 Subject: [PATCH 648/725] Revert "Fixed signed/unsigned warnings with Visual Studio when comparing SDL_bool with boolean expressions" This reverts commit 61db102da90227b5dbc52c03dc9848228591e49d. This causes the build to fail: SDL_waylandwindow.c:1876:45: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bit-bitfield-constant-conversion] wind->fullscreen_was_positioned = SDL_TRUE; --- include/SDL3/SDL_stdinc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 90cf90530bced..a257513f3aea4 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -133,7 +133,7 @@ char *alloca(); */ #define SDL_FALSE 0 #define SDL_TRUE 1 -typedef int SDL_bool; +typedef unsigned int SDL_bool; /** * A signed 8-bit integer type. From 423b1fafcddef219b362be3452a05c17f9a49d26 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 18:06:27 -0800 Subject: [PATCH 649/725] Fixed warning C4047: 'function': '__x_ABI_CWindows_CGaming_CInput_CIRawGameController **' differs in levels of indirection from '__x_ABI_CWindows_CGaming_CInput_CIRawGameController *' This warning happens with old and buggy versions of the Windows SDK --- src/joystick/windows/SDL_windows_gaming_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 05efad4538e8d..3365f29ac09d9 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -662,7 +662,7 @@ static int WGI_JoystickInit(void) hr = __FIVectorView_1_Windows__CGaming__CInput__CRawGameController_GetAt(controllers, i, &controller); if (SUCCEEDED(hr) && controller) { - __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_Invoke(&controller_added.iface, NULL, controller); + IEventHandler_CRawGameControllerVtbl_InvokeAdded(&controller_added.iface, NULL, controller); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller); } } @@ -969,7 +969,7 @@ static void WGI_JoystickQuit(void) { if (wgi.controller_statics) { while (wgi.controller_count > 0) { - __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_Invoke(&controller_removed.iface, NULL, wgi.controllers[wgi.controller_count - 1].controller); + IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed.iface, NULL, wgi.controllers[wgi.controller_count - 1].controller); } if (wgi.controllers) { SDL_free(wgi.controllers); From dfe1a37babb78e8cd338a05a0ec7c6a631727ead Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 19:40:45 -0800 Subject: [PATCH 650/725] Fixed error: 'static' is not at beginning of declaration [-Werror=old-style-declaration] --- src/events/SDL_pen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index ba5d1098ea226..b77a92b5f83c3 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -866,7 +866,7 @@ SDL_bool SDL_PenPerformHitTest(void) #define PEN_NAME_LAST PEN_NAME_STROKE #define PEN_NUM_NAMES (PEN_NAME_LAST + 1) -const static char *default_pen_names[PEN_NUM_NAMES] = { +static const char *default_pen_names[] = { /* PEN_NAME_AES */ "AES Pen", /* PEN_NAME_ART */ @@ -892,6 +892,7 @@ const static char *default_pen_names[PEN_NUM_NAMES] = { /* PEN_NAME_STROKE */ "Stroke Pen" }; +SDL_COMPILE_TIME_ASSERT(default_pen_names, SDL_arraysize(default_pen_names) == PEN_NUM_NAMES); #define PEN_SPEC_TYPE_SHIFT 0 #define PEN_SPEC_TYPE_MASK 0x0000000fu From e3d50619f89ed747f3e15e8410c13d5dd47956d7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 29 Dec 2023 20:04:40 -0800 Subject: [PATCH 651/725] Fixed fatal error: SDL_pen.h: No such file or directory --- include/SDL3/SDL.h | 1 + src/video/x11/SDL_x11pen.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index 422c6cc4a52e7..3ace34f314e62 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/src/video/x11/SDL_x11pen.c b/src/video/x11/SDL_x11pen.c index 6d0dbca4ec075..e2af7fc7bfd51 100644 --- a/src/video/x11/SDL_x11pen.c +++ b/src/video/x11/SDL_x11pen.c @@ -24,7 +24,6 @@ #include "../../events/SDL_pen_c.h" #include "../SDL_sysvideo.h" -#include "SDL_pen.h" #include "SDL_x11pen.h" #include "SDL_x11video.h" #include "SDL_x11xinput2.h" From 2faae8457d61585f7ef39d28a77857efa1ef5874 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 30 Dec 2023 11:44:40 -0800 Subject: [PATCH 652/725] The C standard defines a boolean expression as a signed integer value. Microsoft came to the same conclusion: https://devblogs.microsoft.com/oldnewthing/20110328-00/?p=11113 Fixes https://github.com/libsdl-org/SDL/issues/8761 --- include/SDL3/SDL_stdinc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index a257513f3aea4..90cf90530bced 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -133,7 +133,7 @@ char *alloca(); */ #define SDL_FALSE 0 #define SDL_TRUE 1 -typedef unsigned int SDL_bool; +typedef int SDL_bool; /** * A signed 8-bit integer type. From 44c2f344d623b65fff1d5dfe9196fae801e82ba2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 30 Dec 2023 11:47:56 -0800 Subject: [PATCH 653/725] Fixed build --- src/video/android/SDL_android_video_capture.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/android/SDL_android_video_capture.c b/src/video/android/SDL_android_video_capture.c index 3e8e433bb3bde..c673fc83f7a64 100644 --- a/src/video/android/SDL_android_video_capture.c +++ b/src/video/android/SDL_android_video_capture.c @@ -119,7 +119,7 @@ format_2_id(int fmt) { #define CASE(x, y) case x: return y CASE(FORMAT_SDL, 0); CASE(SDL_PIXELFORMAT_RGB565, 1); - CASE(SDL_PIXELFORMAT_RGB888, 2); + CASE(SDL_PIXELFORMAT_XRGB8888, 2); CASE(SDL_PIXELFORMAT_RGBA8888, 3); CASE(SDL_PIXELFORMAT_RGBX8888, 4); CASE(SDL_PIXELFORMAT_UNKNOWN, 5); @@ -135,7 +135,7 @@ id_2_format(int fmt) { #define CASE(x, y) case y: return x CASE(FORMAT_SDL, 0); CASE(SDL_PIXELFORMAT_RGB565, 1); - CASE(SDL_PIXELFORMAT_RGB888, 2); + CASE(SDL_PIXELFORMAT_XRGB8888, 2); CASE(SDL_PIXELFORMAT_RGBA8888, 3); CASE(SDL_PIXELFORMAT_RGBX8888, 4); CASE(SDL_PIXELFORMAT_UNKNOWN, 5); @@ -152,7 +152,7 @@ format_android_2_sdl(Uint32 fmt) #define CASE(x, y) case x: return y CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL); CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565); - CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_RGB888); + CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888); CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888); CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888); @@ -173,7 +173,7 @@ format_sdl_2_android(Uint32 fmt) #define CASE(x, y) case y: return x CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL); CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565); - CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_RGB888); + CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888); CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888); CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888); #undef CASE From dd2d809407f152c00adc6e96e3a063eb530b7219 Mon Sep 17 00:00:00 2001 From: Amir Kadyrov Date: Sun, 31 Dec 2023 14:19:43 +0400 Subject: [PATCH 654/725] AndroidShowToast: make OneShotTask members private final --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 5165cef8882e4..0d2aeebfab1eb 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -1915,11 +1915,11 @@ public static int showToast(String message, int duration, int gravity, int xOffs try { class OneShotTask implements Runnable { - String mMessage; - int mDuration; - int mGravity; - int mXOffset; - int mYOffset; + private final String mMessage; + private final int mDuration; + private final int mGravity; + private final int mXOffset; + private final int mYOffset; OneShotTask(String message, int duration, int gravity, int xOffset, int yOffset) { mMessage = message; From a7b79c483c9bd03d17a14304982622b3f0c8bfec Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Jan 2024 13:15:39 -0800 Subject: [PATCH 655/725] Remove unused 'window' variable from -[Cocoa_WindowListener windowWillExitFullScreen] --- src/video/cocoa/SDL_cocoawindow.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 79f2c2843a853..758d372357649 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1212,8 +1212,6 @@ - (void)windowDidEnterFullScreen:(NSNotification *)aNotification - (void)windowWillExitFullScreen:(NSNotification *)aNotification { - SDL_Window *window = _data.window; - isFullscreenSpace = NO; inFullscreenTransition = YES; } From 5b3ee51c6ca94f803a4ca77ce0dce08ee0426f80 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Jan 2024 13:15:26 -0800 Subject: [PATCH 656/725] Updated copyright for 2024 --- LICENSE.txt | 2 +- VisualC-GDK/tests/testgdk/src/testgdk.cpp | 2 +- Xcode/SDL/pkg-support/resources/License.txt | 2 +- build-scripts/check_stdlib_usage.py | 2 +- build-scripts/gen_audio_channel_conversion.c | 4 ++-- build-scripts/gen_audio_resampler_filter.c | 4 ++-- include/SDL3/SDL.h | 2 +- include/SDL3/SDL_assert.h | 2 +- include/SDL3/SDL_atomic.h | 2 +- include/SDL3/SDL_audio.h | 2 +- include/SDL3/SDL_begin_code.h | 2 +- include/SDL3/SDL_bits.h | 2 +- include/SDL3/SDL_blendmode.h | 2 +- include/SDL3/SDL_clipboard.h | 2 +- include/SDL3/SDL_close_code.h | 2 +- include/SDL3/SDL_copying.h | 2 +- include/SDL3/SDL_cpuinfo.h | 2 +- include/SDL3/SDL_egl.h | 2 +- include/SDL3/SDL_endian.h | 2 +- include/SDL3/SDL_error.h | 2 +- include/SDL3/SDL_events.h | 2 +- include/SDL3/SDL_filesystem.h | 2 +- include/SDL3/SDL_gamepad.h | 2 +- include/SDL3/SDL_guid.h | 2 +- include/SDL3/SDL_haptic.h | 2 +- include/SDL3/SDL_hidapi.h | 2 +- include/SDL3/SDL_hints.h | 2 +- include/SDL3/SDL_init.h | 2 +- include/SDL3/SDL_intrin.h | 2 +- include/SDL3/SDL_joystick.h | 2 +- include/SDL3/SDL_keyboard.h | 2 +- include/SDL3/SDL_keycode.h | 2 +- include/SDL3/SDL_loadso.h | 2 +- include/SDL3/SDL_locale.h | 2 +- include/SDL3/SDL_log.h | 2 +- include/SDL3/SDL_main.h | 2 +- include/SDL3/SDL_main_impl.h | 2 +- include/SDL3/SDL_messagebox.h | 2 +- include/SDL3/SDL_metal.h | 2 +- include/SDL3/SDL_misc.h | 2 +- include/SDL3/SDL_mouse.h | 2 +- include/SDL3/SDL_mutex.h | 2 +- include/SDL3/SDL_oldnames.h | 2 +- include/SDL3/SDL_opengl.h | 2 +- include/SDL3/SDL_opengles.h | 2 +- include/SDL3/SDL_opengles2.h | 2 +- include/SDL3/SDL_pen.h | 2 +- include/SDL3/SDL_pixels.h | 2 +- include/SDL3/SDL_platform.h | 2 +- include/SDL3/SDL_platform_defines.h | 2 +- include/SDL3/SDL_power.h | 2 +- include/SDL3/SDL_properties.h | 2 +- include/SDL3/SDL_quit.h | 2 +- include/SDL3/SDL_rect.h | 2 +- include/SDL3/SDL_render.h | 2 +- include/SDL3/SDL_revision.h | 2 +- include/SDL3/SDL_rwops.h | 2 +- include/SDL3/SDL_scancode.h | 2 +- include/SDL3/SDL_sensor.h | 2 +- include/SDL3/SDL_stdinc.h | 2 +- include/SDL3/SDL_surface.h | 2 +- include/SDL3/SDL_system.h | 2 +- include/SDL3/SDL_test.h | 2 +- include/SDL3/SDL_test_assert.h | 2 +- include/SDL3/SDL_test_common.h | 2 +- include/SDL3/SDL_test_compare.h | 2 +- include/SDL3/SDL_test_crc32.h | 2 +- include/SDL3/SDL_test_font.h | 2 +- include/SDL3/SDL_test_fuzzer.h | 2 +- include/SDL3/SDL_test_harness.h | 2 +- include/SDL3/SDL_test_log.h | 2 +- include/SDL3/SDL_test_md5.h | 2 +- include/SDL3/SDL_test_memory.h | 2 +- include/SDL3/SDL_test_random.h | 2 +- include/SDL3/SDL_thread.h | 2 +- include/SDL3/SDL_timer.h | 2 +- include/SDL3/SDL_touch.h | 2 +- include/SDL3/SDL_version.h | 2 +- include/SDL3/SDL_video.h | 2 +- include/SDL3/SDL_video_capture.h | 2 +- include/build_config/SDL_build_config.h | 2 +- include/build_config/SDL_build_config.h.cmake | 2 +- include/build_config/SDL_build_config_android.h | 2 +- include/build_config/SDL_build_config_emscripten.h | 2 +- include/build_config/SDL_build_config_ios.h | 2 +- include/build_config/SDL_build_config_macos.h | 2 +- include/build_config/SDL_build_config_minimal.h | 2 +- include/build_config/SDL_build_config_ngage.h | 2 +- include/build_config/SDL_build_config_windows.h | 2 +- include/build_config/SDL_build_config_wingdk.h | 2 +- include/build_config/SDL_build_config_winrt.h | 2 +- include/build_config/SDL_build_config_xbox.h | 2 +- include/build_config/SDL_revision.h.cmake | 2 +- src/SDL.c | 2 +- src/SDL_assert.c | 2 +- src/SDL_assert_c.h | 2 +- src/SDL_error.c | 2 +- src/SDL_error_c.h | 2 +- src/SDL_guid.c | 2 +- src/SDL_hashtable.c | 2 +- src/SDL_hashtable.h | 2 +- src/SDL_hints.c | 2 +- src/SDL_hints_c.h | 2 +- src/SDL_internal.h | 2 +- src/SDL_list.c | 2 +- src/SDL_list.h | 2 +- src/SDL_log.c | 2 +- src/SDL_log_c.h | 2 +- src/SDL_properties.c | 2 +- src/SDL_properties_c.h | 2 +- src/SDL_utils.c | 2 +- src/SDL_utils_c.h | 2 +- src/atomic/SDL_atomic.c | 2 +- src/atomic/SDL_spinlock.c | 2 +- src/audio/SDL_audio.c | 2 +- src/audio/SDL_audio_c.h | 2 +- src/audio/SDL_audio_channel_converters.h | 2 +- src/audio/SDL_audio_resampler_filter.h | 2 +- src/audio/SDL_audiocvt.c | 2 +- src/audio/SDL_audiodev.c | 2 +- src/audio/SDL_audiodev_c.h | 2 +- src/audio/SDL_audioqueue.c | 2 +- src/audio/SDL_audioqueue.h | 2 +- src/audio/SDL_audioresample.c | 2 +- src/audio/SDL_audioresample.h | 2 +- src/audio/SDL_audiotypecvt.c | 2 +- src/audio/SDL_mixer.c | 2 +- src/audio/SDL_sysaudio.h | 2 +- src/audio/SDL_wave.c | 2 +- src/audio/SDL_wave.h | 2 +- src/audio/aaudio/SDL_aaudio.c | 2 +- src/audio/aaudio/SDL_aaudio.h | 2 +- src/audio/aaudio/SDL_aaudiofuncs.h | 2 +- src/audio/alsa/SDL_alsa_audio.c | 2 +- src/audio/alsa/SDL_alsa_audio.h | 2 +- src/audio/android/SDL_androidaudio.c | 2 +- src/audio/android/SDL_androidaudio.h | 2 +- src/audio/coreaudio/SDL_coreaudio.h | 2 +- src/audio/coreaudio/SDL_coreaudio.m | 2 +- src/audio/directsound/SDL_directsound.c | 2 +- src/audio/directsound/SDL_directsound.h | 2 +- src/audio/disk/SDL_diskaudio.c | 2 +- src/audio/disk/SDL_diskaudio.h | 2 +- src/audio/dsp/SDL_dspaudio.c | 2 +- src/audio/dsp/SDL_dspaudio.h | 2 +- src/audio/dummy/SDL_dummyaudio.c | 2 +- src/audio/dummy/SDL_dummyaudio.h | 2 +- src/audio/emscripten/SDL_emscriptenaudio.c | 2 +- src/audio/emscripten/SDL_emscriptenaudio.h | 2 +- src/audio/haiku/SDL_haikuaudio.cc | 2 +- src/audio/haiku/SDL_haikuaudio.h | 2 +- src/audio/jack/SDL_jackaudio.c | 2 +- src/audio/jack/SDL_jackaudio.h | 2 +- src/audio/n3ds/SDL_n3dsaudio.c | 2 +- src/audio/n3ds/SDL_n3dsaudio.h | 2 +- src/audio/netbsd/SDL_netbsdaudio.c | 2 +- src/audio/netbsd/SDL_netbsdaudio.h | 2 +- src/audio/openslES/SDL_openslES.c | 2 +- src/audio/openslES/SDL_openslES.h | 2 +- src/audio/pipewire/SDL_pipewire.c | 2 +- src/audio/pipewire/SDL_pipewire.h | 2 +- src/audio/ps2/SDL_ps2audio.c | 2 +- src/audio/ps2/SDL_ps2audio.h | 2 +- src/audio/psp/SDL_pspaudio.c | 2 +- src/audio/psp/SDL_pspaudio.h | 2 +- src/audio/pulseaudio/SDL_pulseaudio.c | 2 +- src/audio/pulseaudio/SDL_pulseaudio.h | 2 +- src/audio/qnx/SDL_qsa_audio.c | 2 +- src/audio/qnx/SDL_qsa_audio.h | 2 +- src/audio/sndio/SDL_sndioaudio.c | 2 +- src/audio/sndio/SDL_sndioaudio.h | 2 +- src/audio/vita/SDL_vitaaudio.c | 2 +- src/audio/vita/SDL_vitaaudio.h | 2 +- src/audio/wasapi/SDL_wasapi.c | 2 +- src/audio/wasapi/SDL_wasapi.h | 2 +- src/audio/wasapi/SDL_wasapi_win32.c | 2 +- src/audio/wasapi/SDL_wasapi_winrt.cpp | 2 +- src/core/SDL_core_unsupported.c | 2 +- src/core/SDL_runapp.c | 2 +- src/core/android/SDL_android.c | 2 +- src/core/android/SDL_android.h | 2 +- src/core/freebsd/SDL_evdev_kbd_freebsd.c | 2 +- src/core/gdk/SDL_gdk.cpp | 2 +- src/core/gdk/SDL_gdk.h | 2 +- src/core/haiku/SDL_BApp.h | 2 +- src/core/haiku/SDL_BeApp.cc | 2 +- src/core/haiku/SDL_BeApp.h | 2 +- src/core/linux/SDL_dbus.c | 2 +- src/core/linux/SDL_dbus.h | 2 +- src/core/linux/SDL_evdev.c | 2 +- src/core/linux/SDL_evdev.h | 2 +- src/core/linux/SDL_evdev_capabilities.c | 2 +- src/core/linux/SDL_evdev_capabilities.h | 2 +- src/core/linux/SDL_evdev_kbd.c | 2 +- src/core/linux/SDL_evdev_kbd.h | 2 +- src/core/linux/SDL_evdev_kbd_default_accents.h | 2 +- src/core/linux/SDL_evdev_kbd_default_keymap.h | 2 +- src/core/linux/SDL_fcitx.c | 2 +- src/core/linux/SDL_fcitx.h | 2 +- src/core/linux/SDL_ibus.c | 2 +- src/core/linux/SDL_ibus.h | 2 +- src/core/linux/SDL_ime.c | 2 +- src/core/linux/SDL_ime.h | 2 +- src/core/linux/SDL_sandbox.c | 2 +- src/core/linux/SDL_sandbox.h | 2 +- src/core/linux/SDL_system_theme.c | 2 +- src/core/linux/SDL_system_theme.h | 2 +- src/core/linux/SDL_threadprio.c | 2 +- src/core/linux/SDL_udev.c | 2 +- src/core/linux/SDL_udev.h | 2 +- src/core/n3ds/SDL_n3ds.c | 2 +- src/core/openbsd/SDL_wscons.h | 2 +- src/core/openbsd/SDL_wscons_kbd.c | 2 +- src/core/openbsd/SDL_wscons_mouse.c | 2 +- src/core/ps2/SDL_ps2.c | 2 +- src/core/psp/SDL_psp.c | 2 +- src/core/unix/SDL_appid.c | 2 +- src/core/unix/SDL_appid.h | 2 +- src/core/unix/SDL_poll.c | 2 +- src/core/unix/SDL_poll.h | 2 +- src/core/windows/SDL_directx.h | 2 +- src/core/windows/SDL_hid.c | 2 +- src/core/windows/SDL_hid.h | 2 +- src/core/windows/SDL_immdevice.c | 2 +- src/core/windows/SDL_immdevice.h | 2 +- src/core/windows/SDL_windows.c | 2 +- src/core/windows/SDL_windows.h | 2 +- src/core/windows/SDL_xinput.c | 2 +- src/core/windows/SDL_xinput.h | 2 +- src/core/windows/pch.c | 2 +- src/core/windows/pch_cpp.cpp | 2 +- src/core/windows/version.rc | 2 +- src/core/winrt/SDL_winrtapp_common.cpp | 2 +- src/core/winrt/SDL_winrtapp_common.h | 2 +- src/core/winrt/SDL_winrtapp_direct3d.cpp | 2 +- src/core/winrt/SDL_winrtapp_direct3d.h | 2 +- src/core/winrt/SDL_winrtapp_xaml.cpp | 2 +- src/core/winrt/SDL_winrtapp_xaml.h | 2 +- src/cpuinfo/SDL_cpuinfo.c | 2 +- src/dynapi/SDL_dynapi.c | 2 +- src/dynapi/SDL_dynapi.h | 2 +- src/dynapi/SDL_dynapi_overrides.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 2 +- src/dynapi/SDL_dynapi_unsupported.h | 2 +- src/dynapi/gendynapi.py | 2 +- src/events/SDL_clipboardevents.c | 2 +- src/events/SDL_clipboardevents_c.h | 2 +- src/events/SDL_displayevents.c | 2 +- src/events/SDL_displayevents_c.h | 2 +- src/events/SDL_dropevents.c | 2 +- src/events/SDL_dropevents_c.h | 2 +- src/events/SDL_events.c | 2 +- src/events/SDL_events_c.h | 2 +- src/events/SDL_keyboard.c | 2 +- src/events/SDL_keyboard_c.h | 2 +- src/events/SDL_keysym_to_scancode.c | 2 +- src/events/SDL_keysym_to_scancode_c.h | 2 +- src/events/SDL_mouse.c | 2 +- src/events/SDL_mouse_c.h | 2 +- src/events/SDL_pen.c | 2 +- src/events/SDL_pen_c.h | 2 +- src/events/SDL_quit.c | 2 +- src/events/SDL_scancode_tables.c | 2 +- src/events/SDL_scancode_tables_c.h | 2 +- src/events/SDL_touch.c | 2 +- src/events/SDL_touch_c.h | 2 +- src/events/SDL_windowevents.c | 2 +- src/events/SDL_windowevents_c.h | 2 +- src/events/blank_cursor.h | 2 +- src/events/default_cursor.h | 2 +- src/events/scancodes_ascii.h | 2 +- src/events/scancodes_darwin.h | 2 +- src/events/scancodes_linux.h | 2 +- src/events/scancodes_windows.h | 2 +- src/events/scancodes_xfree86.h | 2 +- src/file/SDL_rwops.c | 2 +- src/file/cocoa/SDL_rwopsbundlesupport.h | 2 +- src/file/cocoa/SDL_rwopsbundlesupport.m | 2 +- src/file/n3ds/SDL_rwopsromfs.c | 2 +- src/file/n3ds/SDL_rwopsromfs.h | 2 +- src/filesystem/android/SDL_sysfilesystem.c | 2 +- src/filesystem/cocoa/SDL_sysfilesystem.m | 2 +- src/filesystem/dummy/SDL_sysfilesystem.c | 2 +- src/filesystem/emscripten/SDL_sysfilesystem.c | 2 +- src/filesystem/gdk/SDL_sysfilesystem.cpp | 2 +- src/filesystem/haiku/SDL_sysfilesystem.cc | 2 +- src/filesystem/n3ds/SDL_sysfilesystem.c | 2 +- src/filesystem/ps2/SDL_sysfilesystem.c | 2 +- src/filesystem/psp/SDL_sysfilesystem.c | 2 +- src/filesystem/riscos/SDL_sysfilesystem.c | 2 +- src/filesystem/unix/SDL_sysfilesystem.c | 2 +- src/filesystem/vita/SDL_sysfilesystem.c | 2 +- src/filesystem/windows/SDL_sysfilesystem.c | 2 +- src/filesystem/winrt/SDL_sysfilesystem.cpp | 2 +- src/haptic/SDL_haptic.c | 2 +- src/haptic/SDL_haptic_c.h | 2 +- src/haptic/SDL_syshaptic.h | 2 +- src/haptic/android/SDL_syshaptic.c | 2 +- src/haptic/android/SDL_syshaptic_c.h | 2 +- src/haptic/darwin/SDL_syshaptic.c | 2 +- src/haptic/darwin/SDL_syshaptic_c.h | 2 +- src/haptic/dummy/SDL_syshaptic.c | 2 +- src/haptic/linux/SDL_syshaptic.c | 2 +- src/haptic/windows/SDL_dinputhaptic.c | 2 +- src/haptic/windows/SDL_dinputhaptic_c.h | 2 +- src/haptic/windows/SDL_windowshaptic.c | 2 +- src/haptic/windows/SDL_windowshaptic_c.h | 2 +- src/haptic/windows/SDL_xinputhaptic.c | 2 +- src/haptic/windows/SDL_xinputhaptic_c.h | 2 +- src/hidapi/SDL_hidapi.c | 2 +- src/hidapi/SDL_hidapi_android.h | 2 +- src/hidapi/SDL_hidapi_c.h | 2 +- src/hidapi/SDL_hidapi_ios.h | 2 +- src/hidapi/SDL_hidapi_libusb.h | 2 +- src/hidapi/SDL_hidapi_linux.h | 2 +- src/hidapi/SDL_hidapi_mac.h | 2 +- src/hidapi/SDL_hidapi_netbsd.h | 2 +- src/hidapi/SDL_hidapi_steamxbox.h | 2 +- src/hidapi/SDL_hidapi_windows.h | 2 +- src/hidapi/libusb/hidapi_thread_sdl.h | 2 +- src/joystick/SDL_gamepad.c | 2 +- src/joystick/SDL_gamepad_c.h | 2 +- src/joystick/SDL_gamepad_db.h | 2 +- src/joystick/SDL_joystick.c | 2 +- src/joystick/SDL_joystick_c.h | 2 +- src/joystick/SDL_steam_virtual_gamepad.c | 2 +- src/joystick/SDL_steam_virtual_gamepad.h | 2 +- src/joystick/SDL_sysjoystick.h | 2 +- src/joystick/android/SDL_sysjoystick.c | 2 +- src/joystick/android/SDL_sysjoystick_c.h | 2 +- src/joystick/apple/SDL_mfijoystick.m | 2 +- src/joystick/apple/SDL_mfijoystick_c.h | 2 +- src/joystick/bsd/SDL_bsdjoystick.c | 2 +- src/joystick/darwin/SDL_iokitjoystick.c | 2 +- src/joystick/darwin/SDL_iokitjoystick_c.h | 2 +- src/joystick/dummy/SDL_sysjoystick.c | 2 +- src/joystick/emscripten/SDL_sysjoystick.c | 2 +- src/joystick/emscripten/SDL_sysjoystick_c.h | 2 +- src/joystick/haiku/SDL_haikujoystick.cc | 2 +- src/joystick/hidapi/SDL_hidapi_combined.c | 2 +- src/joystick/hidapi/SDL_hidapi_gamecube.c | 2 +- src/joystick/hidapi/SDL_hidapi_luna.c | 2 +- src/joystick/hidapi/SDL_hidapi_nintendo.h | 2 +- src/joystick/hidapi/SDL_hidapi_ps3.c | 2 +- src/joystick/hidapi/SDL_hidapi_ps4.c | 2 +- src/joystick/hidapi/SDL_hidapi_ps5.c | 2 +- src/joystick/hidapi/SDL_hidapi_rumble.c | 2 +- src/joystick/hidapi/SDL_hidapi_rumble.h | 2 +- src/joystick/hidapi/SDL_hidapi_shield.c | 2 +- src/joystick/hidapi/SDL_hidapi_stadia.c | 2 +- src/joystick/hidapi/SDL_hidapi_steam.c | 2 +- src/joystick/hidapi/SDL_hidapi_switch.c | 2 +- src/joystick/hidapi/SDL_hidapi_wii.c | 2 +- src/joystick/hidapi/SDL_hidapi_xbox360.c | 2 +- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 2 +- src/joystick/hidapi/SDL_hidapi_xboxone.c | 2 +- src/joystick/hidapi/SDL_hidapijoystick.c | 2 +- src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 +- src/joystick/linux/SDL_sysjoystick.c | 2 +- src/joystick/linux/SDL_sysjoystick_c.h | 2 +- src/joystick/n3ds/SDL_sysjoystick.c | 2 +- src/joystick/ps2/SDL_sysjoystick.c | 2 +- src/joystick/psp/SDL_sysjoystick.c | 2 +- src/joystick/steam/SDL_steamcontroller.c | 2 +- src/joystick/steam/SDL_steamcontroller.h | 2 +- src/joystick/usb_ids.h | 2 +- src/joystick/virtual/SDL_virtualjoystick.c | 2 +- src/joystick/virtual/SDL_virtualjoystick_c.h | 2 +- src/joystick/vita/SDL_sysjoystick.c | 2 +- src/joystick/windows/SDL_dinputjoystick.c | 2 +- src/joystick/windows/SDL_dinputjoystick_c.h | 2 +- src/joystick/windows/SDL_rawinputjoystick.c | 2 +- src/joystick/windows/SDL_rawinputjoystick_c.h | 2 +- src/joystick/windows/SDL_windows_gaming_input.c | 2 +- src/joystick/windows/SDL_windowsjoystick.c | 2 +- src/joystick/windows/SDL_windowsjoystick_c.h | 2 +- src/joystick/windows/SDL_xinputjoystick.c | 2 +- src/joystick/windows/SDL_xinputjoystick_c.h | 2 +- src/libm/math_libm.h | 2 +- src/loadso/dlopen/SDL_sysloadso.c | 2 +- src/loadso/dummy/SDL_sysloadso.c | 2 +- src/loadso/windows/SDL_sysloadso.c | 2 +- src/locale/SDL_locale.c | 2 +- src/locale/SDL_syslocale.h | 2 +- src/locale/android/SDL_syslocale.c | 2 +- src/locale/dummy/SDL_syslocale.c | 2 +- src/locale/emscripten/SDL_syslocale.c | 2 +- src/locale/haiku/SDL_syslocale.cc | 2 +- src/locale/macos/SDL_syslocale.m | 2 +- src/locale/n3ds/SDL_syslocale.c | 2 +- src/locale/unix/SDL_syslocale.c | 2 +- src/locale/vita/SDL_syslocale.c | 2 +- src/locale/windows/SDL_syslocale.c | 2 +- src/locale/winrt/SDL_syslocale.c | 2 +- src/main/SDL_main_callbacks.c | 2 +- src/main/SDL_main_callbacks.h | 2 +- src/main/emscripten/SDL_sysmain_callbacks.c | 2 +- src/main/generic/SDL_sysmain_callbacks.c | 2 +- src/main/ios/SDL_sysmain_callbacks.m | 2 +- src/misc/SDL_sysurl.h | 2 +- src/misc/SDL_url.c | 2 +- src/misc/android/SDL_sysurl.c | 2 +- src/misc/dummy/SDL_sysurl.c | 2 +- src/misc/emscripten/SDL_sysurl.c | 2 +- src/misc/haiku/SDL_sysurl.cc | 2 +- src/misc/ios/SDL_sysurl.m | 2 +- src/misc/macos/SDL_sysurl.m | 2 +- src/misc/riscos/SDL_sysurl.c | 2 +- src/misc/unix/SDL_sysurl.c | 2 +- src/misc/vita/SDL_sysurl.c | 2 +- src/misc/windows/SDL_sysurl.c | 2 +- src/misc/winrt/SDL_sysurl.cpp | 2 +- src/power/SDL_power.c | 2 +- src/power/SDL_syspower.h | 2 +- src/power/android/SDL_syspower.c | 2 +- src/power/emscripten/SDL_syspower.c | 2 +- src/power/haiku/SDL_syspower.c | 2 +- src/power/linux/SDL_syspower.c | 2 +- src/power/macos/SDL_syspower.c | 2 +- src/power/n3ds/SDL_syspower.c | 2 +- src/power/psp/SDL_syspower.c | 2 +- src/power/uikit/SDL_syspower.h | 2 +- src/power/uikit/SDL_syspower.m | 2 +- src/power/vita/SDL_syspower.c | 2 +- src/power/windows/SDL_syspower.c | 2 +- src/power/winrt/SDL_syspower.cpp | 2 +- src/render/SDL_d3dmath.c | 2 +- src/render/SDL_d3dmath.h | 2 +- src/render/SDL_render.c | 2 +- src/render/SDL_render_unsupported.c | 2 +- src/render/SDL_sysrender.h | 2 +- src/render/SDL_yuv_sw.c | 2 +- src/render/SDL_yuv_sw_c.h | 2 +- src/render/direct3d/SDL_render_d3d.c | 2 +- src/render/direct3d/SDL_shaders_d3d.c | 2 +- src/render/direct3d/SDL_shaders_d3d.h | 2 +- src/render/direct3d11/SDL_render_d3d11.c | 2 +- src/render/direct3d11/SDL_render_winrt.cpp | 2 +- src/render/direct3d11/SDL_render_winrt.h | 2 +- src/render/direct3d11/SDL_shaders_d3d11.c | 2 +- src/render/direct3d11/SDL_shaders_d3d11.h | 2 +- src/render/direct3d12/SDL_render_d3d12.c | 2 +- src/render/direct3d12/SDL_render_d3d12_xbox.cpp | 2 +- src/render/direct3d12/SDL_render_d3d12_xbox.h | 2 +- src/render/direct3d12/SDL_shaders_d3d12.c | 2 +- src/render/direct3d12/SDL_shaders_d3d12.h | 2 +- src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp | 2 +- src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp | 2 +- src/render/metal/SDL_render_metal.m | 2 +- src/render/opengl/SDL_glfuncs.h | 2 +- src/render/opengl/SDL_render_gl.c | 2 +- src/render/opengl/SDL_shaders_gl.c | 2 +- src/render/opengl/SDL_shaders_gl.h | 2 +- src/render/opengles2/SDL_gles2funcs.h | 2 +- src/render/opengles2/SDL_render_gles2.c | 2 +- src/render/opengles2/SDL_shaders_gles2.c | 2 +- src/render/opengles2/SDL_shaders_gles2.h | 2 +- src/render/ps2/SDL_render_ps2.c | 2 +- src/render/psp/SDL_render_psp.c | 2 +- src/render/software/SDL_blendfillrect.c | 2 +- src/render/software/SDL_blendfillrect.h | 2 +- src/render/software/SDL_blendline.c | 2 +- src/render/software/SDL_blendline.h | 2 +- src/render/software/SDL_blendpoint.c | 2 +- src/render/software/SDL_blendpoint.h | 2 +- src/render/software/SDL_draw.h | 2 +- src/render/software/SDL_drawline.c | 2 +- src/render/software/SDL_drawline.h | 2 +- src/render/software/SDL_drawpoint.c | 2 +- src/render/software/SDL_drawpoint.h | 2 +- src/render/software/SDL_render_sw.c | 2 +- src/render/software/SDL_render_sw_c.h | 2 +- src/render/software/SDL_rotate.h | 2 +- src/render/software/SDL_triangle.c | 2 +- src/render/software/SDL_triangle.h | 2 +- src/render/vitagxm/SDL_render_vita_gxm.c | 2 +- src/render/vitagxm/SDL_render_vita_gxm_memory.c | 2 +- src/render/vitagxm/SDL_render_vita_gxm_memory.h | 2 +- src/render/vitagxm/SDL_render_vita_gxm_shaders.h | 2 +- src/render/vitagxm/SDL_render_vita_gxm_tools.c | 2 +- src/render/vitagxm/SDL_render_vita_gxm_tools.h | 2 +- src/render/vitagxm/SDL_render_vita_gxm_types.h | 2 +- src/sensor/SDL_sensor.c | 2 +- src/sensor/SDL_sensor_c.h | 2 +- src/sensor/SDL_syssensor.h | 2 +- src/sensor/android/SDL_androidsensor.c | 2 +- src/sensor/android/SDL_androidsensor.h | 2 +- src/sensor/coremotion/SDL_coremotionsensor.h | 2 +- src/sensor/coremotion/SDL_coremotionsensor.m | 2 +- src/sensor/dummy/SDL_dummysensor.c | 2 +- src/sensor/dummy/SDL_dummysensor.h | 2 +- src/sensor/n3ds/SDL_n3dssensor.c | 2 +- src/sensor/vita/SDL_vitasensor.c | 2 +- src/sensor/vita/SDL_vitasensor.h | 2 +- src/sensor/windows/SDL_windowssensor.c | 2 +- src/sensor/windows/SDL_windowssensor.h | 2 +- src/stdlib/SDL_crc16.c | 2 +- src/stdlib/SDL_crc32.c | 2 +- src/stdlib/SDL_getenv.c | 2 +- src/stdlib/SDL_iconv.c | 2 +- src/stdlib/SDL_malloc.c | 2 +- src/stdlib/SDL_mslibc.c | 2 +- src/stdlib/SDL_qsort.c | 2 +- src/stdlib/SDL_stdlib.c | 2 +- src/stdlib/SDL_string.c | 2 +- src/stdlib/SDL_strtokr.c | 2 +- src/stdlib/SDL_vacopy.h | 2 +- src/test/SDL_test_assert.c | 2 +- src/test/SDL_test_common.c | 2 +- src/test/SDL_test_compare.c | 2 +- src/test/SDL_test_crc32.c | 2 +- src/test/SDL_test_font.c | 2 +- src/test/SDL_test_fuzzer.c | 2 +- src/test/SDL_test_harness.c | 2 +- src/test/SDL_test_log.c | 2 +- src/test/SDL_test_md5.c | 2 +- src/test/SDL_test_memory.c | 2 +- src/test/SDL_test_random.c | 2 +- src/thread/SDL_systhread.h | 2 +- src/thread/SDL_thread.c | 2 +- src/thread/SDL_thread_c.h | 2 +- src/thread/generic/SDL_syscond.c | 2 +- src/thread/generic/SDL_syscond_c.h | 2 +- src/thread/generic/SDL_sysmutex.c | 2 +- src/thread/generic/SDL_sysmutex_c.h | 2 +- src/thread/generic/SDL_sysrwlock.c | 2 +- src/thread/generic/SDL_sysrwlock_c.h | 2 +- src/thread/generic/SDL_syssem.c | 2 +- src/thread/generic/SDL_systhread.c | 2 +- src/thread/generic/SDL_systhread_c.h | 2 +- src/thread/generic/SDL_systls.c | 2 +- src/thread/n3ds/SDL_syscond.c | 2 +- src/thread/n3ds/SDL_sysmutex.c | 2 +- src/thread/n3ds/SDL_sysmutex_c.h | 2 +- src/thread/n3ds/SDL_syssem.c | 2 +- src/thread/n3ds/SDL_systhread.c | 2 +- src/thread/n3ds/SDL_systhread_c.h | 2 +- src/thread/ngage/SDL_sysmutex.cpp | 2 +- src/thread/ngage/SDL_syssem.cpp | 2 +- src/thread/ngage/SDL_systhread.cpp | 2 +- src/thread/ngage/SDL_systhread_c.h | 2 +- src/thread/ps2/SDL_syssem.c | 2 +- src/thread/ps2/SDL_systhread.c | 2 +- src/thread/ps2/SDL_systhread_c.h | 2 +- src/thread/psp/SDL_sysmutex.c | 2 +- src/thread/psp/SDL_sysmutex_c.h | 2 +- src/thread/psp/SDL_syssem.c | 2 +- src/thread/psp/SDL_systhread.c | 2 +- src/thread/psp/SDL_systhread_c.h | 2 +- src/thread/pthread/SDL_syscond.c | 2 +- src/thread/pthread/SDL_sysmutex.c | 2 +- src/thread/pthread/SDL_sysmutex_c.h | 2 +- src/thread/pthread/SDL_sysrwlock.c | 2 +- src/thread/pthread/SDL_syssem.c | 2 +- src/thread/pthread/SDL_systhread.c | 2 +- src/thread/pthread/SDL_systhread_c.h | 2 +- src/thread/pthread/SDL_systls.c | 2 +- src/thread/stdcpp/SDL_syscond.cpp | 2 +- src/thread/stdcpp/SDL_sysmutex.cpp | 2 +- src/thread/stdcpp/SDL_sysmutex_c.h | 2 +- src/thread/stdcpp/SDL_sysrwlock.cpp | 2 +- src/thread/stdcpp/SDL_systhread.cpp | 2 +- src/thread/stdcpp/SDL_systhread_c.h | 2 +- src/thread/vita/SDL_sysmutex.c | 2 +- src/thread/vita/SDL_sysmutex_c.h | 2 +- src/thread/vita/SDL_syssem.c | 2 +- src/thread/vita/SDL_systhread.c | 2 +- src/thread/vita/SDL_systhread_c.h | 2 +- src/thread/windows/SDL_syscond_cv.c | 2 +- src/thread/windows/SDL_sysmutex.c | 2 +- src/thread/windows/SDL_sysmutex_c.h | 2 +- src/thread/windows/SDL_sysrwlock_srw.c | 2 +- src/thread/windows/SDL_syssem.c | 2 +- src/thread/windows/SDL_systhread.c | 2 +- src/thread/windows/SDL_systhread_c.h | 2 +- src/thread/windows/SDL_systls.c | 2 +- src/timer/SDL_timer.c | 2 +- src/timer/SDL_timer_c.h | 2 +- src/timer/dummy/SDL_systimer.c | 2 +- src/timer/haiku/SDL_systimer.c | 2 +- src/timer/n3ds/SDL_systimer.c | 2 +- src/timer/ngage/SDL_systimer.cpp | 2 +- src/timer/ps2/SDL_systimer.c | 2 +- src/timer/psp/SDL_systimer.c | 2 +- src/timer/unix/SDL_systimer.c | 2 +- src/timer/vita/SDL_systimer.c | 2 +- src/timer/windows/SDL_systimer.c | 2 +- src/video/SDL_RLEaccel.c | 2 +- src/video/SDL_RLEaccel_c.h | 2 +- src/video/SDL_blit.c | 2 +- src/video/SDL_blit.h | 2 +- src/video/SDL_blit_0.c | 2 +- src/video/SDL_blit_1.c | 2 +- src/video/SDL_blit_A.c | 2 +- src/video/SDL_blit_N.c | 2 +- src/video/SDL_blit_auto.c | 2 +- src/video/SDL_blit_auto.h | 2 +- src/video/SDL_blit_copy.c | 2 +- src/video/SDL_blit_copy.h | 2 +- src/video/SDL_blit_slow.c | 2 +- src/video/SDL_blit_slow.h | 2 +- src/video/SDL_bmp.c | 2 +- src/video/SDL_clipboard.c | 2 +- src/video/SDL_clipboard_c.h | 2 +- src/video/SDL_egl.c | 2 +- src/video/SDL_egl_c.h | 2 +- src/video/SDL_fillrect.c | 2 +- src/video/SDL_pixels.c | 2 +- src/video/SDL_pixels_c.h | 2 +- src/video/SDL_rect.c | 2 +- src/video/SDL_rect_c.h | 2 +- src/video/SDL_rect_impl.h | 2 +- src/video/SDL_stretch.c | 2 +- src/video/SDL_surface.c | 2 +- src/video/SDL_surface_pixel_impl.h | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_sysvideocapture.h | 2 +- src/video/SDL_video.c | 2 +- src/video/SDL_video_c.h | 2 +- src/video/SDL_video_capture.c | 2 +- src/video/SDL_video_capture_c.h | 2 +- src/video/SDL_video_capture_v4l2.c | 2 +- src/video/SDL_video_unsupported.c | 2 +- src/video/SDL_vulkan_internal.h | 2 +- src/video/SDL_vulkan_utils.c | 2 +- src/video/SDL_yuv.c | 2 +- src/video/SDL_yuv_c.h | 2 +- src/video/android/SDL_android_video_capture.c | 2 +- src/video/android/SDL_androidclipboard.c | 2 +- src/video/android/SDL_androidclipboard.h | 2 +- src/video/android/SDL_androidevents.c | 2 +- src/video/android/SDL_androidevents.h | 2 +- src/video/android/SDL_androidgl.c | 2 +- src/video/android/SDL_androidgl.h | 2 +- src/video/android/SDL_androidkeyboard.c | 2 +- src/video/android/SDL_androidkeyboard.h | 2 +- src/video/android/SDL_androidmessagebox.c | 2 +- src/video/android/SDL_androidmessagebox.h | 2 +- src/video/android/SDL_androidmouse.c | 2 +- src/video/android/SDL_androidmouse.h | 2 +- src/video/android/SDL_androidtouch.c | 2 +- src/video/android/SDL_androidtouch.h | 2 +- src/video/android/SDL_androidvideo.c | 2 +- src/video/android/SDL_androidvideo.h | 2 +- src/video/android/SDL_androidvulkan.c | 2 +- src/video/android/SDL_androidvulkan.h | 2 +- src/video/android/SDL_androidwindow.c | 2 +- src/video/android/SDL_androidwindow.h | 2 +- src/video/cocoa/SDL_cocoaclipboard.h | 2 +- src/video/cocoa/SDL_cocoaclipboard.m | 2 +- src/video/cocoa/SDL_cocoaevents.h | 2 +- src/video/cocoa/SDL_cocoaevents.m | 2 +- src/video/cocoa/SDL_cocoakeyboard.h | 2 +- src/video/cocoa/SDL_cocoakeyboard.m | 2 +- src/video/cocoa/SDL_cocoamessagebox.h | 2 +- src/video/cocoa/SDL_cocoamessagebox.m | 2 +- src/video/cocoa/SDL_cocoametalview.h | 2 +- src/video/cocoa/SDL_cocoametalview.m | 2 +- src/video/cocoa/SDL_cocoamodes.h | 2 +- src/video/cocoa/SDL_cocoamodes.m | 2 +- src/video/cocoa/SDL_cocoamouse.h | 2 +- src/video/cocoa/SDL_cocoamouse.m | 2 +- src/video/cocoa/SDL_cocoaopengl.h | 2 +- src/video/cocoa/SDL_cocoaopengl.m | 2 +- src/video/cocoa/SDL_cocoaopengles.h | 2 +- src/video/cocoa/SDL_cocoaopengles.m | 2 +- src/video/cocoa/SDL_cocoavideo.h | 2 +- src/video/cocoa/SDL_cocoavideo.m | 2 +- src/video/cocoa/SDL_cocoavulkan.h | 2 +- src/video/cocoa/SDL_cocoavulkan.m | 2 +- src/video/cocoa/SDL_cocoawindow.h | 2 +- src/video/cocoa/SDL_cocoawindow.m | 2 +- src/video/dummy/SDL_nullevents.c | 2 +- src/video/dummy/SDL_nullevents_c.h | 2 +- src/video/dummy/SDL_nullframebuffer.c | 2 +- src/video/dummy/SDL_nullframebuffer_c.h | 2 +- src/video/dummy/SDL_nullvideo.c | 2 +- src/video/dummy/SDL_nullvideo.h | 2 +- src/video/emscripten/SDL_emscriptenevents.c | 2 +- src/video/emscripten/SDL_emscriptenevents.h | 2 +- src/video/emscripten/SDL_emscriptenframebuffer.c | 2 +- src/video/emscripten/SDL_emscriptenframebuffer.h | 2 +- src/video/emscripten/SDL_emscriptenmouse.c | 2 +- src/video/emscripten/SDL_emscriptenmouse.h | 2 +- src/video/emscripten/SDL_emscriptenopengles.c | 2 +- src/video/emscripten/SDL_emscriptenopengles.h | 2 +- src/video/emscripten/SDL_emscriptenvideo.c | 2 +- src/video/emscripten/SDL_emscriptenvideo.h | 2 +- src/video/gdk/SDL_gdktextinput.cpp | 2 +- src/video/gdk/SDL_gdktextinput.h | 2 +- src/video/haiku/SDL_BApp.h | 2 +- src/video/haiku/SDL_BWin.h | 2 +- src/video/haiku/SDL_bclipboard.cc | 2 +- src/video/haiku/SDL_bclipboard.h | 2 +- src/video/haiku/SDL_bevents.cc | 2 +- src/video/haiku/SDL_bevents.h | 2 +- src/video/haiku/SDL_bframebuffer.cc | 2 +- src/video/haiku/SDL_bframebuffer.h | 2 +- src/video/haiku/SDL_bkeyboard.cc | 2 +- src/video/haiku/SDL_bkeyboard.h | 2 +- src/video/haiku/SDL_bmessagebox.cc | 2 +- src/video/haiku/SDL_bmessagebox.h | 2 +- src/video/haiku/SDL_bmodes.cc | 2 +- src/video/haiku/SDL_bmodes.h | 2 +- src/video/haiku/SDL_bopengl.cc | 2 +- src/video/haiku/SDL_bopengl.h | 2 +- src/video/haiku/SDL_bvideo.cc | 2 +- src/video/haiku/SDL_bvideo.h | 2 +- src/video/haiku/SDL_bwindow.cc | 2 +- src/video/haiku/SDL_bwindow.h | 2 +- src/video/kmsdrm/SDL_kmsdrmdyn.c | 2 +- src/video/kmsdrm/SDL_kmsdrmdyn.h | 2 +- src/video/kmsdrm/SDL_kmsdrmevents.c | 2 +- src/video/kmsdrm/SDL_kmsdrmevents.h | 2 +- src/video/kmsdrm/SDL_kmsdrmmouse.c | 2 +- src/video/kmsdrm/SDL_kmsdrmmouse.h | 2 +- src/video/kmsdrm/SDL_kmsdrmopengles.c | 2 +- src/video/kmsdrm/SDL_kmsdrmopengles.h | 2 +- src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvulkan.c | 2 +- src/video/kmsdrm/SDL_kmsdrmvulkan.h | 2 +- src/video/n3ds/SDL_n3dsevents.c | 2 +- src/video/n3ds/SDL_n3dsevents_c.h | 2 +- src/video/n3ds/SDL_n3dsframebuffer.c | 2 +- src/video/n3ds/SDL_n3dsframebuffer_c.h | 2 +- src/video/n3ds/SDL_n3dsswkb.c | 2 +- src/video/n3ds/SDL_n3dsswkb.h | 2 +- src/video/n3ds/SDL_n3dstouch.c | 2 +- src/video/n3ds/SDL_n3dstouch.h | 2 +- src/video/n3ds/SDL_n3dsvideo.c | 2 +- src/video/n3ds/SDL_n3dsvideo.h | 2 +- src/video/ngage/SDL_ngageevents.cpp | 2 +- src/video/ngage/SDL_ngageevents_c.h | 2 +- src/video/ngage/SDL_ngageframebuffer.cpp | 2 +- src/video/ngage/SDL_ngageframebuffer_c.h | 2 +- src/video/ngage/SDL_ngagevideo.cpp | 2 +- src/video/ngage/SDL_ngagevideo.h | 2 +- src/video/ngage/SDL_ngagewindow.cpp | 2 +- src/video/ngage/SDL_ngagewindow.h | 2 +- src/video/offscreen/SDL_offscreenevents.c | 2 +- src/video/offscreen/SDL_offscreenevents_c.h | 2 +- src/video/offscreen/SDL_offscreenframebuffer.c | 2 +- src/video/offscreen/SDL_offscreenframebuffer_c.h | 2 +- src/video/offscreen/SDL_offscreenopengles.c | 2 +- src/video/offscreen/SDL_offscreenopengles.h | 2 +- src/video/offscreen/SDL_offscreenvideo.c | 2 +- src/video/offscreen/SDL_offscreenvideo.h | 2 +- src/video/offscreen/SDL_offscreenwindow.c | 2 +- src/video/offscreen/SDL_offscreenwindow.h | 2 +- src/video/ps2/SDL_ps2video.c | 2 +- src/video/ps2/SDL_ps2video.h | 2 +- src/video/psp/SDL_pspevents.c | 2 +- src/video/psp/SDL_pspevents_c.h | 2 +- src/video/psp/SDL_pspgl.c | 2 +- src/video/psp/SDL_pspgl_c.h | 2 +- src/video/psp/SDL_pspmouse.c | 2 +- src/video/psp/SDL_pspmouse_c.h | 2 +- src/video/psp/SDL_pspvideo.c | 2 +- src/video/psp/SDL_pspvideo.h | 2 +- src/video/raspberry/SDL_rpievents.c | 2 +- src/video/raspberry/SDL_rpievents_c.h | 2 +- src/video/raspberry/SDL_rpimouse.c | 2 +- src/video/raspberry/SDL_rpimouse.h | 2 +- src/video/raspberry/SDL_rpiopengles.c | 2 +- src/video/raspberry/SDL_rpiopengles.h | 2 +- src/video/raspberry/SDL_rpivideo.c | 2 +- src/video/raspberry/SDL_rpivideo.h | 2 +- src/video/riscos/SDL_riscosdefs.h | 2 +- src/video/riscos/SDL_riscosevents.c | 2 +- src/video/riscos/SDL_riscosevents_c.h | 2 +- src/video/riscos/SDL_riscosframebuffer.c | 2 +- src/video/riscos/SDL_riscosframebuffer_c.h | 2 +- src/video/riscos/SDL_riscosmessagebox.c | 2 +- src/video/riscos/SDL_riscosmessagebox.h | 2 +- src/video/riscos/SDL_riscosmodes.c | 2 +- src/video/riscos/SDL_riscosmodes.h | 2 +- src/video/riscos/SDL_riscosmouse.c | 2 +- src/video/riscos/SDL_riscosmouse.h | 2 +- src/video/riscos/SDL_riscosvideo.c | 2 +- src/video/riscos/SDL_riscosvideo.h | 2 +- src/video/riscos/SDL_riscoswindow.c | 2 +- src/video/riscos/SDL_riscoswindow.h | 2 +- src/video/riscos/scancodes_riscos.h | 2 +- src/video/sdlgenblit.pl | 2 +- src/video/uikit/SDL_uikitappdelegate.h | 2 +- src/video/uikit/SDL_uikitappdelegate.m | 2 +- src/video/uikit/SDL_uikitclipboard.h | 2 +- src/video/uikit/SDL_uikitclipboard.m | 2 +- src/video/uikit/SDL_uikitevents.h | 2 +- src/video/uikit/SDL_uikitevents.m | 2 +- src/video/uikit/SDL_uikitmessagebox.h | 2 +- src/video/uikit/SDL_uikitmessagebox.m | 2 +- src/video/uikit/SDL_uikitmetalview.h | 2 +- src/video/uikit/SDL_uikitmetalview.m | 2 +- src/video/uikit/SDL_uikitmodes.h | 2 +- src/video/uikit/SDL_uikitmodes.m | 2 +- src/video/uikit/SDL_uikitopengles.h | 2 +- src/video/uikit/SDL_uikitopengles.m | 2 +- src/video/uikit/SDL_uikitopenglview.h | 2 +- src/video/uikit/SDL_uikitopenglview.m | 2 +- src/video/uikit/SDL_uikitvideo.h | 2 +- src/video/uikit/SDL_uikitvideo.m | 2 +- src/video/uikit/SDL_uikitview.h | 2 +- src/video/uikit/SDL_uikitview.m | 2 +- src/video/uikit/SDL_uikitviewcontroller.h | 2 +- src/video/uikit/SDL_uikitviewcontroller.m | 2 +- src/video/uikit/SDL_uikitvulkan.h | 2 +- src/video/uikit/SDL_uikitvulkan.m | 2 +- src/video/uikit/SDL_uikitwindow.h | 2 +- src/video/uikit/SDL_uikitwindow.m | 2 +- src/video/vita/SDL_vitaframebuffer.c | 2 +- src/video/vita/SDL_vitaframebuffer.h | 2 +- src/video/vita/SDL_vitagl_pvr.c | 2 +- src/video/vita/SDL_vitagl_pvr_c.h | 2 +- src/video/vita/SDL_vitagles.c | 2 +- src/video/vita/SDL_vitagles_c.h | 2 +- src/video/vita/SDL_vitagles_pvr.c | 2 +- src/video/vita/SDL_vitagles_pvr_c.h | 2 +- src/video/vita/SDL_vitakeyboard.c | 2 +- src/video/vita/SDL_vitakeyboard.h | 2 +- src/video/vita/SDL_vitamessagebox.c | 2 +- src/video/vita/SDL_vitamessagebox.h | 2 +- src/video/vita/SDL_vitamouse.c | 2 +- src/video/vita/SDL_vitamouse_c.h | 2 +- src/video/vita/SDL_vitatouch.c | 2 +- src/video/vita/SDL_vitatouch.h | 2 +- src/video/vita/SDL_vitavideo.c | 2 +- src/video/vita/SDL_vitavideo.h | 2 +- src/video/vivante/SDL_vivanteopengles.c | 2 +- src/video/vivante/SDL_vivanteopengles.h | 2 +- src/video/vivante/SDL_vivanteplatform.c | 2 +- src/video/vivante/SDL_vivanteplatform.h | 2 +- src/video/vivante/SDL_vivantevideo.c | 2 +- src/video/vivante/SDL_vivantevideo.h | 2 +- src/video/vivante/SDL_vivantevulkan.c | 2 +- src/video/vivante/SDL_vivantevulkan.h | 2 +- src/video/wayland/SDL_waylandclipboard.c | 2 +- src/video/wayland/SDL_waylandclipboard.h | 2 +- src/video/wayland/SDL_waylanddatamanager.c | 2 +- src/video/wayland/SDL_waylanddatamanager.h | 2 +- src/video/wayland/SDL_waylanddyn.c | 2 +- src/video/wayland/SDL_waylanddyn.h | 2 +- src/video/wayland/SDL_waylandevents.c | 2 +- src/video/wayland/SDL_waylandevents_c.h | 2 +- src/video/wayland/SDL_waylandkeyboard.c | 2 +- src/video/wayland/SDL_waylandkeyboard.h | 2 +- src/video/wayland/SDL_waylandmessagebox.c | 2 +- src/video/wayland/SDL_waylandmessagebox.h | 2 +- src/video/wayland/SDL_waylandmouse.c | 2 +- src/video/wayland/SDL_waylandmouse.h | 2 +- src/video/wayland/SDL_waylandopengles.c | 2 +- src/video/wayland/SDL_waylandopengles.h | 2 +- src/video/wayland/SDL_waylandsym.h | 2 +- src/video/wayland/SDL_waylandvideo.c | 2 +- src/video/wayland/SDL_waylandvideo.h | 2 +- src/video/wayland/SDL_waylandvulkan.c | 2 +- src/video/wayland/SDL_waylandvulkan.h | 2 +- src/video/wayland/SDL_waylandwindow.c | 2 +- src/video/wayland/SDL_waylandwindow.h | 2 +- src/video/windows/SDL_msctf.h | 2 +- src/video/windows/SDL_windowsclipboard.c | 2 +- src/video/windows/SDL_windowsclipboard.h | 2 +- src/video/windows/SDL_windowsevents.c | 2 +- src/video/windows/SDL_windowsevents.h | 2 +- src/video/windows/SDL_windowsframebuffer.c | 2 +- src/video/windows/SDL_windowsframebuffer.h | 2 +- src/video/windows/SDL_windowskeyboard.c | 2 +- src/video/windows/SDL_windowskeyboard.h | 2 +- src/video/windows/SDL_windowsmessagebox.c | 2 +- src/video/windows/SDL_windowsmessagebox.h | 2 +- src/video/windows/SDL_windowsmodes.c | 2 +- src/video/windows/SDL_windowsmodes.h | 2 +- src/video/windows/SDL_windowsmouse.c | 2 +- src/video/windows/SDL_windowsmouse.h | 2 +- src/video/windows/SDL_windowsopengl.c | 2 +- src/video/windows/SDL_windowsopengl.h | 2 +- src/video/windows/SDL_windowsopengles.c | 2 +- src/video/windows/SDL_windowsopengles.h | 2 +- src/video/windows/SDL_windowsvideo.c | 2 +- src/video/windows/SDL_windowsvideo.h | 2 +- src/video/windows/SDL_windowsvulkan.c | 2 +- src/video/windows/SDL_windowsvulkan.h | 2 +- src/video/windows/SDL_windowswindow.c | 2 +- src/video/windows/SDL_windowswindow.h | 2 +- src/video/windows/wmmsg.h | 2 +- src/video/winrt/SDL_winrtevents.cpp | 2 +- src/video/winrt/SDL_winrtevents_c.h | 2 +- src/video/winrt/SDL_winrtgamebar.cpp | 2 +- src/video/winrt/SDL_winrtgamebar_cpp.h | 2 +- src/video/winrt/SDL_winrtkeyboard.cpp | 2 +- src/video/winrt/SDL_winrtmessagebox.cpp | 2 +- src/video/winrt/SDL_winrtmessagebox.h | 2 +- src/video/winrt/SDL_winrtmouse.cpp | 2 +- src/video/winrt/SDL_winrtmouse_c.h | 2 +- src/video/winrt/SDL_winrtopengles.cpp | 2 +- src/video/winrt/SDL_winrtopengles.h | 2 +- src/video/winrt/SDL_winrtpointerinput.cpp | 2 +- src/video/winrt/SDL_winrtvideo.cpp | 2 +- src/video/winrt/SDL_winrtvideo_cpp.h | 2 +- src/video/x11/SDL_x11clipboard.c | 2 +- src/video/x11/SDL_x11clipboard.h | 2 +- src/video/x11/SDL_x11dyn.c | 2 +- src/video/x11/SDL_x11dyn.h | 2 +- src/video/x11/SDL_x11events.c | 2 +- src/video/x11/SDL_x11events.h | 2 +- src/video/x11/SDL_x11framebuffer.c | 2 +- src/video/x11/SDL_x11framebuffer.h | 2 +- src/video/x11/SDL_x11keyboard.c | 2 +- src/video/x11/SDL_x11keyboard.h | 2 +- src/video/x11/SDL_x11messagebox.c | 2 +- src/video/x11/SDL_x11messagebox.h | 2 +- src/video/x11/SDL_x11modes.c | 2 +- src/video/x11/SDL_x11modes.h | 2 +- src/video/x11/SDL_x11mouse.c | 2 +- src/video/x11/SDL_x11mouse.h | 2 +- src/video/x11/SDL_x11opengl.c | 2 +- src/video/x11/SDL_x11opengl.h | 2 +- src/video/x11/SDL_x11opengles.c | 2 +- src/video/x11/SDL_x11opengles.h | 2 +- src/video/x11/SDL_x11pen.c | 2 +- src/video/x11/SDL_x11pen.h | 2 +- src/video/x11/SDL_x11sym.h | 2 +- src/video/x11/SDL_x11touch.c | 2 +- src/video/x11/SDL_x11touch.h | 2 +- src/video/x11/SDL_x11video.c | 2 +- src/video/x11/SDL_x11video.h | 2 +- src/video/x11/SDL_x11vulkan.c | 2 +- src/video/x11/SDL_x11vulkan.h | 2 +- src/video/x11/SDL_x11window.c | 2 +- src/video/x11/SDL_x11window.h | 2 +- src/video/x11/SDL_x11xfixes.c | 2 +- src/video/x11/SDL_x11xfixes.h | 2 +- src/video/x11/SDL_x11xinput2.c | 2 +- src/video/x11/SDL_x11xinput2.h | 2 +- test/checkkeys.c | 2 +- test/checkkeysthreads.c | 2 +- test/gamepadutils.c | 2 +- test/gamepadutils.h | 2 +- test/loopwave.c | 2 +- test/pretest.c | 2 +- test/testatomic.c | 2 +- test/testaudiocapture.c | 2 +- test/testaudiohotplug.c | 2 +- test/testaudioinfo.c | 2 +- test/testaudiostreamdynamicresample.c | 2 +- test/testautomation.c | 2 +- test/testautomation_images.c | 2 +- test/testautomation_images.h | 2 +- test/testautomation_pen.c | 2 +- test/testbounds.c | 2 +- test/testcontroller.c | 2 +- test/testcustomcursor.c | 2 +- test/testdisplayinfo.c | 2 +- test/testdraw.c | 2 +- test/testdrawchessboard.c | 2 +- test/testdropfile.c | 2 +- test/testerror.c | 2 +- test/testevdev.c | 2 +- test/testffmpeg.c | 2 +- test/testffmpeg_videotoolbox.h | 2 +- test/testffmpeg_videotoolbox.m | 2 +- test/testfile.c | 2 +- test/testfilesystem.c | 2 +- test/testgeometry.c | 2 +- test/testgl.c | 2 +- test/testgles.c | 2 +- test/testgles2.c | 2 +- test/testgles2_sdf.c | 2 +- test/testhittesting.c | 2 +- test/testhotplug.c | 2 +- test/testiconv.c | 2 +- test/testime.c | 2 +- test/testintersections.c | 2 +- test/testkeys.c | 2 +- test/testloadso.c | 2 +- test/testlocale.c | 2 +- test/testlock.c | 2 +- test/testmessage.c | 2 +- test/testmouse.c | 2 +- test/testmultiaudio.c | 2 +- test/testnative.c | 2 +- test/testnative.h | 2 +- test/testnativew32.c | 2 +- test/testnativex11.c | 2 +- test/testoffscreen.c | 2 +- test/testoverlay.c | 2 +- test/testpen.c | 2 +- test/testplatform.c | 2 +- test/testpopup.c | 2 +- test/testpower.c | 2 +- test/testqsort.c | 2 +- test/testrelative.c | 2 +- test/testrendercopyex.c | 2 +- test/testrendertarget.c | 2 +- test/testresample.c | 2 +- test/testrumble.c | 2 +- test/testrwlock.c | 2 +- test/testscale.c | 2 +- test/testsem.c | 2 +- test/testsensor.c | 2 +- test/testshader.c | 2 +- test/testshape.c | 2 +- test/testsprite.c | 2 +- test/testspriteminimal.c | 2 +- test/teststreaming.c | 2 +- test/testsurround.c | 2 +- test/testthread.c | 2 +- test/testtimer.c | 2 +- test/testurl.c | 2 +- test/testutils.c | 2 +- test/testutils.h | 2 +- test/testver.c | 2 +- test/testvideocapture.c | 2 +- test/testvideocaptureminimal.c | 2 +- test/testviewport.c | 2 +- test/testvulkan.c | 2 +- test/testwm.c | 2 +- test/testyuv.c | 2 +- test/testyuv_cvt.c | 2 +- test/testyuv_cvt.h | 2 +- test/torturethread.c | 2 +- 1023 files changed, 1025 insertions(+), 1025 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 83d8937efee76..74bb56cdd5d81 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 1997-2023 Sam Lantinga +Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/VisualC-GDK/tests/testgdk/src/testgdk.cpp index 50f93e2fab918..f65fd4b964557 100644 --- a/VisualC-GDK/tests/testgdk/src/testgdk.cpp +++ b/VisualC-GDK/tests/testgdk/src/testgdk.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/Xcode/SDL/pkg-support/resources/License.txt b/Xcode/SDL/pkg-support/resources/License.txt index 523c51e4968a7..42f37361d4462 100644 --- a/Xcode/SDL/pkg-support/resources/License.txt +++ b/Xcode/SDL/pkg-support/resources/License.txt @@ -1,6 +1,6 @@ Simple DirectMedia Layer -Copyright (C) 1997-2023 Sam Lantinga +Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/build-scripts/check_stdlib_usage.py b/build-scripts/check_stdlib_usage.py index 830a04a3ca0fd..5e62ff1876e16 100755 --- a/build-scripts/check_stdlib_usage.py +++ b/build-scripts/check_stdlib_usage.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # # Simple DirectMedia Layer -# Copyright (C) 1997-2023 Sam Lantinga +# Copyright (C) 1997-2024 Sam Lantinga # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages diff --git a/build-scripts/gen_audio_channel_conversion.c b/build-scripts/gen_audio_channel_conversion.c index 720a9e5997cee..f774e7db89dc7 100644 --- a/build-scripts/gen_audio_channel_conversion.c +++ b/build-scripts/gen_audio_channel_conversion.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -406,7 +406,7 @@ int main(void) printf( "/*\n" " Simple DirectMedia Layer\n" - " Copyright (C) 1997-2023 Sam Lantinga \n" + " Copyright (C) 1997-2024 Sam Lantinga \n" "\n" " This software is provided 'as-is', without any express or implied\n" " warranty. In no event will the authors be held liable for any damages\n" diff --git a/build-scripts/gen_audio_resampler_filter.c b/build-scripts/gen_audio_resampler_filter.c index 732b873d2347d..c115484a9cdb3 100644 --- a/build-scripts/gen_audio_resampler_filter.c +++ b/build-scripts/gen_audio_resampler_filter.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -109,7 +109,7 @@ int main(void) printf( "/*\n" " Simple DirectMedia Layer\n" - " Copyright (C) 1997-2023 Sam Lantinga \n" + " Copyright (C) 1997-2024 Sam Lantinga \n" "\n" " This software is provided 'as-is', without any express or implied\n" " warranty. In no event will the authors be held liable for any damages\n" diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index 3ace34f314e62..a0a77e539d9c5 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_assert.h b/include/SDL3/SDL_assert.h index cdf1da17774bd..e4f553e4f6b81 100644 --- a/include/SDL3/SDL_assert.h +++ b/include/SDL3/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_atomic.h b/include/SDL3/SDL_atomic.h index ece4ac5a3613e..8198e923e7d18 100644 --- a/include/SDL3/SDL_atomic.h +++ b/include/SDL3/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 7ce55ef206090..1dbfcb117af4b 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_begin_code.h b/include/SDL3/SDL_begin_code.h index 6f52f9fbcdceb..1280382512767 100644 --- a/include/SDL3/SDL_begin_code.h +++ b/include/SDL3/SDL_begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_bits.h b/include/SDL3/SDL_bits.h index 1d7c09c173aa8..d4a3aff355a04 100644 --- a/include/SDL3/SDL_bits.h +++ b/include/SDL3/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_blendmode.h b/include/SDL3/SDL_blendmode.h index d84d2ba926c06..4b1b4ee490a5e 100644 --- a/include/SDL3/SDL_blendmode.h +++ b/include/SDL3/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_clipboard.h b/include/SDL3/SDL_clipboard.h index 5f05034bfaee2..84317613f80ed 100644 --- a/include/SDL3/SDL_clipboard.h +++ b/include/SDL3/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_close_code.h b/include/SDL3/SDL_close_code.h index 55cf3ff3b92d9..7e51e665f22ac 100644 --- a/include/SDL3/SDL_close_code.h +++ b/include/SDL3/SDL_close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_copying.h b/include/SDL3/SDL_copying.h index 4fd0ca11f2b04..6f6ade5e942d7 100644 --- a/include/SDL3/SDL_copying.h +++ b/include/SDL3/SDL_copying.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_cpuinfo.h b/include/SDL3/SDL_cpuinfo.h index 0813c4d283d02..c4b3d3988906b 100644 --- a/include/SDL3/SDL_cpuinfo.h +++ b/include/SDL3/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_egl.h b/include/SDL3/SDL_egl.h index 1053b4c31448f..1945a8fdaa577 100644 --- a/include/SDL3/SDL_egl.h +++ b/include/SDL3/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_endian.h b/include/SDL3/SDL_endian.h index d670265f1cc39..480fe5ff5078c 100644 --- a/include/SDL3/SDL_endian.h +++ b/include/SDL3/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_error.h b/include/SDL3/SDL_error.h index 26b7d33d7f966..b6ae7aec03e0d 100644 --- a/include/SDL3/SDL_error.h +++ b/include/SDL3/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 11276e5ff53bd..32655f7c62c4d 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 79024d2168f5e..8ee4d2c27a646 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 40df9ca5a09c7..be970e640b8fe 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_guid.h b/include/SDL3/SDL_guid.h index 11f1ffa6c27cf..accb4d9a5c180 100644 --- a/include/SDL3/SDL_guid.h +++ b/include/SDL3/SDL_guid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_haptic.h b/include/SDL3/SDL_haptic.h index 1b336ffb53351..757099440f7b4 100644 --- a/include/SDL3/SDL_haptic.h +++ b/include/SDL3/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_hidapi.h b/include/SDL3/SDL_hidapi.h index 3a1bbace0f53b..422c329acd993 100644 --- a/include/SDL3/SDL_hidapi.h +++ b/include/SDL3/SDL_hidapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index baf43e54a78df..e12093360e952 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_init.h b/include/SDL3/SDL_init.h index ce41eb99b0d9e..472afc9947a32 100644 --- a/include/SDL3/SDL_init.h +++ b/include/SDL3/SDL_init.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_intrin.h b/include/SDL3/SDL_intrin.h index 5d276d6ee419e..d75ce78876263 100644 --- a/include/SDL3/SDL_intrin.h +++ b/include/SDL3/SDL_intrin.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index 6fa5d171deaeb..80f210d6d4528 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index 35f6141ba9995..042ae43d07cdd 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_keycode.h b/include/SDL3/SDL_keycode.h index 31899c3f952cf..e94ace90bacad 100644 --- a/include/SDL3/SDL_keycode.h +++ b/include/SDL3/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_loadso.h b/include/SDL3/SDL_loadso.h index 41439fd2d23d8..58e14d37f6e5f 100644 --- a/include/SDL3/SDL_loadso.h +++ b/include/SDL3/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_locale.h b/include/SDL3/SDL_locale.h index 4e3932ce7f7b4..7ac803ca37dfd 100644 --- a/include/SDL3/SDL_locale.h +++ b/include/SDL3/SDL_locale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h index bda15070fa3e4..dd33ad9427c2e 100644 --- a/include/SDL3/SDL_log.h +++ b/include/SDL3/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index e914415193c72..76f08f100ca50 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index 8eb8bb54952a4..33a3d4347a20d 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_messagebox.h b/include/SDL3/SDL_messagebox.h index e1ee10aef6aba..17696c6494729 100644 --- a/include/SDL3/SDL_messagebox.h +++ b/include/SDL3/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_metal.h b/include/SDL3/SDL_metal.h index 6568871235fa2..016ee94747d28 100644 --- a/include/SDL3/SDL_metal.h +++ b/include/SDL3/SDL_metal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_misc.h b/include/SDL3/SDL_misc.h index ae1b32de83c67..e50d91bd1389c 100644 --- a/include/SDL3/SDL_misc.h +++ b/include/SDL3/SDL_misc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index c00d769885f12..d9df80df8db3e 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index f0a0e7d96ed58..d4610cb40284b 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index d0fa5da1843ca..bc5366ee94559 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_opengl.h b/include/SDL3/SDL_opengl.h index 6eb7c90b9763c..9fb298f908fd3 100644 --- a/include/SDL3/SDL_opengl.h +++ b/include/SDL3/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_opengles.h b/include/SDL3/SDL_opengles.h index 5f50b5385305a..8f4b66764984d 100644 --- a/include/SDL3/SDL_opengles.h +++ b/include/SDL3/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_opengles2.h b/include/SDL3/SDL_opengles2.h index abbe47b76e2fc..a3b3788526903 100644 --- a/include/SDL3/SDL_opengles2.h +++ b/include/SDL3/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index 0edd3512b1fa8..36c67b7cf7d29 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 3d39e2e982598..383def8c915ce 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_platform.h b/include/SDL3/SDL_platform.h index b2171fbbfb1aa..289d02dacb845 100644 --- a/include/SDL3/SDL_platform.h +++ b/include/SDL3/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h index da657bc504aa2..55a55c30653cc 100644 --- a/include/SDL3/SDL_platform_defines.h +++ b/include/SDL3/SDL_platform_defines.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_power.h b/include/SDL3/SDL_power.h index 5bb381b90a954..d957f237e4412 100644 --- a/include/SDL3/SDL_power.h +++ b/include/SDL3/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index 4e535aaacce7c..c5d3daca64392 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -1,6 +1,6 @@ /* Simple DiretMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_quit.h b/include/SDL3/SDL_quit.h index 18ef4142ed241..1361dff4d0fc3 100644 --- a/include/SDL3/SDL_quit.h +++ b/include/SDL3/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_rect.h b/include/SDL3/SDL_rect.h index 1b5ce0410fc93..4d03884d44197 100644 --- a/include/SDL3/SDL_rect.h +++ b/include/SDL3/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 15b0836b485e1..3923350968286 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_revision.h b/include/SDL3/SDL_revision.h index 7af451e11090a..badf017d18ce6 100644 --- a/include/SDL3/SDL_revision.h +++ b/include/SDL3/SDL_revision.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h index 86b53347b3653..557bdb8116620 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_scancode.h b/include/SDL3/SDL_scancode.h index 384aa5a48c748..6d3728dd28189 100644 --- a/include/SDL3/SDL_scancode.h +++ b/include/SDL3/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h index 9df4e71da2e76..6db5beb38bb3d 100644 --- a/include/SDL3/SDL_sensor.h +++ b/include/SDL3/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 90cf90530bced..4f864873e1264 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 8742cd1b78303..7ccbda915557c 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index 04b2cce56f06f..2b20dbe7f4144 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test.h b/include/SDL3/SDL_test.h index 3e51601dd7f75..634382cf41cdd 100644 --- a/include/SDL3/SDL_test.h +++ b/include/SDL3/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_assert.h b/include/SDL3/SDL_test_assert.h index 329367ea2eba9..122c355bd2ce2 100644 --- a/include/SDL3/SDL_test_assert.h +++ b/include/SDL3/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index c54a20084662b..0d428e1cfdc21 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_compare.h b/include/SDL3/SDL_test_compare.h index 985fd8ec8b06c..4bd0db3157012 100644 --- a/include/SDL3/SDL_test_compare.h +++ b/include/SDL3/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_crc32.h b/include/SDL3/SDL_test_crc32.h index fc91673d0b67d..a4103f5c22493 100644 --- a/include/SDL3/SDL_test_crc32.h +++ b/include/SDL3/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_font.h b/include/SDL3/SDL_test_font.h index e7fd3f7248828..824f97c2504e3 100644 --- a/include/SDL3/SDL_test_font.h +++ b/include/SDL3/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_fuzzer.h b/include/SDL3/SDL_test_fuzzer.h index c8ddc8b9852a1..14c5dc9b91a08 100644 --- a/include/SDL3/SDL_test_fuzzer.h +++ b/include/SDL3/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_harness.h b/include/SDL3/SDL_test_harness.h index 45944faafe416..b17e0b30aba02 100644 --- a/include/SDL3/SDL_test_harness.h +++ b/include/SDL3/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_log.h b/include/SDL3/SDL_test_log.h index 62db0a865a669..315d0ae0eadf5 100644 --- a/include/SDL3/SDL_test_log.h +++ b/include/SDL3/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_md5.h b/include/SDL3/SDL_test_md5.h index 0a4e9f05ea648..4aa06340bef1c 100644 --- a/include/SDL3/SDL_test_md5.h +++ b/include/SDL3/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_memory.h b/include/SDL3/SDL_test_memory.h index fb62b20f09060..6d858efdff8bc 100644 --- a/include/SDL3/SDL_test_memory.h +++ b/include/SDL3/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_test_random.h b/include/SDL3/SDL_test_random.h index 69c75c6a6282f..5c3e84a8dcc17 100644 --- a/include/SDL3/SDL_test_random.h +++ b/include/SDL3/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_thread.h b/include/SDL3/SDL_thread.h index d2979486d17ca..22b91cbab13a3 100644 --- a/include/SDL3/SDL_thread.h +++ b/include/SDL3/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_timer.h b/include/SDL3/SDL_timer.h index 99c4795c81727..b87620409e380 100644 --- a/include/SDL3/SDL_timer.h +++ b/include/SDL3/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index 58a8461c93f85..4140668f39eca 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_version.h b/include/SDL3/SDL_version.h index 4f34f9487c26d..61ab8548f5e6f 100644 --- a/include/SDL3/SDL_version.h +++ b/include/SDL3/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 755bbac31f06c..d20bd0ee9ad66 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL3/SDL_video_capture.h b/include/SDL3/SDL_video_capture.h index 12baaf5a46057..80a21605460a8 100644 --- a/include/SDL3/SDL_video_capture.h +++ b/include/SDL3/SDL_video_capture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config.h b/include/build_config/SDL_build_config.h index 138e571f8d945..6fa6d899bfe93 100644 --- a/include/build_config/SDL_build_config.h +++ b/include/build_config/SDL_build_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index b725a98e14806..3a201d7e5f05b 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h index 99a7ab7deca2e..ad75cc1fbabc4 100644 --- a/include/build_config/SDL_build_config_android.h +++ b/include/build_config/SDL_build_config_android.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_emscripten.h b/include/build_config/SDL_build_config_emscripten.h index afa4e16e11c7e..fcaa277c0d5df 100644 --- a/include/build_config/SDL_build_config_emscripten.h +++ b/include/build_config/SDL_build_config_emscripten.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index 340bbc0c29971..a6691465e8c44 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index bf1b682ed02b5..66bdb5ea42808 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_minimal.h b/include/build_config/SDL_build_config_minimal.h index b94d080874001..689234a885a37 100644 --- a/include/build_config/SDL_build_config_minimal.h +++ b/include/build_config/SDL_build_config_minimal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_ngage.h b/include/build_config/SDL_build_config_ngage.h index 13d97d2213c7b..1942ef464f2b0 100644 --- a/include/build_config/SDL_build_config_ngage.h +++ b/include/build_config/SDL_build_config_ngage.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index 4d7242e5b5d34..d83857d689ecd 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_wingdk.h b/include/build_config/SDL_build_config_wingdk.h index 8d587e555f1e7..0999b87f2b0e7 100644 --- a/include/build_config/SDL_build_config_wingdk.h +++ b/include/build_config/SDL_build_config_wingdk.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_winrt.h b/include/build_config/SDL_build_config_winrt.h index bc65ffea2ffdd..3b252cec930a5 100644 --- a/include/build_config/SDL_build_config_winrt.h +++ b/include/build_config/SDL_build_config_winrt.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 08def0c0146c4..1a31c0d7fa409 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/build_config/SDL_revision.h.cmake b/include/build_config/SDL_revision.h.cmake index 17aa1051d6fe9..bd94c5f2f2fc0 100644 --- a/include/build_config/SDL_revision.h.cmake +++ b/include/build_config/SDL_revision.h.cmake @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL.c b/src/SDL.c index 302e625e90dc8..d39303ffe12d4 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_assert.c b/src/SDL_assert.c index 6c2491aaca0ea..fd167430fb257 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_assert_c.h b/src/SDL_assert_c.h index 37934f31c3bf9..f4f1d2f8bba2b 100644 --- a/src/SDL_assert_c.h +++ b/src/SDL_assert_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_error.c b/src/SDL_error.c index c8db336814457..f01fd3c88deca 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_error_c.h b/src/SDL_error_c.h index ed5d06b49f620..c3e4f78224ffa 100644 --- a/src/SDL_error_c.h +++ b/src/SDL_error_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_guid.c b/src/SDL_guid.c index fc68db4291001..a73852ddcdc9f 100644 --- a/src/SDL_guid.c +++ b/src/SDL_guid.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index b6a8b0d49cd34..25b893b6a37d1 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h index 44a1788724064..96614bc17d7bd 100644 --- a/src/SDL_hashtable.h +++ b/src/SDL_hashtable.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_hints.c b/src/SDL_hints.c index e45823a4ebb1c..b3cebbf9dc0ba 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_hints_c.h b/src/SDL_hints_c.h index e71314781dd1b..68cceac7f36d5 100644 --- a/src/SDL_hints_c.h +++ b/src/SDL_hints_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_internal.h b/src/SDL_internal.h index 2ae4ba2dd802f..bfca0782cdbcc 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_list.c b/src/SDL_list.c index b6ea10d105c0d..4d03e78ea39ef 100644 --- a/src/SDL_list.c +++ b/src/SDL_list.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_list.h b/src/SDL_list.h index a42897a9c693d..583f78aa07325 100644 --- a/src/SDL_list.h +++ b/src/SDL_list.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_log.c b/src/SDL_log.c index aea6ce38697e8..198be022081b4 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_log_c.h b/src/SDL_log_c.h index e62eff4ae2cfd..3da88d6842ec6 100644 --- a/src/SDL_log_c.h +++ b/src/SDL_log_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 27271a4872993..83e5dd682b6dc 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -1,6 +1,6 @@ /* Simple DiretMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_properties_c.h b/src/SDL_properties_c.h index 10b4df4aed186..9b590cde3dad4 100644 --- a/src/SDL_properties_c.h +++ b/src/SDL_properties_c.h @@ -1,6 +1,6 @@ /* Simple DiretMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_utils.c b/src/SDL_utils.c index 7401d1cbef91b..581964b0d8a52 100644 --- a/src/SDL_utils.c +++ b/src/SDL_utils.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SDL_utils_c.h b/src/SDL_utils_c.h index d4c8387e86257..98658c3613599 100644 --- a/src/SDL_utils_c.h +++ b/src/SDL_utils_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index 5ffa2e61eabd0..2919e80004ed1 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index 25615accc452c..82dcace1d4c6c 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index c43506426e0c7..99488a75d5075 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h index 949d9e6c6e2c9..95cac81aac48e 100644 --- a/src/audio/SDL_audio_c.h +++ b/src/audio/SDL_audio_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audio_channel_converters.h b/src/audio/SDL_audio_channel_converters.h index 5fe6df52fb4a1..a005a7ee25f57 100644 --- a/src/audio/SDL_audio_channel_converters.h +++ b/src/audio/SDL_audio_channel_converters.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audio_resampler_filter.h b/src/audio/SDL_audio_resampler_filter.h index 42e4666506c52..ae12a97aca411 100644 --- a/src/audio/SDL_audio_resampler_filter.h +++ b/src/audio/SDL_audio_resampler_filter.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 27f69f7020c7d..54b8189d33017 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index f49a9fe7fdcce..ad8a2ad099023 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audiodev_c.h b/src/audio/SDL_audiodev_c.h index 53d451fc10bd7..8ea867c25e013 100644 --- a/src/audio/SDL_audiodev_c.h +++ b/src/audio/SDL_audiodev_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audioqueue.c b/src/audio/SDL_audioqueue.c index 085e8aaee02db..d5a9e3ac6ee98 100644 --- a/src/audio/SDL_audioqueue.c +++ b/src/audio/SDL_audioqueue.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audioqueue.h b/src/audio/SDL_audioqueue.h index 76012e91db3ca..9b18a5c5eb05e 100644 --- a/src/audio/SDL_audioqueue.h +++ b/src/audio/SDL_audioqueue.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audioresample.c b/src/audio/SDL_audioresample.c index a357fab9e306d..9ca6d0a223559 100644 --- a/src/audio/SDL_audioresample.c +++ b/src/audio/SDL_audioresample.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audioresample.h b/src/audio/SDL_audioresample.h index fcf3f5121760b..9a6920e08d5c8 100644 --- a/src/audio/SDL_audioresample.h +++ b/src/audio/SDL_audioresample.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 6f54265a83c62..770922bbaa8fc 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_mixer.c b/src/audio/SDL_mixer.c index 30b099346f488..4e71620b08d21 100644 --- a/src/audio/SDL_mixer.c +++ b/src/audio/SDL_mixer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 649e50651c3aa..eb6b38bad83ef 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 1af3b97e1b273..633783af43301 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/SDL_wave.h b/src/audio/SDL_wave.h index f91a2803dfdd0..66128f7520f25 100644 --- a/src/audio/SDL_wave.h +++ b/src/audio/SDL_wave.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index d46f671b67fd0..4445ba8c85ed7 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/aaudio/SDL_aaudio.h b/src/audio/aaudio/SDL_aaudio.h index 61cce54cf7113..3354304a1fc00 100644 --- a/src/audio/aaudio/SDL_aaudio.h +++ b/src/audio/aaudio/SDL_aaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/aaudio/SDL_aaudiofuncs.h b/src/audio/aaudio/SDL_aaudiofuncs.h index 0fba87d1ed7be..59771b380f005 100644 --- a/src/audio/aaudio/SDL_aaudiofuncs.h +++ b/src/audio/aaudio/SDL_aaudiofuncs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright , (C) 1997-2023 Sam Lantinga + Copyright , (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 98953a96ae3ba..c0f696b9c0dc3 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/alsa/SDL_alsa_audio.h b/src/audio/alsa/SDL_alsa_audio.h index 2d41b3f1cc4b7..1209fe2d12583 100644 --- a/src/audio/alsa/SDL_alsa_audio.h +++ b/src/audio/alsa/SDL_alsa_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index 55be7dddd8d02..0c8713ee7143d 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/android/SDL_androidaudio.h b/src/audio/android/SDL_androidaudio.h index 5efdc419d0da0..ba00e61510f04 100644 --- a/src/audio/android/SDL_androidaudio.h +++ b/src/audio/android/SDL_androidaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/coreaudio/SDL_coreaudio.h b/src/audio/coreaudio/SDL_coreaudio.h index 6c4891da2a0d5..ffa221fef38eb 100644 --- a/src/audio/coreaudio/SDL_coreaudio.h +++ b/src/audio/coreaudio/SDL_coreaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 2133b992c9cc7..79fc65aa49c78 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index 305f3d4615345..cd659c062f407 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/directsound/SDL_directsound.h b/src/audio/directsound/SDL_directsound.h index 18b67dac277b9..e3e0c2695d816 100644 --- a/src/audio/directsound/SDL_directsound.h +++ b/src/audio/directsound/SDL_directsound.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index 8a523318770ff..e0fd415fa2c18 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/disk/SDL_diskaudio.h b/src/audio/disk/SDL_diskaudio.h index 97930b0b141e5..81d22b65739b9 100644 --- a/src/audio/disk/SDL_diskaudio.h +++ b/src/audio/disk/SDL_diskaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index a9c3c22d2fd3d..e9412e083410f 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/dsp/SDL_dspaudio.h b/src/audio/dsp/SDL_dspaudio.h index 00d329be5b364..b7634e16132cc 100644 --- a/src/audio/dsp/SDL_dspaudio.h +++ b/src/audio/dsp/SDL_dspaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index 91775d3722a0e..19c4b4f093342 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/dummy/SDL_dummyaudio.h b/src/audio/dummy/SDL_dummyaudio.h index d629e0d8b1bb5..6f4c31c97917f 100644 --- a/src/audio/dummy/SDL_dummyaudio.h +++ b/src/audio/dummy/SDL_dummyaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index 6c8fc60a4226b..764f0b5598254 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/emscripten/SDL_emscriptenaudio.h b/src/audio/emscripten/SDL_emscriptenaudio.h index 89a08a9655b45..d10d4a2ae5fbf 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.h +++ b/src/audio/emscripten/SDL_emscriptenaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index 5772fbe056507..ed234d01f3485 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/haiku/SDL_haikuaudio.h b/src/audio/haiku/SDL_haikuaudio.h index 9187ef642291e..6ba2bb22adbf3 100644 --- a/src/audio/haiku/SDL_haikuaudio.h +++ b/src/audio/haiku/SDL_haikuaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 8c79a7eeea53a..3fb16fdede90f 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/jack/SDL_jackaudio.h b/src/audio/jack/SDL_jackaudio.h index 9a9d082f85104..4fe0053ff790a 100644 --- a/src/audio/jack/SDL_jackaudio.h +++ b/src/audio/jack/SDL_jackaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/n3ds/SDL_n3dsaudio.c b/src/audio/n3ds/SDL_n3dsaudio.c index 7692d7853ee47..35f9a31960d2d 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.c +++ b/src/audio/n3ds/SDL_n3dsaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/n3ds/SDL_n3dsaudio.h b/src/audio/n3ds/SDL_n3dsaudio.h index e0f6617f5da63..932944d374e5a 100644 --- a/src/audio/n3ds/SDL_n3dsaudio.h +++ b/src/audio/n3ds/SDL_n3dsaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c index ac2606302633d..f0de69482e811 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.c +++ b/src/audio/netbsd/SDL_netbsdaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/netbsd/SDL_netbsdaudio.h b/src/audio/netbsd/SDL_netbsdaudio.h index 72bbacfe9df28..dc3247cb43d6f 100644 --- a/src/audio/netbsd/SDL_netbsdaudio.h +++ b/src/audio/netbsd/SDL_netbsdaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index 4253ebcadfcf7..84f92a41b8dfa 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/openslES/SDL_openslES.h b/src/audio/openslES/SDL_openslES.h index a13e11129d935..9d65a7dabfeec 100644 --- a/src/audio/openslES/SDL_openslES.h +++ b/src/audio/openslES/SDL_openslES.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 00e46942288f1..492b0e493dfb8 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/pipewire/SDL_pipewire.h b/src/audio/pipewire/SDL_pipewire.h index 1350fffb14d94..1b07185cee86e 100644 --- a/src/audio/pipewire/SDL_pipewire.h +++ b/src/audio/pipewire/SDL_pipewire.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/ps2/SDL_ps2audio.c b/src/audio/ps2/SDL_ps2audio.c index 0971031c5117e..a8230715d6c40 100644 --- a/src/audio/ps2/SDL_ps2audio.c +++ b/src/audio/ps2/SDL_ps2audio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/ps2/SDL_ps2audio.h b/src/audio/ps2/SDL_ps2audio.h index 5b5f71a8cf277..d75cb8bf08ad7 100644 --- a/src/audio/ps2/SDL_ps2audio.h +++ b/src/audio/ps2/SDL_ps2audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index f2b771661cc81..5783e7df09dfb 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/psp/SDL_pspaudio.h b/src/audio/psp/SDL_pspaudio.h index da535e2a72f9e..6b3c0006501f0 100644 --- a/src/audio/psp/SDL_pspaudio.h +++ b/src/audio/psp/SDL_pspaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index bf86b49caf21f..2d0ca10094eeb 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/pulseaudio/SDL_pulseaudio.h b/src/audio/pulseaudio/SDL_pulseaudio.h index cc5e67e2aa95b..1d209cb1e424d 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/src/audio/pulseaudio/SDL_pulseaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/qnx/SDL_qsa_audio.c b/src/audio/qnx/SDL_qsa_audio.c index 0e2d37cf4a6d3..6b69670cf142d 100644 --- a/src/audio/qnx/SDL_qsa_audio.c +++ b/src/audio/qnx/SDL_qsa_audio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2021 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/qnx/SDL_qsa_audio.h b/src/audio/qnx/SDL_qsa_audio.h index e092612e065af..ea53752092989 100644 --- a/src/audio/qnx/SDL_qsa_audio.h +++ b/src/audio/qnx/SDL_qsa_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2021 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 59205889e5343..ee35d3f39de4b 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/sndio/SDL_sndioaudio.h b/src/audio/sndio/SDL_sndioaudio.h index 3337b18452c06..11a8d608ddedf 100644 --- a/src/audio/sndio/SDL_sndioaudio.h +++ b/src/audio/sndio/SDL_sndioaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c index 865752c2b7ee8..2de08d93c5c4c 100644 --- a/src/audio/vita/SDL_vitaaudio.c +++ b/src/audio/vita/SDL_vitaaudio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/vita/SDL_vitaaudio.h b/src/audio/vita/SDL_vitaaudio.h index 00b6d4812f339..35b46e5f3c6b2 100644 --- a/src/audio/vita/SDL_vitaaudio.h +++ b/src/audio/vita/SDL_vitaaudio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 294f6420b1a93..5eae508b3ea14 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/wasapi/SDL_wasapi.h b/src/audio/wasapi/SDL_wasapi.h index 8207c32cef87d..45a8173510cba 100644 --- a/src/audio/wasapi/SDL_wasapi.h +++ b/src/audio/wasapi/SDL_wasapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 6c95e9ee655a6..fd84394fb9830 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/audio/wasapi/SDL_wasapi_winrt.cpp b/src/audio/wasapi/SDL_wasapi_winrt.cpp index 7fce6776051e0..0af821d7b1228 100644 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c index 82329b0f0b057..d67dab04dceb6 100644 --- a/src/core/SDL_core_unsupported.c +++ b/src/core/SDL_core_unsupported.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/SDL_runapp.c b/src/core/SDL_runapp.c index bb5a602168c43..52c7ede11bb60 100644 --- a/src/core/SDL_runapp.c +++ b/src/core/SDL_runapp.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index c34c301105b6e..8b3dc1507c5f0 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index 10c95161f9329..c1256306b3465 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c index a89003ed2227b..2c1df4a8d2297 100644 --- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/gdk/SDL_gdk.cpp b/src/core/gdk/SDL_gdk.cpp index c2dd14e244d2c..2c4469b407d3c 100644 --- a/src/core/gdk/SDL_gdk.cpp +++ b/src/core/gdk/SDL_gdk.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/gdk/SDL_gdk.h b/src/core/gdk/SDL_gdk.h index 645b59a2e94ab..d500c41fd036c 100644 --- a/src/core/gdk/SDL_gdk.h +++ b/src/core/gdk/SDL_gdk.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/haiku/SDL_BApp.h b/src/core/haiku/SDL_BApp.h index 6deaff2ec5fc5..39fec77829cdd 100644 --- a/src/core/haiku/SDL_BApp.h +++ b/src/core/haiku/SDL_BApp.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/haiku/SDL_BeApp.cc b/src/core/haiku/SDL_BeApp.cc index 7f62bc52e4c4a..ccb9a4db312c4 100644 --- a/src/core/haiku/SDL_BeApp.cc +++ b/src/core/haiku/SDL_BeApp.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/haiku/SDL_BeApp.h b/src/core/haiku/SDL_BeApp.h index ec8bd7fafcfb9..fde331aec9db4 100644 --- a/src/core/haiku/SDL_BeApp.h +++ b/src/core/haiku/SDL_BeApp.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index 900e1a1b248dc..8bfbec8ad0634 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_dbus.h b/src/core/linux/SDL_dbus.h index 7a6feeb3c9ec2..c37de56aa18bc 100644 --- a/src/core/linux/SDL_dbus.h +++ b/src/core/linux/SDL_dbus.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index c12fcf0bb702d..f7e26b12deec7 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev.h b/src/core/linux/SDL_evdev.h index c9ac38edd2a33..fc7c4bd53f28a 100644 --- a/src/core/linux/SDL_evdev.h +++ b/src/core/linux/SDL_evdev.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c index 96653f6465aae..865abf4feb978 100644 --- a/src/core/linux/SDL_evdev_capabilities.c +++ b/src/core/linux/SDL_evdev_capabilities.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2020 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/src/core/linux/SDL_evdev_capabilities.h b/src/core/linux/SDL_evdev_capabilities.h index ca90309ed0e61..49df8da79dec0 100644 --- a/src/core/linux/SDL_evdev_capabilities.h +++ b/src/core/linux/SDL_evdev_capabilities.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2020 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index cf768cdf74e4a..7c81b5444eec0 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev_kbd.h b/src/core/linux/SDL_evdev_kbd.h index 73cff0bc3a75e..7c38bc9d59062 100644 --- a/src/core/linux/SDL_evdev_kbd.h +++ b/src/core/linux/SDL_evdev_kbd.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev_kbd_default_accents.h b/src/core/linux/SDL_evdev_kbd_default_accents.h index 1bf49c1b28b5e..259e6572ae082 100644 --- a/src/core/linux/SDL_evdev_kbd_default_accents.h +++ b/src/core/linux/SDL_evdev_kbd_default_accents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_evdev_kbd_default_keymap.h b/src/core/linux/SDL_evdev_kbd_default_keymap.h index db767cb1a45fc..790dac9b0cd2f 100644 --- a/src/core/linux/SDL_evdev_kbd_default_keymap.h +++ b/src/core/linux/SDL_evdev_kbd_default_keymap.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index 5f67ffb049ab6..af1689607998a 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_fcitx.h b/src/core/linux/SDL_fcitx.h index 2d029a1fff5f1..44ee053309f68 100644 --- a/src/core/linux/SDL_fcitx.h +++ b/src/core/linux/SDL_fcitx.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index d1ed37b63d559..6313f537ce5c2 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_ibus.h b/src/core/linux/SDL_ibus.h index 560aa126370e1..377a9fc2bd36f 100644 --- a/src/core/linux/SDL_ibus.h +++ b/src/core/linux/SDL_ibus.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_ime.c b/src/core/linux/SDL_ime.c index 1b9394e8896c4..752c3ab9b8c2b 100644 --- a/src/core/linux/SDL_ime.c +++ b/src/core/linux/SDL_ime.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_ime.h b/src/core/linux/SDL_ime.h index 3b21b50290c92..f0ac778259afe 100644 --- a/src/core/linux/SDL_ime.h +++ b/src/core/linux/SDL_ime.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_sandbox.c b/src/core/linux/SDL_sandbox.c index f0e0cb79e9ead..413148fc7b93b 100644 --- a/src/core/linux/SDL_sandbox.c +++ b/src/core/linux/SDL_sandbox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/src/core/linux/SDL_sandbox.h b/src/core/linux/SDL_sandbox.h index 6824c1565cd10..8339c90b45ab6 100644 --- a/src/core/linux/SDL_sandbox.h +++ b/src/core/linux/SDL_sandbox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/src/core/linux/SDL_system_theme.c b/src/core/linux/SDL_system_theme.c index 3b6e44581f60c..20b2412261fee 100644 --- a/src/core/linux/SDL_system_theme.c +++ b/src/core/linux/SDL_system_theme.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_system_theme.h b/src/core/linux/SDL_system_theme.h index 8d521faaf6c55..396b3a76ef17f 100644 --- a/src/core/linux/SDL_system_theme.h +++ b/src/core/linux/SDL_system_theme.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_threadprio.c b/src/core/linux/SDL_threadprio.c index c5d28dc92085e..cc8d6e4771bea 100644 --- a/src/core/linux/SDL_threadprio.c +++ b/src/core/linux/SDL_threadprio.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index a2d5bb62f009c..aa12289efe72e 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h index 60bef169c35f8..b3972d675c6a2 100644 --- a/src/core/linux/SDL_udev.h +++ b/src/core/linux/SDL_udev.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/n3ds/SDL_n3ds.c b/src/core/n3ds/SDL_n3ds.c index 0c1d8b4b17504..46610d19b587d 100644 --- a/src/core/n3ds/SDL_n3ds.c +++ b/src/core/n3ds/SDL_n3ds.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/openbsd/SDL_wscons.h b/src/core/openbsd/SDL_wscons.h index e53e574238e8b..40e102d00552d 100644 --- a/src/core/openbsd/SDL_wscons.h +++ b/src/core/openbsd/SDL_wscons.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c index a92a0484c3d3b..6832cc83e8c3b 100644 --- a/src/core/openbsd/SDL_wscons_kbd.c +++ b/src/core/openbsd/SDL_wscons_kbd.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c index 88855e469443c..3d3de9557977a 100644 --- a/src/core/openbsd/SDL_wscons_mouse.c +++ b/src/core/openbsd/SDL_wscons_mouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/ps2/SDL_ps2.c b/src/core/ps2/SDL_ps2.c index 5149c90e48218..b0a6f549323c6 100644 --- a/src/core/ps2/SDL_ps2.c +++ b/src/core/ps2/SDL_ps2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/psp/SDL_psp.c b/src/core/psp/SDL_psp.c index d66ed88d3db29..2b47c5b10aa27 100644 --- a/src/core/psp/SDL_psp.c +++ b/src/core/psp/SDL_psp.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/unix/SDL_appid.c b/src/core/unix/SDL_appid.c index c7cddc5b9f79b..fd2f2dc35d812 100644 --- a/src/core/unix/SDL_appid.c +++ b/src/core/unix/SDL_appid.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/unix/SDL_appid.h b/src/core/unix/SDL_appid.h index d5acb009b4164..976788cb135b5 100644 --- a/src/core/unix/SDL_appid.h +++ b/src/core/unix/SDL_appid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer -Copyright (C) 1997-2023 Sam Lantinga +Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/unix/SDL_poll.c b/src/core/unix/SDL_poll.c index d4c6e2ab8d800..2ff460997d5fb 100644 --- a/src/core/unix/SDL_poll.c +++ b/src/core/unix/SDL_poll.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/unix/SDL_poll.h b/src/core/unix/SDL_poll.h index b3f261d1fa00c..eef1d64b27c96 100644 --- a/src/core/unix/SDL_poll.h +++ b/src/core/unix/SDL_poll.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_directx.h b/src/core/windows/SDL_directx.h index 06ff79784338a..6736d8d7bd2c0 100644 --- a/src/core/windows/SDL_directx.h +++ b/src/core/windows/SDL_directx.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_hid.c b/src/core/windows/SDL_hid.c index 541f6490faa2d..6cea5344e97b7 100644 --- a/src/core/windows/SDL_hid.c +++ b/src/core/windows/SDL_hid.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_hid.h b/src/core/windows/SDL_hid.h index c0bb56b298a24..4dbdd757765f4 100644 --- a/src/core/windows/SDL_hid.h +++ b/src/core/windows/SDL_hid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 97a22a47f1f39..2e956b4733284 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_immdevice.h b/src/core/windows/SDL_immdevice.h index 5ed0c5ddc8b64..3dcd45ebc2716 100644 --- a/src/core/windows/SDL_immdevice.h +++ b/src/core/windows/SDL_immdevice.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index 39f48f9d9c057..0e6b474e06e02 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 8928938342d3f..610449565515c 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_xinput.c b/src/core/windows/SDL_xinput.c index fe34b75fe148d..36c9d818685fe 100644 --- a/src/core/windows/SDL_xinput.c +++ b/src/core/windows/SDL_xinput.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/SDL_xinput.h b/src/core/windows/SDL_xinput.h index 1d01da3674d5a..4790fec21dae8 100644 --- a/src/core/windows/SDL_xinput.h +++ b/src/core/windows/SDL_xinput.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/pch.c b/src/core/windows/pch.c index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/core/windows/pch.c +++ b/src/core/windows/pch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/pch_cpp.cpp b/src/core/windows/pch_cpp.cpp index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/core/windows/pch_cpp.cpp +++ b/src/core/windows/pch_cpp.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/windows/version.rc b/src/core/windows/version.rc index 259a1f0d2a71e..84869e1c0fc3f 100644 --- a/src/core/windows/version.rc +++ b/src/core/windows/version.rc @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "SDL\0" VALUE "FileVersion", "3, 0, 0, 0\0" VALUE "InternalName", "SDL\0" - VALUE "LegalCopyright", "Copyright (C) 2023 Sam Lantinga\0" + VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0" VALUE "OriginalFilename", "SDL3.dll\0" VALUE "ProductName", "Simple DirectMedia Layer\0" VALUE "ProductVersion", "3, 0, 0, 0\0" diff --git a/src/core/winrt/SDL_winrtapp_common.cpp b/src/core/winrt/SDL_winrtapp_common.cpp index 5ccb9158e4ee5..c20f52420a2a8 100644 --- a/src/core/winrt/SDL_winrtapp_common.cpp +++ b/src/core/winrt/SDL_winrtapp_common.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/winrt/SDL_winrtapp_common.h b/src/core/winrt/SDL_winrtapp_common.h index 635fb916c13e1..83cfd776227dc 100644 --- a/src/core/winrt/SDL_winrtapp_common.h +++ b/src/core/winrt/SDL_winrtapp_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index 64572f33b2bb4..404fa73604a1b 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/winrt/SDL_winrtapp_direct3d.h b/src/core/winrt/SDL_winrtapp_direct3d.h index a8795ff09c88a..9fb21f3209774 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.h +++ b/src/core/winrt/SDL_winrtapp_direct3d.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/winrt/SDL_winrtapp_xaml.cpp b/src/core/winrt/SDL_winrtapp_xaml.cpp index 9998e0ea83cec..81a54515ded4d 100644 --- a/src/core/winrt/SDL_winrtapp_xaml.cpp +++ b/src/core/winrt/SDL_winrtapp_xaml.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/core/winrt/SDL_winrtapp_xaml.h b/src/core/winrt/SDL_winrtapp_xaml.h index 2d4de64644e1b..b321cc8320b84 100644 --- a/src/core/winrt/SDL_winrtapp_xaml.h +++ b/src/core/winrt/SDL_winrtapp_xaml.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index bed2a35122c32..2f0dc1e575cd0 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index c865aac715ff6..3900b6cacc018 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 1f0fd4b3901ea..579cdf4980b9a 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 451fadbd96e1b..52abfed6b9c11 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 5b3cb2d2025ed..04cb56bc7c107 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/SDL_dynapi_unsupported.h b/src/dynapi/SDL_dynapi_unsupported.h index 40c1feee166cc..5bad9e5a2948b 100644 --- a/src/dynapi/SDL_dynapi_unsupported.h +++ b/src/dynapi/SDL_dynapi_unsupported.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index 3c5f73cd92781..6f78afc52f3f6 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Simple DirectMedia Layer -# Copyright (C) 1997-2023 Sam Lantinga +# Copyright (C) 1997-2024 Sam Lantinga # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_clipboardevents.c b/src/events/SDL_clipboardevents.c index bc9b07e6edf2b..0c2f20ac598d0 100644 --- a/src/events/SDL_clipboardevents.c +++ b/src/events/SDL_clipboardevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_clipboardevents_c.h b/src/events/SDL_clipboardevents_c.h index ce74e3cbdb1a1..557bd0d1a23bd 100644 --- a/src/events/SDL_clipboardevents_c.h +++ b/src/events/SDL_clipboardevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index d7b620a56a7a2..14c29f308e398 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_displayevents_c.h b/src/events/SDL_displayevents_c.h index ac2094739033b..c93d9ffa15e1e 100644 --- a/src/events/SDL_displayevents_c.h +++ b/src/events/SDL_displayevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index b029bd2d5c7d6..610652c256187 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_dropevents_c.h b/src/events/SDL_dropevents_c.h index f2396d5d30c0a..4379d68c2fe1c 100644 --- a/src/events/SDL_dropevents_c.h +++ b/src/events/SDL_dropevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 0801db7d31342..2a346f03c49a9 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_events_c.h b/src/events/SDL_events_c.h index 8c6310cd25b27..181583d71d07f 100644 --- a/src/events/SDL_events_c.h +++ b/src/events/SDL_events_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index f01b90a08cec2..aba50237ffa4c 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_keyboard_c.h b/src/events/SDL_keyboard_c.h index b8e76df68f190..98459b1ddf924 100644 --- a/src/events/SDL_keyboard_c.h +++ b/src/events/SDL_keyboard_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_keysym_to_scancode.c b/src/events/SDL_keysym_to_scancode.c index a14cb60b71f55..08e9809424846 100644 --- a/src/events/SDL_keysym_to_scancode.c +++ b/src/events/SDL_keysym_to_scancode.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_keysym_to_scancode_c.h b/src/events/SDL_keysym_to_scancode_c.h index 6e9e79e7985a6..91611a5d1593d 100644 --- a/src/events/SDL_keysym_to_scancode_c.h +++ b/src/events/SDL_keysym_to_scancode_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 57357ad938cc1..2f14cacf4111d 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index cd08f1640b0ed..e024534fa353d 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index b77a92b5f83c3..a4e9d30434b92 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h index 255ec0516ee5a..fef9c529f442e 100644 --- a/src/events/SDL_pen_c.h +++ b/src/events/SDL_pen_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index d103c313fccc4..e4928d3797115 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_scancode_tables.c b/src/events/SDL_scancode_tables.c index 78c6304c587f4..c09d9797e2892 100644 --- a/src/events/SDL_scancode_tables.c +++ b/src/events/SDL_scancode_tables.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_scancode_tables_c.h b/src/events/SDL_scancode_tables_c.h index 7a39e8bc68154..655f627cbf2f5 100644 --- a/src/events/SDL_scancode_tables_c.h +++ b/src/events/SDL_scancode_tables_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 2a38293fe0094..071fdff472799 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_touch_c.h b/src/events/SDL_touch_c.h index 34d7e290b618a..dda6adc14de5b 100644 --- a/src/events/SDL_touch_c.h +++ b/src/events/SDL_touch_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 268aff882cb66..9a184bc8541f1 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/SDL_windowevents_c.h b/src/events/SDL_windowevents_c.h index 4c81281e76545..93e9509344b1c 100644 --- a/src/events/SDL_windowevents_c.h +++ b/src/events/SDL_windowevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/blank_cursor.h b/src/events/blank_cursor.h index 95899f715c459..fd84744cc4204 100644 --- a/src/events/blank_cursor.h +++ b/src/events/blank_cursor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/default_cursor.h b/src/events/default_cursor.h index 10692b72e8df2..4e30aff2a960e 100644 --- a/src/events/default_cursor.h +++ b/src/events/default_cursor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/scancodes_ascii.h b/src/events/scancodes_ascii.h index 9a88e8f29f5a8..ee49ab8813532 100644 --- a/src/events/scancodes_ascii.h +++ b/src/events/scancodes_ascii.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/scancodes_darwin.h b/src/events/scancodes_darwin.h index c6ae005b1f632..c38ed60ef1a7e 100644 --- a/src/events/scancodes_darwin.h +++ b/src/events/scancodes_darwin.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/scancodes_linux.h b/src/events/scancodes_linux.h index d9c478c9317a4..a9869a8d009b1 100644 --- a/src/events/scancodes_linux.h +++ b/src/events/scancodes_linux.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/scancodes_windows.h b/src/events/scancodes_windows.h index a41d69b2190c3..75635e6d76a42 100644 --- a/src/events/scancodes_windows.h +++ b/src/events/scancodes_windows.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/events/scancodes_xfree86.h b/src/events/scancodes_xfree86.h index e297eb53d1751..f3001d8325bcf 100644 --- a/src/events/scancodes_xfree86.h +++ b/src/events/scancodes_xfree86.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 371926794307d..dde12ded3df4f 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.h b/src/file/cocoa/SDL_rwopsbundlesupport.h index 17bc86b4f22db..c57ce4529306f 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.h +++ b/src/file/cocoa/SDL_rwopsbundlesupport.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.m b/src/file/cocoa/SDL_rwopsbundlesupport.m index 9ce5f0e6c1076..a6f763b41c9e8 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.m +++ b/src/file/cocoa/SDL_rwopsbundlesupport.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/file/n3ds/SDL_rwopsromfs.c b/src/file/n3ds/SDL_rwopsromfs.c index 92d9a8141fb0a..afa9e53c4fde9 100644 --- a/src/file/n3ds/SDL_rwopsromfs.c +++ b/src/file/n3ds/SDL_rwopsromfs.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/file/n3ds/SDL_rwopsromfs.h b/src/file/n3ds/SDL_rwopsromfs.h index 99bc0b447c46b..572a71441040d 100644 --- a/src/file/n3ds/SDL_rwopsromfs.h +++ b/src/file/n3ds/SDL_rwopsromfs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/android/SDL_sysfilesystem.c b/src/filesystem/android/SDL_sysfilesystem.c index 0fc466ffb329b..4d5fb5deca031 100644 --- a/src/filesystem/android/SDL_sysfilesystem.c +++ b/src/filesystem/android/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index eb5ee9b859371..71f674fae3f94 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/dummy/SDL_sysfilesystem.c b/src/filesystem/dummy/SDL_sysfilesystem.c index 197284cfce9fc..442728223e022 100644 --- a/src/filesystem/dummy/SDL_sysfilesystem.c +++ b/src/filesystem/dummy/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c index b22ee4ce5115d..69069e937fd4b 100644 --- a/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp index 6794a31fea28d..1fb0ff9a5c4e6 100644 --- a/src/filesystem/gdk/SDL_sysfilesystem.cpp +++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index d28baacef19b4..893e24a6d28a5 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c index a4bea05c62409..689a35bbbb72f 100644 --- a/src/filesystem/n3ds/SDL_sysfilesystem.c +++ b/src/filesystem/n3ds/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/ps2/SDL_sysfilesystem.c b/src/filesystem/ps2/SDL_sysfilesystem.c index e81460a245a00..d5b2632b2950c 100644 --- a/src/filesystem/ps2/SDL_sysfilesystem.c +++ b/src/filesystem/ps2/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/psp/SDL_sysfilesystem.c b/src/filesystem/psp/SDL_sysfilesystem.c index f262af55fb0d4..5386cb53a49ee 100644 --- a/src/filesystem/psp/SDL_sysfilesystem.c +++ b/src/filesystem/psp/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c index 83b676de2b85d..bbbc144b001dd 100644 --- a/src/filesystem/riscos/SDL_sysfilesystem.c +++ b/src/filesystem/riscos/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index d288e9d757e6d..91baf4373d1e5 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c index 83b84254406aa..11d320ee4bb03 100644 --- a/src/filesystem/vita/SDL_sysfilesystem.c +++ b/src/filesystem/vita/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c index 160d330879861..f9e2361610a94 100644 --- a/src/filesystem/windows/SDL_sysfilesystem.c +++ b/src/filesystem/windows/SDL_sysfilesystem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index 6cefbc049c48f..d5b7c020f9ee5 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index 60dd37d34c087..3fbac01e57ad3 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/SDL_haptic_c.h b/src/haptic/SDL_haptic_c.h index 744dfb7ed71db..06ef1be0924b7 100644 --- a/src/haptic/SDL_haptic_c.h +++ b/src/haptic/SDL_haptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/SDL_syshaptic.h b/src/haptic/SDL_syshaptic.h index 58fc55b9f1521..71f7ed55d5784 100644 --- a/src/haptic/SDL_syshaptic.h +++ b/src/haptic/SDL_syshaptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index 8a68cf7956765..bf8404c999bff 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/android/SDL_syshaptic_c.h b/src/haptic/android/SDL_syshaptic_c.h index 001c0da03e0af..f07f4e1ded8c4 100644 --- a/src/haptic/android/SDL_syshaptic_c.h +++ b/src/haptic/android/SDL_syshaptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index 44a85b3835170..a00cb9d61be57 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/darwin/SDL_syshaptic_c.h b/src/haptic/darwin/SDL_syshaptic_c.h index 896a71b2a1efc..67bc86358de28 100644 --- a/src/haptic/darwin/SDL_syshaptic_c.h +++ b/src/haptic/darwin/SDL_syshaptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/dummy/SDL_syshaptic.c b/src/haptic/dummy/SDL_syshaptic.c index 480195fc6d9b6..419f7bad6b7e8 100644 --- a/src/haptic/dummy/SDL_syshaptic.c +++ b/src/haptic/dummy/SDL_syshaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 0649ce37c9eae..c4e6c1830ff31 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_dinputhaptic.c b/src/haptic/windows/SDL_dinputhaptic.c index 45214ddcdeba9..04f4a48cc6557 100644 --- a/src/haptic/windows/SDL_dinputhaptic.c +++ b/src/haptic/windows/SDL_dinputhaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_dinputhaptic_c.h b/src/haptic/windows/SDL_dinputhaptic_c.h index 89dc4c11d87b0..0f87afbc4e096 100644 --- a/src/haptic/windows/SDL_dinputhaptic_c.h +++ b/src/haptic/windows/SDL_dinputhaptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c index fae8542b4b3ba..b7dbae3fdf104 100644 --- a/src/haptic/windows/SDL_windowshaptic.c +++ b/src/haptic/windows/SDL_windowshaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_windowshaptic_c.h b/src/haptic/windows/SDL_windowshaptic_c.h index 9219dcf01a7cc..a84430c30ae31 100644 --- a/src/haptic/windows/SDL_windowshaptic_c.h +++ b/src/haptic/windows/SDL_windowshaptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index b307b31cf1170..6e8de2a0f6959 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/haptic/windows/SDL_xinputhaptic_c.h b/src/haptic/windows/SDL_xinputhaptic_c.h index 47a64807db700..b61fd5c9cc1a0 100644 --- a/src/haptic/windows/SDL_xinputhaptic_c.h +++ b/src/haptic/windows/SDL_xinputhaptic_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index 9d168ade4c9b8..97a60c4280ba4 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_android.h b/src/hidapi/SDL_hidapi_android.h index 4fe554c7e57b8..58d80c301613f 100644 --- a/src/hidapi/SDL_hidapi_android.h +++ b/src/hidapi/SDL_hidapi_android.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_c.h b/src/hidapi/SDL_hidapi_c.h index 59e4f3e8123bb..62148cdc360f8 100644 --- a/src/hidapi/SDL_hidapi_c.h +++ b/src/hidapi/SDL_hidapi_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_ios.h b/src/hidapi/SDL_hidapi_ios.h index c921fde332b16..4b61150ac11c4 100644 --- a/src/hidapi/SDL_hidapi_ios.h +++ b/src/hidapi/SDL_hidapi_ios.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_libusb.h b/src/hidapi/SDL_hidapi_libusb.h index 456a4bf16c08e..9f62be520bfc4 100644 --- a/src/hidapi/SDL_hidapi_libusb.h +++ b/src/hidapi/SDL_hidapi_libusb.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_linux.h b/src/hidapi/SDL_hidapi_linux.h index 7face2418a6fb..388af3232bd76 100644 --- a/src/hidapi/SDL_hidapi_linux.h +++ b/src/hidapi/SDL_hidapi_linux.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_mac.h b/src/hidapi/SDL_hidapi_mac.h index d7c0f50044a40..423a9469e4737 100644 --- a/src/hidapi/SDL_hidapi_mac.h +++ b/src/hidapi/SDL_hidapi_mac.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_netbsd.h b/src/hidapi/SDL_hidapi_netbsd.h index 3ca6803b2b691..fa5cf9724fc6f 100644 --- a/src/hidapi/SDL_hidapi_netbsd.h +++ b/src/hidapi/SDL_hidapi_netbsd.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_steamxbox.h b/src/hidapi/SDL_hidapi_steamxbox.h index 0570acb38d87f..cab4ef586a98f 100644 --- a/src/hidapi/SDL_hidapi_steamxbox.h +++ b/src/hidapi/SDL_hidapi_steamxbox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/SDL_hidapi_windows.h b/src/hidapi/SDL_hidapi_windows.h index 09604c67d68ef..f96bbd539a71f 100644 --- a/src/hidapi/SDL_hidapi_windows.h +++ b/src/hidapi/SDL_hidapi_windows.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/hidapi/libusb/hidapi_thread_sdl.h b/src/hidapi/libusb/hidapi_thread_sdl.h index f96eacf8c9289..78b7e09eb5d83 100644 --- a/src/hidapi/libusb/hidapi_thread_sdl.h +++ b/src/hidapi/libusb/hidapi_thread_sdl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index e8fe5fdf85edf..acadfaa99d606 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_gamepad_c.h b/src/joystick/SDL_gamepad_c.h index 113be066a34fe..0c0614098fe24 100644 --- a/src/joystick/SDL_gamepad_c.h +++ b/src/joystick/SDL_gamepad_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 886d7a93416c2..a554c9cd151b9 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 1d71653b21726..e39fdc5ef126c 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 10dd13696a7b6..95ab4f71e1798 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_steam_virtual_gamepad.c b/src/joystick/SDL_steam_virtual_gamepad.c index 2d56e08a12207..b8b2038adb19c 100644 --- a/src/joystick/SDL_steam_virtual_gamepad.c +++ b/src/joystick/SDL_steam_virtual_gamepad.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_steam_virtual_gamepad.h b/src/joystick/SDL_steam_virtual_gamepad.h index fb12e7730f0c7..d683327181015 100644 --- a/src/joystick/SDL_steam_virtual_gamepad.h +++ b/src/joystick/SDL_steam_virtual_gamepad.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index dfab89928820a..ae50d8f6fef2d 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 9eeed2384ac48..cacb47b9e5d4f 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/android/SDL_sysjoystick_c.h b/src/joystick/android/SDL_sysjoystick_c.h index 84106dc696f16..28dd6b3bed7c9 100644 --- a/src/joystick/android/SDL_sysjoystick_c.h +++ b/src/joystick/android/SDL_sysjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 8ce2ac3d66b60..3aa0c82a609e3 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index 0b32885886271..0dae2ac644047 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index 27276af08bfa7..dcc2980c5fdd6 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 74a588be415c0..036fdd41bbb54 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/darwin/SDL_iokitjoystick_c.h b/src/joystick/darwin/SDL_iokitjoystick_c.h index 630d4aba47cd8..756e9b7ab3d9e 100644 --- a/src/joystick/darwin/SDL_iokitjoystick_c.h +++ b/src/joystick/darwin/SDL_iokitjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 687175f9f9864..125e3c03ffa3c 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index e98f2213f7d4e..3a6cd9d06fe74 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/emscripten/SDL_sysjoystick_c.h b/src/joystick/emscripten/SDL_sysjoystick_c.h index 33eb96e1ccf9c..9ba6b35e23b2c 100644 --- a/src/joystick/emscripten/SDL_sysjoystick_c.h +++ b/src/joystick/emscripten/SDL_sysjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index e107c717902d1..9110b0adca5c3 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index 57fb7556b1b9a..3d090242e0a8e 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 8ca952cf237f0..ee90fdf5918ca 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 27476ab34586a..ed408a2f52c9c 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_nintendo.h b/src/joystick/hidapi/SDL_hidapi_nintendo.h index daa1e92ab4b1d..e12c61aaa5ac6 100644 --- a/src/joystick/hidapi/SDL_hidapi_nintendo.h +++ b/src/joystick/hidapi/SDL_hidapi_nintendo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index aee477df601f6..8992f0d8d9809 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 550da29085796..91ce0f5c8a715 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index add062d442f99..7ce112c94f7bd 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index 8a246861f26d0..5d270fc1983ce 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.h b/src/joystick/hidapi/SDL_hidapi_rumble.h index 8e30847e09082..0a1ccb9dfba1b 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.h +++ b/src/joystick/hidapi/SDL_hidapi_rumble.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 5d38727f81392..0128f698d34cf 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 50d2dd1dbe7c6..f55664bcd8cd5 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index bbc5f70227e55..2e09abee8493a 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index cf931b444c6ca..c0f8a64b2c688 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index bd9b26e3bee4f..065c3b97d101f 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index bcccbc7dbb9f1..d0097fb7a1562 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index b7e69b7c94803..db16c37601c87 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 096bff1ed6d4c..a7a6508fdc95b 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index ce06c11722673..a3c6872b0ac46 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 74f0b749c6f4d..9cb1702194665 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 6d55e9cc419dd..742bbf4235232 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/linux/SDL_sysjoystick_c.h b/src/joystick/linux/SDL_sysjoystick_c.h index e737332d6af3d..98bee2042583d 100644 --- a/src/joystick/linux/SDL_sysjoystick_c.h +++ b/src/joystick/linux/SDL_sysjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index 6460235ea6874..79a666f6b7ead 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/ps2/SDL_sysjoystick.c b/src/joystick/ps2/SDL_sysjoystick.c index 46d3a9a4e8d90..5fc5df3278905 100644 --- a/src/joystick/ps2/SDL_sysjoystick.c +++ b/src/joystick/ps2/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index eb2b987841b9f..f66abfaa7d38f 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/steam/SDL_steamcontroller.c b/src/joystick/steam/SDL_steamcontroller.c index 5ec4ad7bc99c9..d2bd3eccf2b3f 100644 --- a/src/joystick/steam/SDL_steamcontroller.c +++ b/src/joystick/steam/SDL_steamcontroller.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/steam/SDL_steamcontroller.h b/src/joystick/steam/SDL_steamcontroller.h index f3755af04e3ff..b53016284aba5 100644 --- a/src/joystick/steam/SDL_steamcontroller.h +++ b/src/joystick/steam/SDL_steamcontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 2765ebcc2e20d..0db98ac9cf945 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index b15177ec30558..d7859bf3a3b9c 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/virtual/SDL_virtualjoystick_c.h b/src/joystick/virtual/SDL_virtualjoystick_c.h index b672b8623dc7c..2f16cc6c1a66f 100644 --- a/src/joystick/virtual/SDL_virtualjoystick_c.h +++ b/src/joystick/virtual/SDL_virtualjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c index b1acf232745e0..4eb9edfd1cd2a 100644 --- a/src/joystick/vita/SDL_sysjoystick.c +++ b/src/joystick/vita/SDL_sysjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index bc79a97736deb..63c31a3c77d98 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_dinputjoystick_c.h b/src/joystick/windows/SDL_dinputjoystick_c.h index 95cf5df7324fe..d864f737d0329 100644 --- a/src/joystick/windows/SDL_dinputjoystick_c.h +++ b/src/joystick/windows/SDL_dinputjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index b5f6113f2053c..cd0e16ca36c68 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 2023 Sam Lantinga + Copyright (C) 2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_rawinputjoystick_c.h b/src/joystick/windows/SDL_rawinputjoystick_c.h index 534ae08824cfb..d4f9e79fb6a4a 100644 --- a/src/joystick/windows/SDL_rawinputjoystick_c.h +++ b/src/joystick/windows/SDL_rawinputjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index 3365f29ac09d9..c79cf8e720e61 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 1476d899a5be9..11aa16a97de54 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_windowsjoystick_c.h b/src/joystick/windows/SDL_windowsjoystick_c.h index 50c0786bccc1d..cea67f919d42b 100644 --- a/src/joystick/windows/SDL_windowsjoystick_c.h +++ b/src/joystick/windows/SDL_windowsjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 0e00de57985a0..42a5f41ef39a8 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/joystick/windows/SDL_xinputjoystick_c.h b/src/joystick/windows/SDL_xinputjoystick_c.h index 88b49c586989d..180086388d6f8 100644 --- a/src/joystick/windows/SDL_xinputjoystick_c.h +++ b/src/joystick/windows/SDL_xinputjoystick_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/libm/math_libm.h b/src/libm/math_libm.h index 510a5c2421e86..1313a075df326 100644 --- a/src/libm/math_libm.h +++ b/src/libm/math_libm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/loadso/dlopen/SDL_sysloadso.c b/src/loadso/dlopen/SDL_sysloadso.c index a8f8849d9aea3..b7a37a4b25198 100644 --- a/src/loadso/dlopen/SDL_sysloadso.c +++ b/src/loadso/dlopen/SDL_sysloadso.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/loadso/dummy/SDL_sysloadso.c b/src/loadso/dummy/SDL_sysloadso.c index ba18a7a2b3eb9..9a2f524b7b28c 100644 --- a/src/loadso/dummy/SDL_sysloadso.c +++ b/src/loadso/dummy/SDL_sysloadso.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/loadso/windows/SDL_sysloadso.c b/src/loadso/windows/SDL_sysloadso.c index 5eebf216890c8..92a61beb00864 100644 --- a/src/loadso/windows/SDL_sysloadso.c +++ b/src/loadso/windows/SDL_sysloadso.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/SDL_locale.c b/src/locale/SDL_locale.c index aef5d6ffc9093..5ad0312757a18 100644 --- a/src/locale/SDL_locale.c +++ b/src/locale/SDL_locale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/SDL_syslocale.h b/src/locale/SDL_syslocale.h index 52851e53c6175..0bcc0ad94195e 100644 --- a/src/locale/SDL_syslocale.h +++ b/src/locale/SDL_syslocale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/android/SDL_syslocale.c b/src/locale/android/SDL_syslocale.c index 99b3bcdf3fa06..03a687486099b 100644 --- a/src/locale/android/SDL_syslocale.c +++ b/src/locale/android/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/dummy/SDL_syslocale.c b/src/locale/dummy/SDL_syslocale.c index 742d5b0d9d507..769dcc8fd1a09 100644 --- a/src/locale/dummy/SDL_syslocale.c +++ b/src/locale/dummy/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/emscripten/SDL_syslocale.c b/src/locale/emscripten/SDL_syslocale.c index c22681ff3149c..fe06151a41e6d 100644 --- a/src/locale/emscripten/SDL_syslocale.c +++ b/src/locale/emscripten/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/haiku/SDL_syslocale.cc b/src/locale/haiku/SDL_syslocale.cc index 08932e1a26970..5e5da395d8d39 100644 --- a/src/locale/haiku/SDL_syslocale.cc +++ b/src/locale/haiku/SDL_syslocale.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/macos/SDL_syslocale.m b/src/locale/macos/SDL_syslocale.m index 2aece9e294103..a9d1af3c2bde1 100644 --- a/src/locale/macos/SDL_syslocale.m +++ b/src/locale/macos/SDL_syslocale.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/n3ds/SDL_syslocale.c b/src/locale/n3ds/SDL_syslocale.c index 1d389c6495e61..02ba03a4e5509 100644 --- a/src/locale/n3ds/SDL_syslocale.c +++ b/src/locale/n3ds/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/unix/SDL_syslocale.c b/src/locale/unix/SDL_syslocale.c index f420cdf6d9f16..a03849dd4b812 100644 --- a/src/locale/unix/SDL_syslocale.c +++ b/src/locale/unix/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/vita/SDL_syslocale.c b/src/locale/vita/SDL_syslocale.c index 3a8c1f226e5fb..42bdcd2c9dd29 100644 --- a/src/locale/vita/SDL_syslocale.c +++ b/src/locale/vita/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/windows/SDL_syslocale.c b/src/locale/windows/SDL_syslocale.c index e26f129dcd5d2..ec8d44ad13b07 100644 --- a/src/locale/windows/SDL_syslocale.c +++ b/src/locale/windows/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/locale/winrt/SDL_syslocale.c b/src/locale/winrt/SDL_syslocale.c index f1fe7d098aa7d..8e0550d57eade 100644 --- a/src/locale/winrt/SDL_syslocale.c +++ b/src/locale/winrt/SDL_syslocale.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index 0e7fb8d2895f3..a89ffb915fdd4 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/main/SDL_main_callbacks.h b/src/main/SDL_main_callbacks.h index 229fec7766a02..5a906cfc8e65b 100644 --- a/src/main/SDL_main_callbacks.h +++ b/src/main/SDL_main_callbacks.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/main/emscripten/SDL_sysmain_callbacks.c b/src/main/emscripten/SDL_sysmain_callbacks.c index 151ccf49a2cad..cb9fbb4cefaff 100644 --- a/src/main/emscripten/SDL_sysmain_callbacks.c +++ b/src/main/emscripten/SDL_sysmain_callbacks.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index fa18e80002c5a..8adbf6c4afa05 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/main/ios/SDL_sysmain_callbacks.m b/src/main/ios/SDL_sysmain_callbacks.m index 8cffd9c11795b..09bc9932f6de0 100644 --- a/src/main/ios/SDL_sysmain_callbacks.m +++ b/src/main/ios/SDL_sysmain_callbacks.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/SDL_sysurl.h b/src/misc/SDL_sysurl.h index ca9bcc49d649c..0eca8ac19fc7a 100644 --- a/src/misc/SDL_sysurl.h +++ b/src/misc/SDL_sysurl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/SDL_url.c b/src/misc/SDL_url.c index aa58b536e4dab..34016bf96f5da 100644 --- a/src/misc/SDL_url.c +++ b/src/misc/SDL_url.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/android/SDL_sysurl.c b/src/misc/android/SDL_sysurl.c index 05b741fbd7256..07067de1015b5 100644 --- a/src/misc/android/SDL_sysurl.c +++ b/src/misc/android/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/dummy/SDL_sysurl.c b/src/misc/dummy/SDL_sysurl.c index 7e60e49c88f46..358b3e6d8c83d 100644 --- a/src/misc/dummy/SDL_sysurl.c +++ b/src/misc/dummy/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/emscripten/SDL_sysurl.c b/src/misc/emscripten/SDL_sysurl.c index 8926a929cfcf5..023bd15b23b7b 100644 --- a/src/misc/emscripten/SDL_sysurl.c +++ b/src/misc/emscripten/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/haiku/SDL_sysurl.cc b/src/misc/haiku/SDL_sysurl.cc index cf619ef09f6c8..5c6dd00c8ee7c 100644 --- a/src/misc/haiku/SDL_sysurl.cc +++ b/src/misc/haiku/SDL_sysurl.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/ios/SDL_sysurl.m b/src/misc/ios/SDL_sysurl.m index 7db7f48db0dad..719e0b2cb8d2c 100644 --- a/src/misc/ios/SDL_sysurl.m +++ b/src/misc/ios/SDL_sysurl.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/macos/SDL_sysurl.m b/src/misc/macos/SDL_sysurl.m index b372cec40dcea..2eff382a0f00c 100644 --- a/src/misc/macos/SDL_sysurl.m +++ b/src/misc/macos/SDL_sysurl.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/riscos/SDL_sysurl.c b/src/misc/riscos/SDL_sysurl.c index 67206e371c135..f9285b76fe481 100644 --- a/src/misc/riscos/SDL_sysurl.c +++ b/src/misc/riscos/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/unix/SDL_sysurl.c b/src/misc/unix/SDL_sysurl.c index 709a58422a94e..b9c910e07a740 100644 --- a/src/misc/unix/SDL_sysurl.c +++ b/src/misc/unix/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/vita/SDL_sysurl.c b/src/misc/vita/SDL_sysurl.c index ac3c449bb0e80..5e0cb1d3c6b70 100644 --- a/src/misc/vita/SDL_sysurl.c +++ b/src/misc/vita/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/windows/SDL_sysurl.c b/src/misc/windows/SDL_sysurl.c index 38bf896f708b4..11d720cfbd8fb 100644 --- a/src/misc/windows/SDL_sysurl.c +++ b/src/misc/windows/SDL_sysurl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/misc/winrt/SDL_sysurl.cpp b/src/misc/winrt/SDL_sysurl.cpp index 23bf289d4cc1f..cd6ae2f5d870b 100644 --- a/src/misc/winrt/SDL_sysurl.cpp +++ b/src/misc/winrt/SDL_sysurl.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/SDL_power.c b/src/power/SDL_power.c index 61921703b24fd..af1e5bfbd1e8e 100644 --- a/src/power/SDL_power.c +++ b/src/power/SDL_power.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/SDL_syspower.h b/src/power/SDL_syspower.h index 3c79f0de79dcc..31328162b4e6f 100644 --- a/src/power/SDL_syspower.h +++ b/src/power/SDL_syspower.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/android/SDL_syspower.c b/src/power/android/SDL_syspower.c index 1e3c2488050c1..0cae9d33cad4c 100644 --- a/src/power/android/SDL_syspower.c +++ b/src/power/android/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/emscripten/SDL_syspower.c b/src/power/emscripten/SDL_syspower.c index c316a9e4f832f..05dec175b959e 100644 --- a/src/power/emscripten/SDL_syspower.c +++ b/src/power/emscripten/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/haiku/SDL_syspower.c b/src/power/haiku/SDL_syspower.c index 6298ee5813f23..14bf6423c2192 100644 --- a/src/power/haiku/SDL_syspower.c +++ b/src/power/haiku/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/linux/SDL_syspower.c b/src/power/linux/SDL_syspower.c index 410dc6b002809..e4a17a08fd6ee 100644 --- a/src/power/linux/SDL_syspower.c +++ b/src/power/linux/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/macos/SDL_syspower.c b/src/power/macos/SDL_syspower.c index 7c472e3348c65..13ea6f36b45c2 100644 --- a/src/power/macos/SDL_syspower.c +++ b/src/power/macos/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/n3ds/SDL_syspower.c b/src/power/n3ds/SDL_syspower.c index 511f1f987a9ae..57a745b3df2be 100644 --- a/src/power/n3ds/SDL_syspower.c +++ b/src/power/n3ds/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/psp/SDL_syspower.c b/src/power/psp/SDL_syspower.c index db670a371614e..96d379267629a 100644 --- a/src/power/psp/SDL_syspower.c +++ b/src/power/psp/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/uikit/SDL_syspower.h b/src/power/uikit/SDL_syspower.h index 40755ae6c2030..8365c75b27257 100644 --- a/src/power/uikit/SDL_syspower.h +++ b/src/power/uikit/SDL_syspower.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/uikit/SDL_syspower.m b/src/power/uikit/SDL_syspower.m index f1d29d393dd74..3049c1e0c14db 100644 --- a/src/power/uikit/SDL_syspower.m +++ b/src/power/uikit/SDL_syspower.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/vita/SDL_syspower.c b/src/power/vita/SDL_syspower.c index 3f1d9a0cadc26..5e216abe031ca 100644 --- a/src/power/vita/SDL_syspower.c +++ b/src/power/vita/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/windows/SDL_syspower.c b/src/power/windows/SDL_syspower.c index 7f978c591f212..4525c86762dd4 100644 --- a/src/power/windows/SDL_syspower.c +++ b/src/power/windows/SDL_syspower.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/power/winrt/SDL_syspower.cpp b/src/power/winrt/SDL_syspower.cpp index d9a423a543ab2..4df727976a3e3 100644 --- a/src/power/winrt/SDL_syspower.cpp +++ b/src/power/winrt/SDL_syspower.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_d3dmath.c b/src/render/SDL_d3dmath.c index 1d68320be58b9..7b50487c096a8 100644 --- a/src/render/SDL_d3dmath.c +++ b/src/render/SDL_d3dmath.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_d3dmath.h b/src/render/SDL_d3dmath.h index 6ced717b3821e..95b52601a2abd 100644 --- a/src/render/SDL_d3dmath.h +++ b/src/render/SDL_d3dmath.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 7344d95a6e34a..45ed877be0c6e 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_render_unsupported.c b/src/render/SDL_render_unsupported.c index 89742d4b6ab86..214b5fff6bb9d 100644 --- a/src/render/SDL_render_unsupported.c +++ b/src/render/SDL_render_unsupported.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 51d58c384349d..b1f82cb8534a7 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index 5761bcc580698..0257c5d654390 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/SDL_yuv_sw_c.h b/src/render/SDL_yuv_sw_c.h index 85d67f045a1ba..b3c0f5ef33eae 100644 --- a/src/render/SDL_yuv_sw_c.h +++ b/src/render/SDL_yuv_sw_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 2ab49bd29f188..1e15ae8f2c992 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d/SDL_shaders_d3d.c b/src/render/direct3d/SDL_shaders_d3d.c index c1d914f215688..a05d23daa60dc 100644 --- a/src/render/direct3d/SDL_shaders_d3d.c +++ b/src/render/direct3d/SDL_shaders_d3d.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d/SDL_shaders_d3d.h b/src/render/direct3d/SDL_shaders_d3d.h index 922afdc02e4f3..13ecf6fc84659 100644 --- a/src/render/direct3d/SDL_shaders_d3d.h +++ b/src/render/direct3d/SDL_shaders_d3d.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 1c14a515079db..05052be568754 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d11/SDL_render_winrt.cpp b/src/render/direct3d11/SDL_render_winrt.cpp index 34992d99cd450..6c5bec8e64c32 100644 --- a/src/render/direct3d11/SDL_render_winrt.cpp +++ b/src/render/direct3d11/SDL_render_winrt.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d11/SDL_render_winrt.h b/src/render/direct3d11/SDL_render_winrt.h index ce1757a9d3ff9..cee20b5189faf 100644 --- a/src/render/direct3d11/SDL_render_winrt.h +++ b/src/render/direct3d11/SDL_render_winrt.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d11/SDL_shaders_d3d11.c b/src/render/direct3d11/SDL_shaders_d3d11.c index 3019751b03ed8..66f7c8ce81d17 100644 --- a/src/render/direct3d11/SDL_shaders_d3d11.c +++ b/src/render/direct3d11/SDL_shaders_d3d11.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d11/SDL_shaders_d3d11.h b/src/render/direct3d11/SDL_shaders_d3d11.h index 7f49498d375e8..14cbe0e50a57b 100644 --- a/src/render/direct3d11/SDL_shaders_d3d11.h +++ b/src/render/direct3d11/SDL_shaders_d3d11.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 24393fb4da8c8..4c590eac7562c 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_render_d3d12_xbox.cpp b/src/render/direct3d12/SDL_render_d3d12_xbox.cpp index 48a6df991c803..a7fbef19212e9 100644 --- a/src/render/direct3d12/SDL_render_d3d12_xbox.cpp +++ b/src/render/direct3d12/SDL_render_d3d12_xbox.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_render_d3d12_xbox.h b/src/render/direct3d12/SDL_render_d3d12_xbox.h index fd725d9f42365..4f5ee1fc0dfec 100644 --- a/src/render/direct3d12/SDL_render_d3d12_xbox.h +++ b/src/render/direct3d12/SDL_render_d3d12_xbox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_shaders_d3d12.c b/src/render/direct3d12/SDL_shaders_d3d12.c index 36bedf52a055f..ea5ef31944f71 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12.c +++ b/src/render/direct3d12/SDL_shaders_d3d12.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_shaders_d3d12.h b/src/render/direct3d12/SDL_shaders_d3d12.h index 76861ada69500..e672f0d2f9b29 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12.h +++ b/src/render/direct3d12/SDL_shaders_d3d12.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp b/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp index 6dcb07ba5a2bb..90339bf234f5e 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp +++ b/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp b/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp index bfcfc471aff79..beeefabbd6e62 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp +++ b/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 3d3e0586e38f9..2b631540b2ae9 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengl/SDL_glfuncs.h b/src/render/opengl/SDL_glfuncs.h index f32b368c38cd7..3c0f098d5480f 100644 --- a/src/render/opengl/SDL_glfuncs.h +++ b/src/render/opengl/SDL_glfuncs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 4d04fa7c816b3..d033130b9a0ae 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengl/SDL_shaders_gl.c b/src/render/opengl/SDL_shaders_gl.c index 2416038a08ffb..3431e32ebc9e1 100644 --- a/src/render/opengl/SDL_shaders_gl.c +++ b/src/render/opengl/SDL_shaders_gl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengl/SDL_shaders_gl.h b/src/render/opengl/SDL_shaders_gl.h index 22022501ba147..c0a4c424c6297 100644 --- a/src/render/opengl/SDL_shaders_gl.h +++ b/src/render/opengl/SDL_shaders_gl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengles2/SDL_gles2funcs.h b/src/render/opengles2/SDL_gles2funcs.h index 59910214531e7..125d64d8e3ff7 100644 --- a/src/render/opengles2/SDL_gles2funcs.h +++ b/src/render/opengles2/SDL_gles2funcs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 698ec57a486c0..bae60b7f97495 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c index 4acfdea3431d7..1502256a6beae 100644 --- a/src/render/opengles2/SDL_shaders_gles2.c +++ b/src/render/opengles2/SDL_shaders_gles2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h index ac3364809c001..b153d1dd06671 100644 --- a/src/render/opengles2/SDL_shaders_gles2.h +++ b/src/render/opengles2/SDL_shaders_gles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index dca67c364ee0d..1052ff4055ff3 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 6769238aee705..7b88642ef3422 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendfillrect.c b/src/render/software/SDL_blendfillrect.c index 73c456c1f0615..f5e3f2355ecc8 100644 --- a/src/render/software/SDL_blendfillrect.c +++ b/src/render/software/SDL_blendfillrect.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendfillrect.h b/src/render/software/SDL_blendfillrect.h index 65bf5235707fc..8ab67d2efd765 100644 --- a/src/render/software/SDL_blendfillrect.h +++ b/src/render/software/SDL_blendfillrect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendline.c b/src/render/software/SDL_blendline.c index 83280e44b6782..e52acd7a67be5 100644 --- a/src/render/software/SDL_blendline.c +++ b/src/render/software/SDL_blendline.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendline.h b/src/render/software/SDL_blendline.h index d694129b09e4c..ad079545b6ff4 100644 --- a/src/render/software/SDL_blendline.h +++ b/src/render/software/SDL_blendline.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendpoint.c b/src/render/software/SDL_blendpoint.c index 59b1fd6db3a54..16072c9ae5b23 100644 --- a/src/render/software/SDL_blendpoint.c +++ b/src/render/software/SDL_blendpoint.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_blendpoint.h b/src/render/software/SDL_blendpoint.h index 563e15dd90b34..7b4b679ba3f6d 100644 --- a/src/render/software/SDL_blendpoint.h +++ b/src/render/software/SDL_blendpoint.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_draw.h b/src/render/software/SDL_draw.h index b8f3fc6420199..155116182b430 100644 --- a/src/render/software/SDL_draw.h +++ b/src/render/software/SDL_draw.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_drawline.c b/src/render/software/SDL_drawline.c index bb7d6a3d403a1..c588e2e540000 100644 --- a/src/render/software/SDL_drawline.c +++ b/src/render/software/SDL_drawline.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_drawline.h b/src/render/software/SDL_drawline.h index 90599389821b9..1bbb827f1c37d 100644 --- a/src/render/software/SDL_drawline.h +++ b/src/render/software/SDL_drawline.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_drawpoint.c b/src/render/software/SDL_drawpoint.c index a9bd16cb96da8..6152c4dabddba 100644 --- a/src/render/software/SDL_drawpoint.c +++ b/src/render/software/SDL_drawpoint.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_drawpoint.h b/src/render/software/SDL_drawpoint.h index de6d59735031b..6766f9d9570b2 100644 --- a/src/render/software/SDL_drawpoint.h +++ b/src/render/software/SDL_drawpoint.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index bb2fe7558db04..95bc2f57ae9bc 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_render_sw_c.h b/src/render/software/SDL_render_sw_c.h index 3bdffa6537a38..fad327c0b4929 100644 --- a/src/render/software/SDL_render_sw_c.h +++ b/src/render/software/SDL_render_sw_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_rotate.h b/src/render/software/SDL_rotate.h index 43e90e8af369c..9e08e53abb2bd 100644 --- a/src/render/software/SDL_rotate.h +++ b/src/render/software/SDL_rotate.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index 619925c589fa9..e62ff22e45b8b 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/software/SDL_triangle.h b/src/render/software/SDL_triangle.h index 9f983439f8f0f..f5af0aad1b3fc 100644 --- a/src/render/software/SDL_triangle.h +++ b/src/render/software/SDL_triangle.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 6b3831b658281..b665543d6d808 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/src/render/vitagxm/SDL_render_vita_gxm_memory.c index 159aa5624c05e..4eef2bb40feb6 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_memory.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/src/render/vitagxm/SDL_render_vita_gxm_memory.h index 6be61cf15adbc..9cd9f8899aa5c 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_memory.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_shaders.h b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h index 98d8605410f9f..ed3e3caa7bade 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_shaders.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c index bb89fa2c4a219..82fc7516a6384 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h index 1f4d5034cb137..067edc2df211e 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h index 2bdec06f4c7c6..0ae20924b04e3 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_types.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 4253af0d7d252..c2806f981bcd5 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/SDL_sensor_c.h b/src/sensor/SDL_sensor_c.h index 689a108920012..fce4896873969 100644 --- a/src/sensor/SDL_sensor_c.h +++ b/src/sensor/SDL_sensor_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index 2e3e3b3ca22b5..65fb1ad3091e7 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index b2154b1634f26..eb46dd5e046a3 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/android/SDL_androidsensor.h b/src/sensor/android/SDL_androidsensor.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/sensor/android/SDL_androidsensor.h +++ b/src/sensor/android/SDL_androidsensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/coremotion/SDL_coremotionsensor.h b/src/sensor/coremotion/SDL_coremotionsensor.h index cbbec8989ba81..2e65230e06239 100644 --- a/src/sensor/coremotion/SDL_coremotionsensor.h +++ b/src/sensor/coremotion/SDL_coremotionsensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/coremotion/SDL_coremotionsensor.m b/src/sensor/coremotion/SDL_coremotionsensor.m index 7fdc28a5d2fed..3f9c36464f695 100644 --- a/src/sensor/coremotion/SDL_coremotionsensor.m +++ b/src/sensor/coremotion/SDL_coremotionsensor.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/dummy/SDL_dummysensor.c b/src/sensor/dummy/SDL_dummysensor.c index 6e8f933b0ad8d..c9041d81e1c81 100644 --- a/src/sensor/dummy/SDL_dummysensor.c +++ b/src/sensor/dummy/SDL_dummysensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/dummy/SDL_dummysensor.h b/src/sensor/dummy/SDL_dummysensor.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/sensor/dummy/SDL_dummysensor.h +++ b/src/sensor/dummy/SDL_dummysensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/n3ds/SDL_n3dssensor.c b/src/sensor/n3ds/SDL_n3dssensor.c index 0e75c8e66880e..5b44d6562e549 100644 --- a/src/sensor/n3ds/SDL_n3dssensor.c +++ b/src/sensor/n3ds/SDL_n3dssensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/vita/SDL_vitasensor.c b/src/sensor/vita/SDL_vitasensor.c index 04323228c1b09..7c0cd8b6e06c9 100644 --- a/src/sensor/vita/SDL_vitasensor.c +++ b/src/sensor/vita/SDL_vitasensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/vita/SDL_vitasensor.h b/src/sensor/vita/SDL_vitasensor.h index 0bd3f3ba4cd9e..92518df7afcbb 100644 --- a/src/sensor/vita/SDL_vitasensor.h +++ b/src/sensor/vita/SDL_vitasensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index e61e826990be0..d7c8813fa320c 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/sensor/windows/SDL_windowssensor.h b/src/sensor/windows/SDL_windowssensor.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/sensor/windows/SDL_windowssensor.h +++ b/src/sensor/windows/SDL_windowssensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_crc16.c b/src/stdlib/SDL_crc16.c index 9847f983fdaf6..58830d6990291 100644 --- a/src/stdlib/SDL_crc16.c +++ b/src/stdlib/SDL_crc16.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_crc32.c b/src/stdlib/SDL_crc32.c index 2eb90174aa479..f61ae5439c59a 100644 --- a/src/stdlib/SDL_crc32.c +++ b/src/stdlib/SDL_crc32.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_getenv.c b/src/stdlib/SDL_getenv.c index b6837e5846b17..b8bceabafeea0 100644 --- a/src/stdlib/SDL_getenv.c +++ b/src/stdlib/SDL_getenv.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c index 2c98b77286f0d..b4c444bdd7b72 100644 --- a/src/stdlib/SDL_iconv.c +++ b/src/stdlib/SDL_iconv.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c index cfa9036c8e082..3f6a8240a589f 100644 --- a/src/stdlib/SDL_malloc.c +++ b/src/stdlib/SDL_malloc.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_mslibc.c b/src/stdlib/SDL_mslibc.c index 184b7e2d1cf8b..eac162dce0f0f 100644 --- a/src/stdlib/SDL_mslibc.c +++ b/src/stdlib/SDL_mslibc.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_qsort.c b/src/stdlib/SDL_qsort.c index 9e44f89d0194a..6454b2ca48920 100644 --- a/src/stdlib/SDL_qsort.c +++ b/src/stdlib/SDL_qsort.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_stdlib.c b/src/stdlib/SDL_stdlib.c index 789c8eb90b23c..97cab4c5267b5 100644 --- a/src/stdlib/SDL_stdlib.c +++ b/src/stdlib/SDL_stdlib.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 192bd3f99163a..0a88b4ede67a5 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_strtokr.c b/src/stdlib/SDL_strtokr.c index e67c0ed415ff3..53026184f6f6f 100644 --- a/src/stdlib/SDL_strtokr.c +++ b/src/stdlib/SDL_strtokr.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/stdlib/SDL_vacopy.h b/src/stdlib/SDL_vacopy.h index e1df5c6bc8374..e557b489df161 100644 --- a/src/stdlib/SDL_vacopy.h +++ b/src/stdlib/SDL_vacopy.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_assert.c b/src/test/SDL_test_assert.c index b0dd71e9f4dcb..ad7b63a1e630b 100644 --- a/src/test/SDL_test_assert.c +++ b/src/test/SDL_test_assert.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 655a8a86e41b8..b5a258f8fb862 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index f0244d57fd13a..d7adb22daf6ba 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_crc32.c b/src/test/SDL_test_crc32.c index 57ebef3734957..b079daed0e69a 100644 --- a/src/test/SDL_test_crc32.c +++ b/src/test/SDL_test_crc32.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_font.c b/src/test/SDL_test_font.c index 7f33918980e62..67e2c17ba9603 100644 --- a/src/test/SDL_test_font.c +++ b/src/test/SDL_test_font.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_fuzzer.c b/src/test/SDL_test_fuzzer.c index 37fe9a591f2fb..7e45f6c0e603a 100644 --- a/src/test/SDL_test_fuzzer.c +++ b/src/test/SDL_test_fuzzer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_harness.c b/src/test/SDL_test_harness.c index e17bb12159eca..ed43b7a9870fa 100644 --- a/src/test/SDL_test_harness.c +++ b/src/test/SDL_test_harness.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_log.c b/src/test/SDL_test_log.c index 54261f59917c2..e3532dc07c386 100644 --- a/src/test/SDL_test_log.c +++ b/src/test/SDL_test_log.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_md5.c b/src/test/SDL_test_md5.c index ce89e4ddaf72f..b14dd83afea92 100644 --- a/src/test/SDL_test_md5.c +++ b/src/test/SDL_test_md5.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_memory.c b/src/test/SDL_test_memory.c index 75d535a1d2328..f8c8d7b3b045d 100644 --- a/src/test/SDL_test_memory.c +++ b/src/test/SDL_test_memory.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/test/SDL_test_random.c b/src/test/SDL_test_random.c index f004ac7a72cee..72eceadc7e4c0 100644 --- a/src/test/SDL_test_random.c +++ b/src/test/SDL_test_random.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/SDL_systhread.h b/src/thread/SDL_systhread.h index fd9c966edda76..70df324c68ce5 100644 --- a/src/thread/SDL_systhread.h +++ b/src/thread/SDL_systhread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 4f3842c0452f2..ae9a1fda704d7 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h index 30961e039717d..7d4e245aee098 100644 --- a/src/thread/SDL_thread_c.h +++ b/src/thread/SDL_thread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_syscond.c b/src/thread/generic/SDL_syscond.c index 6a8b06aa8a062..291c21f6e4e93 100644 --- a/src/thread/generic/SDL_syscond.c +++ b/src/thread/generic/SDL_syscond.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_syscond_c.h b/src/thread/generic/SDL_syscond_c.h index 93a828c0e49f0..8e36078040fc6 100644 --- a/src/thread/generic/SDL_syscond_c.h +++ b/src/thread/generic/SDL_syscond_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index 1f21ca506f0ff..a56427038ad06 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_sysmutex_c.h b/src/thread/generic/SDL_sysmutex_c.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/thread/generic/SDL_sysmutex_c.h +++ b/src/thread/generic/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_sysrwlock.c b/src/thread/generic/SDL_sysrwlock.c index 73c15e961e5a4..f41c28d7b332d 100644 --- a/src/thread/generic/SDL_sysrwlock.c +++ b/src/thread/generic/SDL_sysrwlock.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_sysrwlock_c.h b/src/thread/generic/SDL_sysrwlock_c.h index 9083cc89c84e8..8264fa896dbbe 100644 --- a/src/thread/generic/SDL_sysrwlock_c.h +++ b/src/thread/generic/SDL_sysrwlock_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_syssem.c b/src/thread/generic/SDL_syssem.c index e2e0f9ca91974..8ae5324350d66 100644 --- a/src/thread/generic/SDL_syssem.c +++ b/src/thread/generic/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_systhread.c b/src/thread/generic/SDL_systhread.c index ce2c8df223dcd..3e455850ba5c2 100644 --- a/src/thread/generic/SDL_systhread.c +++ b/src/thread/generic/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_systhread_c.h b/src/thread/generic/SDL_systhread_c.h index 0dc26b36d5793..352961bee2a20 100644 --- a/src/thread/generic/SDL_systhread_c.h +++ b/src/thread/generic/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/generic/SDL_systls.c b/src/thread/generic/SDL_systls.c index 7ccfd48b379fe..e439f4d4b69e3 100644 --- a/src/thread/generic/SDL_systls.c +++ b/src/thread/generic/SDL_systls.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_syscond.c b/src/thread/n3ds/SDL_syscond.c index aae480b232e66..ff82627fb24fb 100644 --- a/src/thread/n3ds/SDL_syscond.c +++ b/src/thread/n3ds/SDL_syscond.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 61455517800c5..0ca67a584aa22 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_sysmutex_c.h b/src/thread/n3ds/SDL_sysmutex_c.h index aeb341982cf8a..1b22566340ea6 100644 --- a/src/thread/n3ds/SDL_sysmutex_c.h +++ b/src/thread/n3ds/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_syssem.c b/src/thread/n3ds/SDL_syssem.c index 31bca0dd213f9..025aec3b77cac 100644 --- a/src/thread/n3ds/SDL_syssem.c +++ b/src/thread/n3ds/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_systhread.c b/src/thread/n3ds/SDL_systhread.c index 17a50bb24e364..d99fca5a2f7f0 100644 --- a/src/thread/n3ds/SDL_systhread.c +++ b/src/thread/n3ds/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/n3ds/SDL_systhread_c.h b/src/thread/n3ds/SDL_systhread_c.h index e0fc68117d584..195c8cff6c5ee 100644 --- a/src/thread/n3ds/SDL_systhread_c.h +++ b/src/thread/n3ds/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ngage/SDL_sysmutex.cpp b/src/thread/ngage/SDL_sysmutex.cpp index 4d5e3b08cda40..5bf1fd736ebe2 100644 --- a/src/thread/ngage/SDL_sysmutex.cpp +++ b/src/thread/ngage/SDL_sysmutex.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ngage/SDL_syssem.cpp b/src/thread/ngage/SDL_syssem.cpp index 8c458e947187a..081d27870b316 100644 --- a/src/thread/ngage/SDL_syssem.cpp +++ b/src/thread/ngage/SDL_syssem.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ngage/SDL_systhread.cpp b/src/thread/ngage/SDL_systhread.cpp index 6ce6fdab730ca..e57ff6f29bfde 100644 --- a/src/thread/ngage/SDL_systhread.cpp +++ b/src/thread/ngage/SDL_systhread.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ngage/SDL_systhread_c.h b/src/thread/ngage/SDL_systhread_c.h index 8fd96b5b039ba..c0b697282df36 100644 --- a/src/thread/ngage/SDL_systhread_c.h +++ b/src/thread/ngage/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ps2/SDL_syssem.c b/src/thread/ps2/SDL_syssem.c index 09a846d7a71b0..2cd939731d262 100644 --- a/src/thread/ps2/SDL_syssem.c +++ b/src/thread/ps2/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ps2/SDL_systhread.c b/src/thread/ps2/SDL_systhread.c index b40b0be0cc276..c6e4f68199711 100644 --- a/src/thread/ps2/SDL_systhread.c +++ b/src/thread/ps2/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/ps2/SDL_systhread_c.h b/src/thread/ps2/SDL_systhread_c.h index b9757045391b5..afab3838f4161 100644 --- a/src/thread/ps2/SDL_systhread_c.h +++ b/src/thread/ps2/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 7fb94ee7596b1..259f46a239292 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/psp/SDL_sysmutex_c.h b/src/thread/psp/SDL_sysmutex_c.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/thread/psp/SDL_sysmutex_c.h +++ b/src/thread/psp/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index 098a15bb3afc5..9d6065306e250 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/psp/SDL_systhread.c b/src/thread/psp/SDL_systhread.c index 9f3e1a4839f38..a6f6bf72be680 100644 --- a/src/thread/psp/SDL_systhread.c +++ b/src/thread/psp/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/psp/SDL_systhread_c.h b/src/thread/psp/SDL_systhread_c.h index ef3fbccf590a4..ffa844924b77c 100644 --- a/src/thread/psp/SDL_systhread_c.h +++ b/src/thread/psp/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_syscond.c b/src/thread/pthread/SDL_syscond.c index 026f0a1a10ecb..7583abbd408f9 100644 --- a/src/thread/pthread/SDL_syscond.c +++ b/src/thread/pthread/SDL_syscond.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index 9ffbd53c5eafe..07d35cfb970fa 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_sysmutex_c.h b/src/thread/pthread/SDL_sysmutex_c.h index 3e365f6eb091c..bbb5aa87f3213 100644 --- a/src/thread/pthread/SDL_sysmutex_c.h +++ b/src/thread/pthread/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_sysrwlock.c b/src/thread/pthread/SDL_sysrwlock.c index 6d70ac8eadaf1..8e486dc48f32b 100644 --- a/src/thread/pthread/SDL_sysrwlock.c +++ b/src/thread/pthread/SDL_sysrwlock.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_syssem.c b/src/thread/pthread/SDL_syssem.c index 0593e4b2aa5a7..d41377279761e 100644 --- a/src/thread/pthread/SDL_syssem.c +++ b/src/thread/pthread/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index c1e7d062462a6..4a8b84b970636 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_systhread_c.h b/src/thread/pthread/SDL_systhread_c.h index 8a8c07ad67161..e8593c46bd81d 100644 --- a/src/thread/pthread/SDL_systhread_c.h +++ b/src/thread/pthread/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/pthread/SDL_systls.c b/src/thread/pthread/SDL_systls.c index 17b3b64b19694..9c44d575efb9a 100644 --- a/src/thread/pthread/SDL_systls.c +++ b/src/thread/pthread/SDL_systls.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_syscond.cpp b/src/thread/stdcpp/SDL_syscond.cpp index 72536d601c8a6..02c1ddd29d0f9 100644 --- a/src/thread/stdcpp/SDL_syscond.cpp +++ b/src/thread/stdcpp/SDL_syscond.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_sysmutex.cpp b/src/thread/stdcpp/SDL_sysmutex.cpp index 1d33701b2fb93..48be2f96b6afe 100644 --- a/src/thread/stdcpp/SDL_sysmutex.cpp +++ b/src/thread/stdcpp/SDL_sysmutex.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_sysmutex_c.h b/src/thread/stdcpp/SDL_sysmutex_c.h index f70e4c69f35ac..c18f987401401 100644 --- a/src/thread/stdcpp/SDL_sysmutex_c.h +++ b/src/thread/stdcpp/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_sysrwlock.cpp b/src/thread/stdcpp/SDL_sysrwlock.cpp index 7e6742c4e947a..9bb7c1d79f9a2 100644 --- a/src/thread/stdcpp/SDL_sysrwlock.cpp +++ b/src/thread/stdcpp/SDL_sysrwlock.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_systhread.cpp b/src/thread/stdcpp/SDL_systhread.cpp index a1d1fd17c5c66..29004ad2636cd 100644 --- a/src/thread/stdcpp/SDL_systhread.cpp +++ b/src/thread/stdcpp/SDL_systhread.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/stdcpp/SDL_systhread_c.h b/src/thread/stdcpp/SDL_systhread_c.h index 160e50adca28b..49aa4e85f8811 100644 --- a/src/thread/stdcpp/SDL_systhread_c.h +++ b/src/thread/stdcpp/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index 38f31ab05b1f9..c86508ffb5bd7 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/vita/SDL_sysmutex_c.h b/src/thread/vita/SDL_sysmutex_c.h index 2a7ba0c1bc04b..7e84b1a47c558 100644 --- a/src/thread/vita/SDL_sysmutex_c.h +++ b/src/thread/vita/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/vita/SDL_syssem.c b/src/thread/vita/SDL_syssem.c index ca8636c35ceba..1075c528c2b16 100644 --- a/src/thread/vita/SDL_syssem.c +++ b/src/thread/vita/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/vita/SDL_systhread.c b/src/thread/vita/SDL_systhread.c index 013de1134b091..fd6dad9df0ff0 100644 --- a/src/thread/vita/SDL_systhread.c +++ b/src/thread/vita/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/vita/SDL_systhread_c.h b/src/thread/vita/SDL_systhread_c.h index de7a0a60b81df..eb5b1c732e1a9 100644 --- a/src/thread/vita/SDL_systhread_c.h +++ b/src/thread/vita/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_syscond_cv.c b/src/thread/windows/SDL_syscond_cv.c index fdc806411d411..4dd4d97a6fd98 100644 --- a/src/thread/windows/SDL_syscond_cv.c +++ b/src/thread/windows/SDL_syscond_cv.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index aef7e93126d5c..7272b00e76cdb 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_sysmutex_c.h b/src/thread/windows/SDL_sysmutex_c.h index d495ffe49bb3b..1fe81ba081e8c 100644 --- a/src/thread/windows/SDL_sysmutex_c.h +++ b/src/thread/windows/SDL_sysmutex_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_sysrwlock_srw.c b/src/thread/windows/SDL_sysrwlock_srw.c index 864743fdb00f5..a02cfff281c91 100644 --- a/src/thread/windows/SDL_sysrwlock_srw.c +++ b/src/thread/windows/SDL_sysrwlock_srw.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_syssem.c b/src/thread/windows/SDL_syssem.c index acb0950bc9511..7ad6f619afd1a 100644 --- a/src/thread/windows/SDL_syssem.c +++ b/src/thread/windows/SDL_syssem.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c index 0076656506ce6..693700beab61e 100644 --- a/src/thread/windows/SDL_systhread.c +++ b/src/thread/windows/SDL_systhread.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_systhread_c.h b/src/thread/windows/SDL_systhread_c.h index 180b82ea35a36..568551d697c7b 100644 --- a/src/thread/windows/SDL_systhread_c.h +++ b/src/thread/windows/SDL_systhread_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/thread/windows/SDL_systls.c b/src/thread/windows/SDL_systls.c index 3a0dcc976a159..4eb2d53da532c 100644 --- a/src/thread/windows/SDL_systls.c +++ b/src/thread/windows/SDL_systls.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index 4b72503d6d5f1..d3501155a57f4 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/SDL_timer_c.h b/src/timer/SDL_timer_c.h index dd4e0268deef7..161fb91434c71 100644 --- a/src/timer/SDL_timer_c.h +++ b/src/timer/SDL_timer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/dummy/SDL_systimer.c b/src/timer/dummy/SDL_systimer.c index 351f35ceca1ba..3d54655c5d71b 100644 --- a/src/timer/dummy/SDL_systimer.c +++ b/src/timer/dummy/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/haiku/SDL_systimer.c b/src/timer/haiku/SDL_systimer.c index 6bc51e71a9b7b..726e4150180fc 100644 --- a/src/timer/haiku/SDL_systimer.c +++ b/src/timer/haiku/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/n3ds/SDL_systimer.c b/src/timer/n3ds/SDL_systimer.c index fc8fdc304a7c1..99389a4c7626d 100644 --- a/src/timer/n3ds/SDL_systimer.c +++ b/src/timer/n3ds/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/ngage/SDL_systimer.cpp b/src/timer/ngage/SDL_systimer.cpp index 41037a86ed08c..f7f11ea3d3202 100644 --- a/src/timer/ngage/SDL_systimer.cpp +++ b/src/timer/ngage/SDL_systimer.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/ps2/SDL_systimer.c b/src/timer/ps2/SDL_systimer.c index 2ba22807c77e9..7070e17af49ff 100644 --- a/src/timer/ps2/SDL_systimer.c +++ b/src/timer/ps2/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/psp/SDL_systimer.c b/src/timer/psp/SDL_systimer.c index 7ccf73fe07c1e..9df7c11a412fa 100644 --- a/src/timer/psp/SDL_systimer.c +++ b/src/timer/psp/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/unix/SDL_systimer.c b/src/timer/unix/SDL_systimer.c index 3691a08d0186a..a9c6ccbb86b36 100644 --- a/src/timer/unix/SDL_systimer.c +++ b/src/timer/unix/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/vita/SDL_systimer.c b/src/timer/vita/SDL_systimer.c index f7523248e81a7..a99b8e1c2b359 100644 --- a/src/timer/vita/SDL_systimer.c +++ b/src/timer/vita/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/timer/windows/SDL_systimer.c b/src/timer/windows/SDL_systimer.c index 19ab9a5c477bc..54f56de182156 100644 --- a/src/timer/windows/SDL_systimer.c +++ b/src/timer/windows/SDL_systimer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index 2bfd6edb43f8a..cc47574397885 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_RLEaccel_c.h b/src/video/SDL_RLEaccel_c.h index ac37c116d5e41..cbf4c4908ee2d 100644 --- a/src/video/SDL_RLEaccel_c.h +++ b/src/video/SDL_RLEaccel_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 886fcb936d9f1..fb82675bc1aca 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index 09030265d4a2f..be30fa64fa8f6 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_0.c b/src/video/SDL_blit_0.c index 6ad4331f5546d..6fc4356e727ce 100644 --- a/src/video/SDL_blit_0.c +++ b/src/video/SDL_blit_0.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_1.c b/src/video/SDL_blit_1.c index 1a398da6a252a..5f5a3a811c6ef 100644 --- a/src/video/SDL_blit_1.c +++ b/src/video/SDL_blit_1.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_A.c b/src/video/SDL_blit_A.c index 7ee829c5e2d92..1c5e9ceb089b4 100644 --- a/src/video/SDL_blit_A.c +++ b/src/video/SDL_blit_A.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index 541e6edb11e14..49d86a74f7482 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_auto.c b/src/video/SDL_blit_auto.c index 9cfb5bc9c51bd..5bd6f1350fdc5 100644 --- a/src/video/SDL_blit_auto.c +++ b/src/video/SDL_blit_auto.c @@ -1,7 +1,7 @@ /* DO NOT EDIT! This file is generated by sdlgenblit.pl */ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_auto.h b/src/video/SDL_blit_auto.h index c927b62bff746..156145046d9f0 100644 --- a/src/video/SDL_blit_auto.h +++ b/src/video/SDL_blit_auto.h @@ -1,7 +1,7 @@ /* DO NOT EDIT! This file is generated by sdlgenblit.pl */ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_copy.c b/src/video/SDL_blit_copy.c index 8dc3511ede076..36edfc2566242 100644 --- a/src/video/SDL_blit_copy.c +++ b/src/video/SDL_blit_copy.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_copy.h b/src/video/SDL_blit_copy.h index a2967b5246175..de9311531f316 100644 --- a/src/video/SDL_blit_copy.h +++ b/src/video/SDL_blit_copy.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index d4d3d43bac847..621f47c6561c7 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_blit_slow.h b/src/video/SDL_blit_slow.h index 3fabc78bf9c2e..40e1a44cdcdb2 100644 --- a/src/video/SDL_blit_slow.h +++ b/src/video/SDL_blit_slow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index ef2caf7383979..ba7c50da0e826 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c index e6266724e855e..dbfbe51363a0f 100644 --- a/src/video/SDL_clipboard.c +++ b/src/video/SDL_clipboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_clipboard_c.h b/src/video/SDL_clipboard_c.h index 50a245bd8fd80..98e204a26378a 100644 --- a/src/video/SDL_clipboard_c.h +++ b/src/video/SDL_clipboard_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 60c66f37dd7d7..0adf1d77fd226 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -1,6 +1,6 @@ /* * Simple DirectMedia Layer - * Copyright (C) 1997-2023 Sam Lantinga + * Copyright (C) 1997-2024 Sam Lantinga * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h index 1916e12eaab50..fed546a67bcb8 100644 --- a/src/video/SDL_egl_c.h +++ b/src/video/SDL_egl_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_fillrect.c b/src/video/SDL_fillrect.c index 2a4c132be22f0..070e0733989b6 100644 --- a/src/video/SDL_fillrect.c +++ b/src/video/SDL_fillrect.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index d7be3e1368e34..72def3a190a6c 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index 897f973d54020..e0def8aac6068 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_rect.c b/src/video/SDL_rect.c index b91723636d080..a588fa56eff8b 100644 --- a/src/video/SDL_rect.c +++ b/src/video/SDL_rect.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_rect_c.h b/src/video/SDL_rect_c.h index bac380cd9accd..e3d2a033af0ba 100644 --- a/src/video/SDL_rect_c.h +++ b/src/video/SDL_rect_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_rect_impl.h b/src/video/SDL_rect_impl.h index 0b623808a29a9..15492da1337e8 100644 --- a/src/video/SDL_rect_impl.h +++ b/src/video/SDL_rect_impl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_stretch.c b/src/video/SDL_stretch.c index 1bc8c74f1fca1..77e415cf654f6 100644 --- a/src/video/SDL_stretch.c +++ b/src/video/SDL_stretch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index dec18df53d8e3..b5fbba1aa3947 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_surface_pixel_impl.h b/src/video/SDL_surface_pixel_impl.h index 94f1073615292..67f772fe1533a 100644 --- a/src/video/SDL_surface_pixel_impl.h +++ b/src/video/SDL_surface_pixel_impl.h @@ -1,5 +1,5 @@ /* - Copyright 1997-2023 Sam Lantinga + Copyright 1997-2024 Sam Lantinga Copyright 2023 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 8a8816f8c82e4..0273f1ad8b6a9 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_sysvideocapture.h b/src/video/SDL_sysvideocapture.h index 305ba53ec586b..e7ba6e96b056d 100644 --- a/src/video/SDL_sysvideocapture.h +++ b/src/video/SDL_sysvideocapture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index cbab78e823423..464490e922633 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video_c.h b/src/video/SDL_video_c.h index 78f3a3abe9920..ceacd4ccf4c31 100644 --- a/src/video/SDL_video_c.h +++ b/src/video/SDL_video_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video_capture.c b/src/video/SDL_video_capture.c index 57f960addb908..295fc248315c8 100644 --- a/src/video/SDL_video_capture.c +++ b/src/video/SDL_video_capture.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video_capture_c.h b/src/video/SDL_video_capture_c.h index 36f2494d6e683..d7f1aa17d2e9d 100644 --- a/src/video/SDL_video_capture_c.h +++ b/src/video/SDL_video_capture_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video_capture_v4l2.c b/src/video/SDL_video_capture_v4l2.c index 29dcb0f4ee62e..b826704e4b7cf 100644 --- a/src/video/SDL_video_capture_v4l2.c +++ b/src/video/SDL_video_capture_v4l2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_video_unsupported.c b/src/video/SDL_video_unsupported.c index 66be30101873d..633e717e13d48 100644 --- a/src/video/SDL_video_unsupported.c +++ b/src/video/SDL_video_unsupported.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_vulkan_internal.h b/src/video/SDL_vulkan_internal.h index 4d749fa6324f8..5edf7c71b1e63 100644 --- a/src/video/SDL_vulkan_internal.h +++ b/src/video/SDL_vulkan_internal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_vulkan_utils.c b/src/video/SDL_vulkan_utils.c index c2e0a600fca6b..c8452aa6bc707 100644 --- a/src/video/SDL_vulkan_utils.c +++ b/src/video/SDL_vulkan_utils.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c index e8db133818b56..63e0236854096 100644 --- a/src/video/SDL_yuv.c +++ b/src/video/SDL_yuv.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/SDL_yuv_c.h b/src/video/SDL_yuv_c.h index d0ff4463ab404..033a013b9cc88 100644 --- a/src/video/SDL_yuv_c.h +++ b/src/video/SDL_yuv_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_android_video_capture.c b/src/video/android/SDL_android_video_capture.c index c673fc83f7a64..3deec8140335a 100644 --- a/src/video/android/SDL_android_video_capture.c +++ b/src/video/android/SDL_android_video_capture.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidclipboard.c b/src/video/android/SDL_androidclipboard.c index 4dffa43662ac4..70c4fc15562e6 100644 --- a/src/video/android/SDL_androidclipboard.c +++ b/src/video/android/SDL_androidclipboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidclipboard.h b/src/video/android/SDL_androidclipboard.h index d161ef01bb429..e6b22b2aebcb5 100644 --- a/src/video/android/SDL_androidclipboard.h +++ b/src/video/android/SDL_androidclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index 8d3679106ecbf..a24a9f150eb87 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidevents.h b/src/video/android/SDL_androidevents.h index fc6753a10dc1a..35bd5b712d97d 100644 --- a/src/video/android/SDL_androidevents.h +++ b/src/video/android/SDL_androidevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidgl.c b/src/video/android/SDL_androidgl.c index 2b02f8b6e7cb2..f3b40c7841390 100644 --- a/src/video/android/SDL_androidgl.c +++ b/src/video/android/SDL_androidgl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidgl.h b/src/video/android/SDL_androidgl.h index 059d3dcf45204..ab22f83d42699 100644 --- a/src/video/android/SDL_androidgl.h +++ b/src/video/android/SDL_androidgl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidkeyboard.c b/src/video/android/SDL_androidkeyboard.c index 0d602345f5870..4325faa3b6a7e 100644 --- a/src/video/android/SDL_androidkeyboard.c +++ b/src/video/android/SDL_androidkeyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidkeyboard.h b/src/video/android/SDL_androidkeyboard.h index ed3c6fe3ff763..0a194d63d6917 100644 --- a/src/video/android/SDL_androidkeyboard.h +++ b/src/video/android/SDL_androidkeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidmessagebox.c b/src/video/android/SDL_androidmessagebox.c index 8dc1c9e83d4b8..a582be576d1c8 100644 --- a/src/video/android/SDL_androidmessagebox.c +++ b/src/video/android/SDL_androidmessagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidmessagebox.h b/src/video/android/SDL_androidmessagebox.h index c111d00dac143..8b2e388307bb3 100644 --- a/src/video/android/SDL_androidmessagebox.h +++ b/src/video/android/SDL_androidmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c index c3b7b14f2a2bc..39dee434fef8a 100644 --- a/src/video/android/SDL_androidmouse.c +++ b/src/video/android/SDL_androidmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidmouse.h b/src/video/android/SDL_androidmouse.h index c5e88c8f06767..d6f6f7970f61b 100644 --- a/src/video/android/SDL_androidmouse.h +++ b/src/video/android/SDL_androidmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 85e7e04cad29a..6f56f6cb3e7ec 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidtouch.h b/src/video/android/SDL_androidtouch.h index 7ee5aa9822bbd..1637b3f5cee24 100644 --- a/src/video/android/SDL_androidtouch.h +++ b/src/video/android/SDL_androidtouch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index f5f31d739b1a4..eea89b8b07c60 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidvideo.h b/src/video/android/SDL_androidvideo.h index e8b9a09b357de..f6dd54eb56073 100644 --- a/src/video/android/SDL_androidvideo.h +++ b/src/video/android/SDL_androidvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c index 9c18996f8c1e4..14c391a64da03 100644 --- a/src/video/android/SDL_androidvulkan.c +++ b/src/video/android/SDL_androidvulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidvulkan.h b/src/video/android/SDL_androidvulkan.h index d477ad106fc26..314c5d878840e 100644 --- a/src/video/android/SDL_androidvulkan.h +++ b/src/video/android/SDL_androidvulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 0ad5acf2ebf43..858aca0f483cf 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/android/SDL_androidwindow.h b/src/video/android/SDL_androidwindow.h index 5336f912a1c1e..dff81c7bfe9de 100644 --- a/src/video/android/SDL_androidwindow.h +++ b/src/video/android/SDL_androidwindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaclipboard.h b/src/video/cocoa/SDL_cocoaclipboard.h index 8e4b2acd5d150..4fdfb4089b0f6 100644 --- a/src/video/cocoa/SDL_cocoaclipboard.h +++ b/src/video/cocoa/SDL_cocoaclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaclipboard.m b/src/video/cocoa/SDL_cocoaclipboard.m index a02c1f0622b73..b51f8307f42f8 100644 --- a/src/video/cocoa/SDL_cocoaclipboard.m +++ b/src/video/cocoa/SDL_cocoaclipboard.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaevents.h b/src/video/cocoa/SDL_cocoaevents.h index c5846d708c402..096db4dc97487 100644 --- a/src/video/cocoa/SDL_cocoaevents.h +++ b/src/video/cocoa/SDL_cocoaevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 7673d226d83a3..c48c9544dcbfd 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoakeyboard.h b/src/video/cocoa/SDL_cocoakeyboard.h index d522a9c633d73..b1be77dc8b7bb 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.h +++ b/src/video/cocoa/SDL_cocoakeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m index 957c7ac5201d9..04b06bf6865bc 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.m +++ b/src/video/cocoa/SDL_cocoakeyboard.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamessagebox.h b/src/video/cocoa/SDL_cocoamessagebox.h index 7dbd81a539011..f5673453a302b 100644 --- a/src/video/cocoa/SDL_cocoamessagebox.h +++ b/src/video/cocoa/SDL_cocoamessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamessagebox.m b/src/video/cocoa/SDL_cocoamessagebox.m index 39ec8772d1b3a..9ed5ea50aa54c 100644 --- a/src/video/cocoa/SDL_cocoamessagebox.m +++ b/src/video/cocoa/SDL_cocoamessagebox.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoametalview.h b/src/video/cocoa/SDL_cocoametalview.h index aff42f8484292..3e9799ed712fa 100644 --- a/src/video/cocoa/SDL_cocoametalview.h +++ b/src/video/cocoa/SDL_cocoametalview.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m index 08a5c0d472872..71ede95583d0b 100644 --- a/src/video/cocoa/SDL_cocoametalview.m +++ b/src/video/cocoa/SDL_cocoametalview.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamodes.h b/src/video/cocoa/SDL_cocoamodes.h index b3f44c0c6edf6..475d3ab2f15f2 100644 --- a/src/video/cocoa/SDL_cocoamodes.h +++ b/src/video/cocoa/SDL_cocoamodes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamodes.m b/src/video/cocoa/SDL_cocoamodes.m index fd58f8ef6f2a8..072e49a65c655 100644 --- a/src/video/cocoa/SDL_cocoamodes.m +++ b/src/video/cocoa/SDL_cocoamodes.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamouse.h b/src/video/cocoa/SDL_cocoamouse.h index 4e89b7527ce25..b6b3e7497b6d5 100644 --- a/src/video/cocoa/SDL_cocoamouse.h +++ b/src/video/cocoa/SDL_cocoamouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index 49f828125195e..3be095b37af26 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaopengl.h b/src/video/cocoa/SDL_cocoaopengl.h index 1ec05d8f5a8ec..9839c48805bde 100644 --- a/src/video/cocoa/SDL_cocoaopengl.h +++ b/src/video/cocoa/SDL_cocoaopengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index ec0250c340a0d..022d0786ff41e 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaopengles.h b/src/video/cocoa/SDL_cocoaopengles.h index cbdaadd6f6438..57da08aa89088 100644 --- a/src/video/cocoa/SDL_cocoaopengles.h +++ b/src/video/cocoa/SDL_cocoaopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoaopengles.m b/src/video/cocoa/SDL_cocoaopengles.m index bf28563e0857a..0cac7dfb98400 100644 --- a/src/video/cocoa/SDL_cocoaopengles.m +++ b/src/video/cocoa/SDL_cocoaopengles.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoavideo.h b/src/video/cocoa/SDL_cocoavideo.h index 775035fd16a46..2929fe0ad1755 100644 --- a/src/video/cocoa/SDL_cocoavideo.h +++ b/src/video/cocoa/SDL_cocoavideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index e115724e90d7c..1af270e342dc1 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoavulkan.h b/src/video/cocoa/SDL_cocoavulkan.h index fdc4a7e69f5f7..2d94c179a2a94 100644 --- a/src/video/cocoa/SDL_cocoavulkan.h +++ b/src/video/cocoa/SDL_cocoavulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m index 3586e8f64bd09..edcfa441e1a88 100644 --- a/src/video/cocoa/SDL_cocoavulkan.m +++ b/src/video/cocoa/SDL_cocoavulkan.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 1adf6d657784a..46a27b6829a95 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 758d372357649..0b0c8113c8f70 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullevents.c b/src/video/dummy/SDL_nullevents.c index 51e2a8f1f4afe..6849efbbe60dd 100644 --- a/src/video/dummy/SDL_nullevents.c +++ b/src/video/dummy/SDL_nullevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullevents_c.h b/src/video/dummy/SDL_nullevents_c.h index 5cae376b6ea2c..5b1e15fe6e377 100644 --- a/src/video/dummy/SDL_nullevents_c.h +++ b/src/video/dummy/SDL_nullevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c index e67954e067fcb..87d1b1be5f133 100644 --- a/src/video/dummy/SDL_nullframebuffer.c +++ b/src/video/dummy/SDL_nullframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullframebuffer_c.h b/src/video/dummy/SDL_nullframebuffer_c.h index 41ecfaaf5b753..d1e51e91c2445 100644 --- a/src/video/dummy/SDL_nullframebuffer_c.h +++ b/src/video/dummy/SDL_nullframebuffer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index 07f3dfd4bce42..76336d6f00ca9 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/dummy/SDL_nullvideo.h b/src/video/dummy/SDL_nullvideo.h index d7ee2fad6c3bc..97534133f54e5 100644 --- a/src/video/dummy/SDL_nullvideo.h +++ b/src/video/dummy/SDL_nullvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 006cc21319751..271e870a7be6f 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenevents.h b/src/video/emscripten/SDL_emscriptenevents.h index 230b172206ce2..41859805fe7d0 100644 --- a/src/video/emscripten/SDL_emscriptenevents.h +++ b/src/video/emscripten/SDL_emscriptenevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.c b/src/video/emscripten/SDL_emscriptenframebuffer.c index 318a32305fe3c..7d81220360715 100644 --- a/src/video/emscripten/SDL_emscriptenframebuffer.c +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.h b/src/video/emscripten/SDL_emscriptenframebuffer.h index 0192e3507560b..2384ef5869c3f 100644 --- a/src/video/emscripten/SDL_emscriptenframebuffer.h +++ b/src/video/emscripten/SDL_emscriptenframebuffer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c index 40d1af8afdffb..e6beab7ecd18d 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.c +++ b/src/video/emscripten/SDL_emscriptenmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenmouse.h b/src/video/emscripten/SDL_emscriptenmouse.h index 94fd44dfb49e0..f78b2c205d981 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.h +++ b/src/video/emscripten/SDL_emscriptenmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c index 6f0cdd9df48fb..c195e0262bf2e 100644 --- a/src/video/emscripten/SDL_emscriptenopengles.c +++ b/src/video/emscripten/SDL_emscriptenopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenopengles.h b/src/video/emscripten/SDL_emscriptenopengles.h index ecd879296d22d..4a75162330e21 100644 --- a/src/video/emscripten/SDL_emscriptenopengles.h +++ b/src/video/emscripten/SDL_emscriptenopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index b28dbd96acfc4..1e6b08394355d 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/emscripten/SDL_emscriptenvideo.h b/src/video/emscripten/SDL_emscriptenvideo.h index e5e08e148a64f..4417205850c09 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.h +++ b/src/video/emscripten/SDL_emscriptenvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/gdk/SDL_gdktextinput.cpp b/src/video/gdk/SDL_gdktextinput.cpp index c4bdc83ea6e9a..29ffcc0d651ab 100644 --- a/src/video/gdk/SDL_gdktextinput.cpp +++ b/src/video/gdk/SDL_gdktextinput.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/gdk/SDL_gdktextinput.h b/src/video/gdk/SDL_gdktextinput.h index 41f7717881873..7bce9c38133eb 100644 --- a/src/video/gdk/SDL_gdktextinput.h +++ b/src/video/gdk/SDL_gdktextinput.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_BApp.h b/src/video/haiku/SDL_BApp.h index 6deaff2ec5fc5..39fec77829cdd 100644 --- a/src/video/haiku/SDL_BApp.h +++ b/src/video/haiku/SDL_BApp.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_BWin.h b/src/video/haiku/SDL_BWin.h index 4cd1582cd9b7c..1a9a786cb03c2 100644 --- a/src/video/haiku/SDL_BWin.h +++ b/src/video/haiku/SDL_BWin.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bclipboard.cc b/src/video/haiku/SDL_bclipboard.cc index 5759482680eae..f33072f5f11aa 100644 --- a/src/video/haiku/SDL_bclipboard.cc +++ b/src/video/haiku/SDL_bclipboard.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bclipboard.h b/src/video/haiku/SDL_bclipboard.h index 62a6791bc3ff3..ce36bf3c360a1 100644 --- a/src/video/haiku/SDL_bclipboard.h +++ b/src/video/haiku/SDL_bclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bevents.cc b/src/video/haiku/SDL_bevents.cc index 6075eb854a3cf..c3af6c232dc13 100644 --- a/src/video/haiku/SDL_bevents.cc +++ b/src/video/haiku/SDL_bevents.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bevents.h b/src/video/haiku/SDL_bevents.h index d8db1b54cb40c..1edc7229c2192 100644 --- a/src/video/haiku/SDL_bevents.h +++ b/src/video/haiku/SDL_bevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bframebuffer.cc b/src/video/haiku/SDL_bframebuffer.cc index f519650b46982..5beb4567d0474 100644 --- a/src/video/haiku/SDL_bframebuffer.cc +++ b/src/video/haiku/SDL_bframebuffer.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bframebuffer.h b/src/video/haiku/SDL_bframebuffer.h index a1ab7ee152ec6..769a5384715d8 100644 --- a/src/video/haiku/SDL_bframebuffer.h +++ b/src/video/haiku/SDL_bframebuffer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bkeyboard.cc b/src/video/haiku/SDL_bkeyboard.cc index 3f521c9512e4e..db64fd054e627 100644 --- a/src/video/haiku/SDL_bkeyboard.cc +++ b/src/video/haiku/SDL_bkeyboard.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bkeyboard.h b/src/video/haiku/SDL_bkeyboard.h index c16e9f9188d40..d6bf261243479 100644 --- a/src/video/haiku/SDL_bkeyboard.h +++ b/src/video/haiku/SDL_bkeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bmessagebox.cc b/src/video/haiku/SDL_bmessagebox.cc index 84d2d5f6135d0..fe8e963c7507c 100644 --- a/src/video/haiku/SDL_bmessagebox.cc +++ b/src/video/haiku/SDL_bmessagebox.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2018-2019 EXL This software is provided 'as-is', without any express or implied diff --git a/src/video/haiku/SDL_bmessagebox.h b/src/video/haiku/SDL_bmessagebox.h index 9c705e8de4d26..828e2e9689eae 100644 --- a/src/video/haiku/SDL_bmessagebox.h +++ b/src/video/haiku/SDL_bmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2018-2019 EXL This software is provided 'as-is', without any express or implied diff --git a/src/video/haiku/SDL_bmodes.cc b/src/video/haiku/SDL_bmodes.cc index 4c1c707212442..e7c83a875e405 100644 --- a/src/video/haiku/SDL_bmodes.cc +++ b/src/video/haiku/SDL_bmodes.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bmodes.h b/src/video/haiku/SDL_bmodes.h index 0a9ca796e25e4..661b7defbfb54 100644 --- a/src/video/haiku/SDL_bmodes.h +++ b/src/video/haiku/SDL_bmodes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bopengl.cc b/src/video/haiku/SDL_bopengl.cc index 7a2f7335a017e..ad47f41a55800 100644 --- a/src/video/haiku/SDL_bopengl.cc +++ b/src/video/haiku/SDL_bopengl.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bopengl.h b/src/video/haiku/SDL_bopengl.h index aea625cc6359d..c17cb51342516 100644 --- a/src/video/haiku/SDL_bopengl.h +++ b/src/video/haiku/SDL_bopengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 470242d992512..a6ee9a39d1433 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bvideo.h b/src/video/haiku/SDL_bvideo.h index 480aa2d2e3223..3c225c303aff5 100644 --- a/src/video/haiku/SDL_bvideo.h +++ b/src/video/haiku/SDL_bvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index f74b8dd6dfbe4..e3ca49fc72b80 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index 24d5c4f4cb96e..0e0325acf2763 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.c b/src/video/kmsdrm/SDL_kmsdrmdyn.c index e37e2c3e930b6..b03ede6df9634 100644 --- a/src/video/kmsdrm/SDL_kmsdrmdyn.c +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.h b/src/video/kmsdrm/SDL_kmsdrmdyn.h index 23048d27fa3b8..f9a292ec49a86 100644 --- a/src/video/kmsdrm/SDL_kmsdrmdyn.h +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmevents.c b/src/video/kmsdrm/SDL_kmsdrmevents.c index 7479e074da3cb..1523520404371 100644 --- a/src/video/kmsdrm/SDL_kmsdrmevents.c +++ b/src/video/kmsdrm/SDL_kmsdrmevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmevents.h b/src/video/kmsdrm/SDL_kmsdrmevents.h index 0f9bb8693ffbc..a67c5b3d3ab0e 100644 --- a/src/video/kmsdrm/SDL_kmsdrmevents.h +++ b/src/video/kmsdrm/SDL_kmsdrmevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c index 513f5f5338082..1b3524b917e6c 100644 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.c +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.h b/src/video/kmsdrm/SDL_kmsdrmmouse.h index 754dc19e3deb6..69b8b4c2b0fd1 100644 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.h +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c index 30ad56d163320..7c5841cef606b 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.h b/src/video/kmsdrm/SDL_kmsdrmopengles.h index 08f3561fa5f61..ff1989e98244e 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.h +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index d8f31ca9433c1..ad91d0691f758 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 3023f67d29521..70dd2681393aa 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index cea1663459321..0304f811ee8a0 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index c30d9fe98c61e..a3f463eafb252 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.h b/src/video/kmsdrm/SDL_kmsdrmvulkan.h index 5b327197d6666..b29cbe8353b81 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.h +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsevents.c b/src/video/n3ds/SDL_n3dsevents.c index 64cbe603801d8..8c963d9775376 100644 --- a/src/video/n3ds/SDL_n3dsevents.c +++ b/src/video/n3ds/SDL_n3dsevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsevents_c.h b/src/video/n3ds/SDL_n3dsevents_c.h index 25052cb0431ca..5a7b70dcef803 100644 --- a/src/video/n3ds/SDL_n3dsevents_c.h +++ b/src/video/n3ds/SDL_n3dsevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c index 09930621065b2..f368506feec4e 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer.c +++ b/src/video/n3ds/SDL_n3dsframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsframebuffer_c.h b/src/video/n3ds/SDL_n3dsframebuffer_c.h index 09caedaefdf7a..6a3eea0e4431f 100644 --- a/src/video/n3ds/SDL_n3dsframebuffer_c.h +++ b/src/video/n3ds/SDL_n3dsframebuffer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsswkb.c b/src/video/n3ds/SDL_n3dsswkb.c index 033fa5b5675d7..0948fff095e16 100644 --- a/src/video/n3ds/SDL_n3dsswkb.c +++ b/src/video/n3ds/SDL_n3dsswkb.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsswkb.h b/src/video/n3ds/SDL_n3dsswkb.h index fa942ef9b41d7..da86f0b5bb2d9 100644 --- a/src/video/n3ds/SDL_n3dsswkb.h +++ b/src/video/n3ds/SDL_n3dsswkb.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dstouch.c b/src/video/n3ds/SDL_n3dstouch.c index c0e5c07c23484..96ef93bbf8616 100644 --- a/src/video/n3ds/SDL_n3dstouch.c +++ b/src/video/n3ds/SDL_n3dstouch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dstouch.h b/src/video/n3ds/SDL_n3dstouch.h index d1e28e477456e..495688cb6bbba 100644 --- a/src/video/n3ds/SDL_n3dstouch.h +++ b/src/video/n3ds/SDL_n3dstouch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c index 4e55642fe6da2..0c168cb795d97 100644 --- a/src/video/n3ds/SDL_n3dsvideo.c +++ b/src/video/n3ds/SDL_n3dsvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/n3ds/SDL_n3dsvideo.h b/src/video/n3ds/SDL_n3dsvideo.h index 0c0af19c2db67..b5c501568cbc7 100644 --- a/src/video/n3ds/SDL_n3dsvideo.h +++ b/src/video/n3ds/SDL_n3dsvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngageevents.cpp b/src/video/ngage/SDL_ngageevents.cpp index 836fa74bc33cf..fecfaff9e4c29 100644 --- a/src/video/ngage/SDL_ngageevents.cpp +++ b/src/video/ngage/SDL_ngageevents.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngageevents_c.h b/src/video/ngage/SDL_ngageevents_c.h index b67c93cb3618b..46fa908818d9d 100644 --- a/src/video/ngage/SDL_ngageevents_c.h +++ b/src/video/ngage/SDL_ngageevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngageframebuffer.cpp b/src/video/ngage/SDL_ngageframebuffer.cpp index bc4612a77512e..1140eb5166fb1 100644 --- a/src/video/ngage/SDL_ngageframebuffer.cpp +++ b/src/video/ngage/SDL_ngageframebuffer.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngageframebuffer_c.h b/src/video/ngage/SDL_ngageframebuffer_c.h index 861c01402beb0..e465eed2d5aae 100644 --- a/src/video/ngage/SDL_ngageframebuffer_c.h +++ b/src/video/ngage/SDL_ngageframebuffer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngagevideo.cpp b/src/video/ngage/SDL_ngagevideo.cpp index 5d30d42259154..1eff11e5d8550 100644 --- a/src/video/ngage/SDL_ngagevideo.cpp +++ b/src/video/ngage/SDL_ngagevideo.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngagevideo.h b/src/video/ngage/SDL_ngagevideo.h index 0d51b24a9aedf..77252e1446247 100644 --- a/src/video/ngage/SDL_ngagevideo.h +++ b/src/video/ngage/SDL_ngagevideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngagewindow.cpp b/src/video/ngage/SDL_ngagewindow.cpp index 44296e1f00552..57df58c0ce1e8 100644 --- a/src/video/ngage/SDL_ngagewindow.cpp +++ b/src/video/ngage/SDL_ngagewindow.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ngage/SDL_ngagewindow.h b/src/video/ngage/SDL_ngagewindow.h index 58d4d97d49868..39b6c5b5322da 100644 --- a/src/video/ngage/SDL_ngagewindow.h +++ b/src/video/ngage/SDL_ngagewindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenevents.c b/src/video/offscreen/SDL_offscreenevents.c index 28b4453d8cdb2..ce8b50c4b46d5 100644 --- a/src/video/offscreen/SDL_offscreenevents.c +++ b/src/video/offscreen/SDL_offscreenevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenevents_c.h b/src/video/offscreen/SDL_offscreenevents_c.h index 80c8011aa449c..f1d59359a4181 100644 --- a/src/video/offscreen/SDL_offscreenevents_c.h +++ b/src/video/offscreen/SDL_offscreenevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c index 6ca61316f0266..76fa8b72774b7 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer.c +++ b/src/video/offscreen/SDL_offscreenframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenframebuffer_c.h b/src/video/offscreen/SDL_offscreenframebuffer_c.h index 7d50989ad18e6..5b446189a3afd 100644 --- a/src/video/offscreen/SDL_offscreenframebuffer_c.h +++ b/src/video/offscreen/SDL_offscreenframebuffer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenopengles.c b/src/video/offscreen/SDL_offscreenopengles.c index 3786d54086a5c..98601f1f88226 100644 --- a/src/video/offscreen/SDL_offscreenopengles.c +++ b/src/video/offscreen/SDL_offscreenopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenopengles.h b/src/video/offscreen/SDL_offscreenopengles.h index f3bd5c3c75b9f..280880f22782a 100644 --- a/src/video/offscreen/SDL_offscreenopengles.h +++ b/src/video/offscreen/SDL_offscreenopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenvideo.c b/src/video/offscreen/SDL_offscreenvideo.c index 8c24aa215d19b..e4d3148a0d2bf 100644 --- a/src/video/offscreen/SDL_offscreenvideo.c +++ b/src/video/offscreen/SDL_offscreenvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenvideo.h b/src/video/offscreen/SDL_offscreenvideo.h index 8c9c369b0807d..2a998a0d156fc 100644 --- a/src/video/offscreen/SDL_offscreenvideo.h +++ b/src/video/offscreen/SDL_offscreenvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenwindow.c b/src/video/offscreen/SDL_offscreenwindow.c index 2c67d17ccc8ec..5950d0c380409 100644 --- a/src/video/offscreen/SDL_offscreenwindow.c +++ b/src/video/offscreen/SDL_offscreenwindow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/offscreen/SDL_offscreenwindow.h b/src/video/offscreen/SDL_offscreenwindow.h index 488d514a44505..a01880395853b 100644 --- a/src/video/offscreen/SDL_offscreenwindow.h +++ b/src/video/offscreen/SDL_offscreenwindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ps2/SDL_ps2video.c b/src/video/ps2/SDL_ps2video.c index 273e97784f84b..ce1ea0ca326d5 100644 --- a/src/video/ps2/SDL_ps2video.c +++ b/src/video/ps2/SDL_ps2video.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/ps2/SDL_ps2video.h b/src/video/ps2/SDL_ps2video.h index ef255736f3fef..91d8a80466524 100644 --- a/src/video/ps2/SDL_ps2video.h +++ b/src/video/ps2/SDL_ps2video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspevents.c b/src/video/psp/SDL_pspevents.c index 451d621d63593..8cec093fec4f6 100644 --- a/src/video/psp/SDL_pspevents.c +++ b/src/video/psp/SDL_pspevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspevents_c.h b/src/video/psp/SDL_pspevents_c.h index 76739678bbb27..8d41581b280d2 100644 --- a/src/video/psp/SDL_pspevents_c.h +++ b/src/video/psp/SDL_pspevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspgl.c b/src/video/psp/SDL_pspgl.c index 5800648004dab..8d64c430f9826 100644 --- a/src/video/psp/SDL_pspgl.c +++ b/src/video/psp/SDL_pspgl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspgl_c.h b/src/video/psp/SDL_pspgl_c.h index eea46f25e5dc4..72fb62790d4d9 100644 --- a/src/video/psp/SDL_pspgl_c.h +++ b/src/video/psp/SDL_pspgl_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspmouse.c b/src/video/psp/SDL_pspmouse.c index a59091d319dd0..42ec898eb6b84 100644 --- a/src/video/psp/SDL_pspmouse.c +++ b/src/video/psp/SDL_pspmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspmouse_c.h b/src/video/psp/SDL_pspmouse_c.h index 3742738adcab7..a961232b55ab9 100644 --- a/src/video/psp/SDL_pspmouse_c.h +++ b/src/video/psp/SDL_pspmouse_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 95d0d387c2fcd..71542256f04b2 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/psp/SDL_pspvideo.h b/src/video/psp/SDL_pspvideo.h index 28fd92127be94..50de4bca8a759 100644 --- a/src/video/psp/SDL_pspvideo.h +++ b/src/video/psp/SDL_pspvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpievents.c b/src/video/raspberry/SDL_rpievents.c index a6b9b2dff79b1..e592808ef535a 100644 --- a/src/video/raspberry/SDL_rpievents.c +++ b/src/video/raspberry/SDL_rpievents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpievents_c.h b/src/video/raspberry/SDL_rpievents_c.h index 5bdd916354573..737e4c9ece3e2 100644 --- a/src/video/raspberry/SDL_rpievents_c.h +++ b/src/video/raspberry/SDL_rpievents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index 1bd8f839b7858..6999cdb91485c 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpimouse.h b/src/video/raspberry/SDL_rpimouse.h index dc31b1709ccae..074b6e189918a 100644 --- a/src/video/raspberry/SDL_rpimouse.h +++ b/src/video/raspberry/SDL_rpimouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpiopengles.c b/src/video/raspberry/SDL_rpiopengles.c index 0bb530e63fc11..6d5718eb6bbde 100644 --- a/src/video/raspberry/SDL_rpiopengles.c +++ b/src/video/raspberry/SDL_rpiopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpiopengles.h b/src/video/raspberry/SDL_rpiopengles.h index 209d80e125961..93fcc01199619 100644 --- a/src/video/raspberry/SDL_rpiopengles.h +++ b/src/video/raspberry/SDL_rpiopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 25efc514cf3a6..d3b42285fac9b 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/raspberry/SDL_rpivideo.h b/src/video/raspberry/SDL_rpivideo.h index d2904508cdd26..ee0b612b7d309 100644 --- a/src/video/raspberry/SDL_rpivideo.h +++ b/src/video/raspberry/SDL_rpivideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosdefs.h b/src/video/riscos/SDL_riscosdefs.h index 9817d16cc2a34..890d61be87853 100644 --- a/src/video/riscos/SDL_riscosdefs.h +++ b/src/video/riscos/SDL_riscosdefs.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosevents.c b/src/video/riscos/SDL_riscosevents.c index 18d8fde1c1617..ab530115dd22e 100644 --- a/src/video/riscos/SDL_riscosevents.c +++ b/src/video/riscos/SDL_riscosevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosevents_c.h b/src/video/riscos/SDL_riscosevents_c.h index 2bc272ba05737..2a62ccfc1c1fc 100644 --- a/src/video/riscos/SDL_riscosevents_c.h +++ b/src/video/riscos/SDL_riscosevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c index 9a884c86f5512..bf03bc11a9d1a 100644 --- a/src/video/riscos/SDL_riscosframebuffer.c +++ b/src/video/riscos/SDL_riscosframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosframebuffer_c.h b/src/video/riscos/SDL_riscosframebuffer_c.h index 926b76a619288..daa51328adfb3 100644 --- a/src/video/riscos/SDL_riscosframebuffer_c.h +++ b/src/video/riscos/SDL_riscosframebuffer_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmessagebox.c b/src/video/riscos/SDL_riscosmessagebox.c index 223ef8d7a1426..054199d7d9216 100644 --- a/src/video/riscos/SDL_riscosmessagebox.c +++ b/src/video/riscos/SDL_riscosmessagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmessagebox.h b/src/video/riscos/SDL_riscosmessagebox.h index ef16f392aabbc..dcdf36e6f3ff9 100644 --- a/src/video/riscos/SDL_riscosmessagebox.h +++ b/src/video/riscos/SDL_riscosmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmodes.c b/src/video/riscos/SDL_riscosmodes.c index eb0aa4bc60571..8640163f94a1c 100644 --- a/src/video/riscos/SDL_riscosmodes.c +++ b/src/video/riscos/SDL_riscosmodes.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmodes.h b/src/video/riscos/SDL_riscosmodes.h index e3600974518ab..1307e6028a57d 100644 --- a/src/video/riscos/SDL_riscosmodes.h +++ b/src/video/riscos/SDL_riscosmodes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmouse.c b/src/video/riscos/SDL_riscosmouse.c index de31bcdcf4478..32f5d251a3a83 100644 --- a/src/video/riscos/SDL_riscosmouse.c +++ b/src/video/riscos/SDL_riscosmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosmouse.h b/src/video/riscos/SDL_riscosmouse.h index 02c1e3ed36f72..a71e6558d05a3 100644 --- a/src/video/riscos/SDL_riscosmouse.h +++ b/src/video/riscos/SDL_riscosmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c index 399d6ce078508..398628a24ed8e 100644 --- a/src/video/riscos/SDL_riscosvideo.c +++ b/src/video/riscos/SDL_riscosvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscosvideo.h b/src/video/riscos/SDL_riscosvideo.h index 190afa97f2cc1..986bcc2ff17b4 100644 --- a/src/video/riscos/SDL_riscosvideo.h +++ b/src/video/riscos/SDL_riscosvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c index aceb378a2c462..eaacffe3445ca 100644 --- a/src/video/riscos/SDL_riscoswindow.c +++ b/src/video/riscos/SDL_riscoswindow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/SDL_riscoswindow.h b/src/video/riscos/SDL_riscoswindow.h index 46adc3a97d271..a692f747594d1 100644 --- a/src/video/riscos/SDL_riscoswindow.h +++ b/src/video/riscos/SDL_riscoswindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/riscos/scancodes_riscos.h b/src/video/riscos/scancodes_riscos.h index 3895c99e413c2..8dfe14360a8bb 100644 --- a/src/video/riscos/scancodes_riscos.h +++ b/src/video/riscos/scancodes_riscos.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/sdlgenblit.pl b/src/video/sdlgenblit.pl index 1db1ae51a26b3..ad260d29e73fd 100755 --- a/src/video/sdlgenblit.pl +++ b/src/video/sdlgenblit.pl @@ -92,7 +92,7 @@ sub open_file { /* DO NOT EDIT! This file is generated by sdlgenblit.pl */ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitappdelegate.h b/src/video/uikit/SDL_uikitappdelegate.h index e13e6c096525a..c52594dcf8a72 100644 --- a/src/video/uikit/SDL_uikitappdelegate.h +++ b/src/video/uikit/SDL_uikitappdelegate.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 8a4c0e4605b59..d8c3a9e0c2081 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitclipboard.h b/src/video/uikit/SDL_uikitclipboard.h index cb86efdd51d50..584f35235d674 100644 --- a/src/video/uikit/SDL_uikitclipboard.h +++ b/src/video/uikit/SDL_uikitclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitclipboard.m b/src/video/uikit/SDL_uikitclipboard.m index 589c55edf6cee..cc5a757c43268 100644 --- a/src/video/uikit/SDL_uikitclipboard.m +++ b/src/video/uikit/SDL_uikitclipboard.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitevents.h b/src/video/uikit/SDL_uikitevents.h index 82bccad621272..08c6cbcc65a43 100644 --- a/src/video/uikit/SDL_uikitevents.h +++ b/src/video/uikit/SDL_uikitevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitevents.m b/src/video/uikit/SDL_uikitevents.m index be3384833b910..00af2cc422519 100644 --- a/src/video/uikit/SDL_uikitevents.m +++ b/src/video/uikit/SDL_uikitevents.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmessagebox.h b/src/video/uikit/SDL_uikitmessagebox.h index 38c90b5ae97d7..7930ab26e7b27 100644 --- a/src/video/uikit/SDL_uikitmessagebox.h +++ b/src/video/uikit/SDL_uikitmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index e7d80ef7679df..55b69b31ce9f8 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmetalview.h b/src/video/uikit/SDL_uikitmetalview.h index b6c7a4ce443f9..1bfde5363652f 100644 --- a/src/video/uikit/SDL_uikitmetalview.h +++ b/src/video/uikit/SDL_uikitmetalview.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index accda70361c36..a8d34d49f608d 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmodes.h b/src/video/uikit/SDL_uikitmodes.h index b92f19011f462..a71713972cd3a 100644 --- a/src/video/uikit/SDL_uikitmodes.h +++ b/src/video/uikit/SDL_uikitmodes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index e397e97a68aa6..9d0f479c317e1 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitopengles.h b/src/video/uikit/SDL_uikitopengles.h index 3e280df73201e..27f9f43104dbd 100644 --- a/src/video/uikit/SDL_uikitopengles.h +++ b/src/video/uikit/SDL_uikitopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 15163f9936afa..e1e82e036d88d 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index bad1b2eefb4fc..48a51cd95aa3b 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 345c933c827f3..965a86d89452e 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h index f13822299743b..4022cfbb1321f 100644 --- a/src/video/uikit/SDL_uikitvideo.h +++ b/src/video/uikit/SDL_uikitvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 22f5251fd1ca7..99cffbac624ba 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 9fe1686460ba7..2e239ae745dfe 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index e3c92156c6128..b159cca0e0803 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index ddb634e1d0001..5c18876938d84 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/src/video/uikit/SDL_uikitviewcontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 7dc1abeeb42eb..f1594ed740178 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitvulkan.h b/src/video/uikit/SDL_uikitvulkan.h index 540ccca468713..385fdfc02f1ea 100644 --- a/src/video/uikit/SDL_uikitvulkan.h +++ b/src/video/uikit/SDL_uikitvulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m index a8816a4eb62fe..f2d00220ffca9 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index d6998498ce28e..4daad157ef9bb 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 8f515e10c72e5..e786ffc146a02 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitaframebuffer.c b/src/video/vita/SDL_vitaframebuffer.c index 7fb566727b7e9..07d06e9d70929 100644 --- a/src/video/vita/SDL_vitaframebuffer.c +++ b/src/video/vita/SDL_vitaframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitaframebuffer.h b/src/video/vita/SDL_vitaframebuffer.h index eda9b59900607..0502dbf2fefce 100644 --- a/src/video/vita/SDL_vitaframebuffer.h +++ b/src/video/vita/SDL_vitaframebuffer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagl_pvr.c b/src/video/vita/SDL_vitagl_pvr.c index 6e34054a9e6b4..a35a94c63e0a3 100644 --- a/src/video/vita/SDL_vitagl_pvr.c +++ b/src/video/vita/SDL_vitagl_pvr.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagl_pvr_c.h b/src/video/vita/SDL_vitagl_pvr_c.h index 99aceadad03d5..2b9444c6a651d 100644 --- a/src/video/vita/SDL_vitagl_pvr_c.h +++ b/src/video/vita/SDL_vitagl_pvr_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagles.c b/src/video/vita/SDL_vitagles.c index f058c37497d67..da3b6fea33434 100644 --- a/src/video/vita/SDL_vitagles.c +++ b/src/video/vita/SDL_vitagles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagles_c.h b/src/video/vita/SDL_vitagles_c.h index 36885982fc0ba..d2e89a2b3feec 100644 --- a/src/video/vita/SDL_vitagles_c.h +++ b/src/video/vita/SDL_vitagles_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagles_pvr.c b/src/video/vita/SDL_vitagles_pvr.c index 71cd5d92f2a65..c79c29ccb7b1a 100644 --- a/src/video/vita/SDL_vitagles_pvr.c +++ b/src/video/vita/SDL_vitagles_pvr.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitagles_pvr_c.h b/src/video/vita/SDL_vitagles_pvr_c.h index afe60f3b4a89d..d738e1da6f7b4 100644 --- a/src/video/vita/SDL_vitagles_pvr_c.h +++ b/src/video/vita/SDL_vitagles_pvr_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitakeyboard.c b/src/video/vita/SDL_vitakeyboard.c index 106100a8073aa..255c916c898cf 100644 --- a/src/video/vita/SDL_vitakeyboard.c +++ b/src/video/vita/SDL_vitakeyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitakeyboard.h b/src/video/vita/SDL_vitakeyboard.h index 2ef712664772e..d5fa224f7a78e 100644 --- a/src/video/vita/SDL_vitakeyboard.h +++ b/src/video/vita/SDL_vitakeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitamessagebox.c b/src/video/vita/SDL_vitamessagebox.c index 63bf89e38322b..0e8580f8deae2 100644 --- a/src/video/vita/SDL_vitamessagebox.c +++ b/src/video/vita/SDL_vitamessagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitamessagebox.h b/src/video/vita/SDL_vitamessagebox.h index 87c4bda96c5b4..d8f5aadbc6da4 100644 --- a/src/video/vita/SDL_vitamessagebox.h +++ b/src/video/vita/SDL_vitamessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitamouse.c b/src/video/vita/SDL_vitamouse.c index 1030adaa671aa..836d33ee4a273 100644 --- a/src/video/vita/SDL_vitamouse.c +++ b/src/video/vita/SDL_vitamouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitamouse_c.h b/src/video/vita/SDL_vitamouse_c.h index 096fc053dbbf8..8efb8c0f68bd1 100644 --- a/src/video/vita/SDL_vitamouse_c.h +++ b/src/video/vita/SDL_vitamouse_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitatouch.c b/src/video/vita/SDL_vitatouch.c index 58c2d5f79378e..ae13c6d4940b9 100644 --- a/src/video/vita/SDL_vitatouch.c +++ b/src/video/vita/SDL_vitatouch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitatouch.h b/src/video/vita/SDL_vitatouch.h index 2fc1fb06e985f..5986f8dce9dd1 100644 --- a/src/video/vita/SDL_vitatouch.h +++ b/src/video/vita/SDL_vitatouch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 8c0fad1eaafb2..bdb06e990588c 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vita/SDL_vitavideo.h b/src/video/vita/SDL_vitavideo.h index fc62aec2f73a5..8f609425cfb88 100644 --- a/src/video/vita/SDL_vitavideo.h +++ b/src/video/vita/SDL_vitavideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivanteopengles.c b/src/video/vivante/SDL_vivanteopengles.c index fcca0cd8f9bd8..67c78e3e92548 100644 --- a/src/video/vivante/SDL_vivanteopengles.c +++ b/src/video/vivante/SDL_vivanteopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivanteopengles.h b/src/video/vivante/SDL_vivanteopengles.h index ab75465a1d209..b73e3c4c64061 100644 --- a/src/video/vivante/SDL_vivanteopengles.h +++ b/src/video/vivante/SDL_vivanteopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivanteplatform.c b/src/video/vivante/SDL_vivanteplatform.c index 7d966724ad9e3..3ba8c7ddc50d5 100644 --- a/src/video/vivante/SDL_vivanteplatform.c +++ b/src/video/vivante/SDL_vivanteplatform.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivanteplatform.h b/src/video/vivante/SDL_vivanteplatform.h index a3cf24aa08ce7..8831e17596b43 100644 --- a/src/video/vivante/SDL_vivanteplatform.h +++ b/src/video/vivante/SDL_vivanteplatform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index 3a6f56e16218f..ac570bc381eab 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivantevideo.h b/src/video/vivante/SDL_vivantevideo.h index 6bb9985dd9113..bf8d694f24b97 100644 --- a/src/video/vivante/SDL_vivantevideo.h +++ b/src/video/vivante/SDL_vivantevideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c index 29416e6032064..cc99edcf2ad27 100644 --- a/src/video/vivante/SDL_vivantevulkan.c +++ b/src/video/vivante/SDL_vivantevulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/vivante/SDL_vivantevulkan.h b/src/video/vivante/SDL_vivantevulkan.h index 5a0fa9133a4d4..9aa566b20ee26 100644 --- a/src/video/vivante/SDL_vivantevulkan.h +++ b/src/video/vivante/SDL_vivantevulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c index 097852e8f9990..c3e23b7808c97 100644 --- a/src/video/wayland/SDL_waylandclipboard.c +++ b/src/video/wayland/SDL_waylandclipboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandclipboard.h b/src/video/wayland/SDL_waylandclipboard.h index 007fb791ed39d..0209a9bd622d1 100644 --- a/src/video/wayland/SDL_waylandclipboard.h +++ b/src/video/wayland/SDL_waylandclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 9d9808e659a19..eea8c3200d412 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylanddatamanager.h b/src/video/wayland/SDL_waylanddatamanager.h index 1ffaf730f2c21..19fbc004eed6c 100644 --- a/src/video/wayland/SDL_waylanddatamanager.h +++ b/src/video/wayland/SDL_waylanddatamanager.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylanddyn.c b/src/video/wayland/SDL_waylanddyn.c index 7d4dce5c8a1e1..e6021f08cbc29 100644 --- a/src/video/wayland/SDL_waylanddyn.c +++ b/src/video/wayland/SDL_waylanddyn.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylanddyn.h b/src/video/wayland/SDL_waylanddyn.h index 76cfb295c9fca..e674ab8a8b97b 100644 --- a/src/video/wayland/SDL_waylanddyn.h +++ b/src/video/wayland/SDL_waylanddyn.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 096e357b38f28..0dbc8555470b3 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 0d4e66ec5e816..5bd061a25c752 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandkeyboard.c b/src/video/wayland/SDL_waylandkeyboard.c index 17dc4f867e8c5..0e903e2178a3d 100644 --- a/src/video/wayland/SDL_waylandkeyboard.c +++ b/src/video/wayland/SDL_waylandkeyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandkeyboard.h b/src/video/wayland/SDL_waylandkeyboard.h index e8c3ded8ab2fb..4a20ea26ab51e 100644 --- a/src/video/wayland/SDL_waylandkeyboard.h +++ b/src/video/wayland/SDL_waylandkeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandmessagebox.c b/src/video/wayland/SDL_waylandmessagebox.c index 2af96ddec7934..436a860336eb3 100644 --- a/src/video/wayland/SDL_waylandmessagebox.c +++ b/src/video/wayland/SDL_waylandmessagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandmessagebox.h b/src/video/wayland/SDL_waylandmessagebox.h index 5472c8e683133..28817f12f03fd 100644 --- a/src/video/wayland/SDL_waylandmessagebox.h +++ b/src/video/wayland/SDL_waylandmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 11ab35cad30e1..1efb480880171 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandmouse.h b/src/video/wayland/SDL_waylandmouse.h index 0f63d11e48e98..f912455c56aa0 100644 --- a/src/video/wayland/SDL_waylandmouse.h +++ b/src/video/wayland/SDL_waylandmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c index f67d9525852cc..2b83fc3bf8de3 100644 --- a/src/video/wayland/SDL_waylandopengles.c +++ b/src/video/wayland/SDL_waylandopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandopengles.h b/src/video/wayland/SDL_waylandopengles.h index 98968863c9b8d..97dae93fe85f6 100644 --- a/src/video/wayland/SDL_waylandopengles.h +++ b/src/video/wayland/SDL_waylandopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h index bc178d014cc78..4d815c6343e1c 100644 --- a/src/video/wayland/SDL_waylandsym.h +++ b/src/video/wayland/SDL_waylandsym.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 81e48fbb707a2..b29cd3754f909 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index 461a2395bf30c..4691ae6e9cc71 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index a82a5fd9e2925..9fcd575b44c26 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandvulkan.h b/src/video/wayland/SDL_waylandvulkan.h index c3ba76dc2c250..e154d1a0ac82a 100644 --- a/src/video/wayland/SDL_waylandvulkan.h +++ b/src/video/wayland/SDL_waylandvulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 288ec96dd21b1..b7a3ce0bf297e 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index f3d1dd4bae4a4..f7f5037175b2b 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_msctf.h b/src/video/windows/SDL_msctf.h index 5f6829a0715ae..738696f017e9e 100644 --- a/src/video/windows/SDL_msctf.h +++ b/src/video/windows/SDL_msctf.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsclipboard.c b/src/video/windows/SDL_windowsclipboard.c index 8a1e4a4271281..b9c788af1f8d6 100644 --- a/src/video/windows/SDL_windowsclipboard.c +++ b/src/video/windows/SDL_windowsclipboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsclipboard.h b/src/video/windows/SDL_windowsclipboard.h index 17039806e1dc2..5606ef865a74a 100644 --- a/src/video/windows/SDL_windowsclipboard.h +++ b/src/video/windows/SDL_windowsclipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 166053244f6cf..9f0d7f3696941 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsevents.h b/src/video/windows/SDL_windowsevents.h index 12475a3ee8e0e..414019ba9b581 100644 --- a/src/video/windows/SDL_windowsevents.h +++ b/src/video/windows/SDL_windowsevents.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsframebuffer.c b/src/video/windows/SDL_windowsframebuffer.c index d2047577991ca..bdc7fe0fce743 100644 --- a/src/video/windows/SDL_windowsframebuffer.c +++ b/src/video/windows/SDL_windowsframebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsframebuffer.h b/src/video/windows/SDL_windowsframebuffer.h index e9ed44100bd08..5de8e8fc09f23 100644 --- a/src/video/windows/SDL_windowsframebuffer.h +++ b/src/video/windows/SDL_windowsframebuffer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index 9c5db83ee1052..633fe67668484 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowskeyboard.h b/src/video/windows/SDL_windowskeyboard.h index 777bc40e33836..76f8233e3085b 100644 --- a/src/video/windows/SDL_windowskeyboard.h +++ b/src/video/windows/SDL_windowskeyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmessagebox.c b/src/video/windows/SDL_windowsmessagebox.c index 19b48f24c4be2..82aca552b7e90 100644 --- a/src/video/windows/SDL_windowsmessagebox.c +++ b/src/video/windows/SDL_windowsmessagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmessagebox.h b/src/video/windows/SDL_windowsmessagebox.h index 41b5cc7265d16..fa2330e275e22 100644 --- a/src/video/windows/SDL_windowsmessagebox.h +++ b/src/video/windows/SDL_windowsmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index 8f01bf0060ab1..8048359021aa5 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmodes.h b/src/video/windows/SDL_windowsmodes.h index 31a76026cb857..8e2a3a2c4cbd5 100644 --- a/src/video/windows/SDL_windowsmodes.h +++ b/src/video/windows/SDL_windowsmodes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 9f0e6d2dccda6..4ff7950406c1e 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsmouse.h b/src/video/windows/SDL_windowsmouse.h index 3c3788238dabd..50c503279399c 100644 --- a/src/video/windows/SDL_windowsmouse.h +++ b/src/video/windows/SDL_windowsmouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 5846b26aec0fa..d7bc3146be619 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h index 4597d8ee3af90..9780f664fcabd 100644 --- a/src/video/windows/SDL_windowsopengl.h +++ b/src/video/windows/SDL_windowsopengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index ac5dbc0463a31..7847b904b0474 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsopengles.h b/src/video/windows/SDL_windowsopengles.h index 4cd8af41dda57..5a40f777f50a4 100644 --- a/src/video/windows/SDL_windowsopengles.h +++ b/src/video/windows/SDL_windowsopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 793eb4ba404ea..1080a6a75e45e 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index b5a380038d3df..925e4b2e3dc2c 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c index 5a632421c8962..b2eee2b56e70c 100644 --- a/src/video/windows/SDL_windowsvulkan.c +++ b/src/video/windows/SDL_windowsvulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowsvulkan.h b/src/video/windows/SDL_windowsvulkan.h index 95e6c12ae4a57..088e204148e4d 100644 --- a/src/video/windows/SDL_windowsvulkan.h +++ b/src/video/windows/SDL_windowsvulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 78f6aeaff00fd..980fedb0ff60c 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 0b6ceb92da755..ab8ab48522bf0 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/windows/wmmsg.h b/src/video/windows/wmmsg.h index cefe91096c1a3..2e1571dcebbcf 100644 --- a/src/video/windows/wmmsg.h +++ b/src/video/windows/wmmsg.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtevents.cpp b/src/video/winrt/SDL_winrtevents.cpp index 2b7e3ff8dcd75..0a4cdaaba43ed 100644 --- a/src/video/winrt/SDL_winrtevents.cpp +++ b/src/video/winrt/SDL_winrtevents.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h index 72de3bb8fd2a5..e77e37d90e901 100644 --- a/src/video/winrt/SDL_winrtevents_c.h +++ b/src/video/winrt/SDL_winrtevents_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtgamebar.cpp b/src/video/winrt/SDL_winrtgamebar.cpp index 00f777a5c3f00..63d27b6e080f2 100644 --- a/src/video/winrt/SDL_winrtgamebar.cpp +++ b/src/video/winrt/SDL_winrtgamebar.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtgamebar_cpp.h b/src/video/winrt/SDL_winrtgamebar_cpp.h index 6cadd11ca1a6a..51c54628c0b25 100644 --- a/src/video/winrt/SDL_winrtgamebar_cpp.h +++ b/src/video/winrt/SDL_winrtgamebar_cpp.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index 4a62b0186ce10..b1aa6b0363b20 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtmessagebox.cpp b/src/video/winrt/SDL_winrtmessagebox.cpp index aeedc92dcec24..bee890095670b 100644 --- a/src/video/winrt/SDL_winrtmessagebox.cpp +++ b/src/video/winrt/SDL_winrtmessagebox.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtmessagebox.h b/src/video/winrt/SDL_winrtmessagebox.h index 8786eb26a9a40..865ce32908a2a 100644 --- a/src/video/winrt/SDL_winrtmessagebox.h +++ b/src/video/winrt/SDL_winrtmessagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtmouse.cpp b/src/video/winrt/SDL_winrtmouse.cpp index b46c889858225..d16aa01d2ebb1 100644 --- a/src/video/winrt/SDL_winrtmouse.cpp +++ b/src/video/winrt/SDL_winrtmouse.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtmouse_c.h b/src/video/winrt/SDL_winrtmouse_c.h index 1a5438415b8eb..61deedf31738c 100644 --- a/src/video/winrt/SDL_winrtmouse_c.h +++ b/src/video/winrt/SDL_winrtmouse_c.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 52a1ef5b9bc5e..4dfba50eef346 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtopengles.h b/src/video/winrt/SDL_winrtopengles.h index eaebadf553e77..0b00f176d189b 100644 --- a/src/video/winrt/SDL_winrtopengles.h +++ b/src/video/winrt/SDL_winrtopengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp index ade322aa8df52..47dd3c255006b 100644 --- a/src/video/winrt/SDL_winrtpointerinput.cpp +++ b/src/video/winrt/SDL_winrtpointerinput.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index a48359e48766d..b2b307f2a69f1 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h index e8b8c3d47613c..55edc9a686483 100644 --- a/src/video/winrt/SDL_winrtvideo_cpp.h +++ b/src/video/winrt/SDL_winrtvideo_cpp.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11clipboard.c b/src/video/x11/SDL_x11clipboard.c index 708d01d10589d..4ebeb78308995 100644 --- a/src/video/x11/SDL_x11clipboard.c +++ b/src/video/x11/SDL_x11clipboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11clipboard.h b/src/video/x11/SDL_x11clipboard.h index 1a7ce11ebc8f9..2d9c0f1518128 100644 --- a/src/video/x11/SDL_x11clipboard.h +++ b/src/video/x11/SDL_x11clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11dyn.c b/src/video/x11/SDL_x11dyn.c index 5b8a226b927f6..0ae1c5a94a0ba 100644 --- a/src/video/x11/SDL_x11dyn.c +++ b/src/video/x11/SDL_x11dyn.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11dyn.h b/src/video/x11/SDL_x11dyn.h index 610e12bc2fa0a..73d8953e8fa36 100644 --- a/src/video/x11/SDL_x11dyn.h +++ b/src/video/x11/SDL_x11dyn.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 7906c12dfd5f9..56a78c7fc332b 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index 4aadd290bf8d7..4863a2435aa9b 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11framebuffer.c b/src/video/x11/SDL_x11framebuffer.c index 6714a1febbfc6..1d3a3e66599b4 100644 --- a/src/video/x11/SDL_x11framebuffer.c +++ b/src/video/x11/SDL_x11framebuffer.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11framebuffer.h b/src/video/x11/SDL_x11framebuffer.h index 8362346285d72..582cbddb164ac 100644 --- a/src/video/x11/SDL_x11framebuffer.h +++ b/src/video/x11/SDL_x11framebuffer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11keyboard.c b/src/video/x11/SDL_x11keyboard.c index cf2d4c7eec283..6f4851f568b10 100644 --- a/src/video/x11/SDL_x11keyboard.c +++ b/src/video/x11/SDL_x11keyboard.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11keyboard.h b/src/video/x11/SDL_x11keyboard.h index 45ab01dc06dfa..9164e04ec0918 100644 --- a/src/video/x11/SDL_x11keyboard.h +++ b/src/video/x11/SDL_x11keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index 2367b94496e3f..b1f8ab048e1ff 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11messagebox.h b/src/video/x11/SDL_x11messagebox.h index 05802ed3df3ba..f0ecce0f1a9f1 100644 --- a/src/video/x11/SDL_x11messagebox.h +++ b/src/video/x11/SDL_x11messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 0c2812831333e..3ba4f60498806 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11modes.h b/src/video/x11/SDL_x11modes.h index 8d0e341fb11ff..070af28008173 100644 --- a/src/video/x11/SDL_x11modes.h +++ b/src/video/x11/SDL_x11modes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index a9199815202ec..b87416ada3cc8 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11mouse.h b/src/video/x11/SDL_x11mouse.h index 902f9b7791d9c..bbe61eb57edd7 100644 --- a/src/video/x11/SDL_x11mouse.h +++ b/src/video/x11/SDL_x11mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 1d5edd895fe03..f4abb6959d9a7 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2021 NVIDIA Corporation This software is provided 'as-is', without any express or implied diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index 70840231c7a7d..240081f746e5c 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c index 0a2b5831a7217..5bd277d5fdf98 100644 --- a/src/video/x11/SDL_x11opengles.c +++ b/src/video/x11/SDL_x11opengles.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11opengles.h b/src/video/x11/SDL_x11opengles.h index a4237b5edb343..d6158581d0aa7 100644 --- a/src/video/x11/SDL_x11opengles.h +++ b/src/video/x11/SDL_x11opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11pen.c b/src/video/x11/SDL_x11pen.c index e2af7fc7bfd51..61ad579a33e25 100644 --- a/src/video/x11/SDL_x11pen.c +++ b/src/video/x11/SDL_x11pen.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11pen.h b/src/video/x11/SDL_x11pen.h index 04de528c879e5..ebb7847d803a2 100644 --- a/src/video/x11/SDL_x11pen.h +++ b/src/video/x11/SDL_x11pen.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 001633a5e2683..78436c1f94e72 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11touch.c b/src/video/x11/SDL_x11touch.c index 681e9d9c4beed..9b2a86ce365fb 100644 --- a/src/video/x11/SDL_x11touch.c +++ b/src/video/x11/SDL_x11touch.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11touch.h b/src/video/x11/SDL_x11touch.h index 93f66a879dcb1..2343faa5b4163 100644 --- a/src/video/x11/SDL_x11touch.h +++ b/src/video/x11/SDL_x11touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index c985427deba82..5a7ad268cb4b3 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 09efd645e504b..e199dd51692e4 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c index 9b9917bf6f302..e92b5928f1666 100644 --- a/src/video/x11/SDL_x11vulkan.c +++ b/src/video/x11/SDL_x11vulkan.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11vulkan.h b/src/video/x11/SDL_x11vulkan.h index e26727e5505a9..2c81a33a705c5 100644 --- a/src/video/x11/SDL_x11vulkan.h +++ b/src/video/x11/SDL_x11vulkan.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index ddb8f26aa6ea7..7e95621ca5ae8 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 5d1926187baa2..84d92e59168d9 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11xfixes.c b/src/video/x11/SDL_x11xfixes.c index 28ea7a6adb80a..0f620995b7f95 100644 --- a/src/video/x11/SDL_x11xfixes.c +++ b/src/video/x11/SDL_x11xfixes.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11xfixes.h b/src/video/x11/SDL_x11xfixes.h index 2c92794508b34..c1daf4d3e6dcd 100644 --- a/src/video/x11/SDL_x11xfixes.h +++ b/src/video/x11/SDL_x11xfixes.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index 4e8710c83929b..346130a34fb7f 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/video/x11/SDL_x11xinput2.h b/src/video/x11/SDL_x11xinput2.h index 4fea6465b4576..eba6cdf739f82 100644 --- a/src/video/x11/SDL_x11xinput2.h +++ b/src/video/x11/SDL_x11xinput2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/checkkeys.c b/test/checkkeys.c index 5d9ab3e44be72..a5a27ff31899a 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index dcb003cc35096..549244ce4afe2 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/gamepadutils.c b/test/gamepadutils.c index 01641ea3c6deb..656c9970a1439 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/gamepadutils.h b/test/gamepadutils.h index 77ebe1bcb58a0..31813529d4b12 100644 --- a/test/gamepadutils.h +++ b/test/gamepadutils.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/loopwave.c b/test/loopwave.c index 071d4cc979464..1aa627061d983 100644 --- a/test/loopwave.c +++ b/test/loopwave.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/pretest.c b/test/pretest.c index ab43685eef70a..66c2e36734a37 100644 --- a/test/pretest.c +++ b/test/pretest.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testatomic.c b/test/testatomic.c index 599730c9bd46c..84b41bf68b396 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testaudiocapture.c b/test/testaudiocapture.c index dfa22a73ca8a9..04ab2f0832baf 100644 --- a/test/testaudiocapture.c +++ b/test/testaudiocapture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testaudiohotplug.c b/test/testaudiohotplug.c index 72a562cfc067d..daac0f7f5826a 100644 --- a/test/testaudiohotplug.c +++ b/test/testaudiohotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testaudioinfo.c b/test/testaudioinfo.c index cb061db1af616..4ac371c011a37 100644 --- a/test/testaudioinfo.c +++ b/test/testaudioinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testaudiostreamdynamicresample.c b/test/testaudiostreamdynamicresample.c index 4e3b8fb0f88c4..b7b953abca2f0 100644 --- a/test/testaudiostreamdynamicresample.c +++ b/test/testaudiostreamdynamicresample.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testautomation.c b/test/testautomation.c index 40dda20c49474..bb691702b7853 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testautomation_images.c b/test/testautomation_images.c index 753324a82e1a9..f3c7b1e63cb2d 100644 --- a/test/testautomation_images.c +++ b/test/testautomation_images.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testautomation_images.h b/test/testautomation_images.h index a0b0f10812bf1..92b381e5996c6 100644 --- a/test/testautomation_images.h +++ b/test/testautomation_images.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testautomation_pen.c b/test/testautomation_pen.c index d9a6ef2a28890..d0c4508415e37 100644 --- a/test/testautomation_pen.c +++ b/test/testautomation_pen.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testbounds.c b/test/testbounds.c index cea2b229d4f88..143f74c6dc4d2 100644 --- a/test/testbounds.c +++ b/test/testbounds.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testcontroller.c b/test/testcontroller.c index 8c360972dad0e..bcd9c6be3514a 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index cbaaa06d37da3..91af2baef4c0c 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testdisplayinfo.c b/test/testdisplayinfo.c index f11764e48fbe0..0e45b54a808fd 100644 --- a/test/testdisplayinfo.c +++ b/test/testdisplayinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testdraw.c b/test/testdraw.c index eccb8cad4b770..d0d70c33b9e45 100644 --- a/test/testdraw.c +++ b/test/testdraw.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testdrawchessboard.c b/test/testdrawchessboard.c index e067c32995355..1388b044b6eff 100644 --- a/test/testdrawchessboard.c +++ b/test/testdrawchessboard.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testdropfile.c b/test/testdropfile.c index 9047a4a9d0abb..0c0bfca746cda 100644 --- a/test/testdropfile.c +++ b/test/testdropfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testerror.c b/test/testerror.c index 1f3830f12c45a..6792d7d444206 100644 --- a/test/testerror.c +++ b/test/testerror.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testevdev.c b/test/testevdev.c index fbc362b21e1f9..a991d48381db6 100644 --- a/test/testevdev.c +++ b/test/testevdev.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright (C) 2020-2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/test/testffmpeg.c b/test/testffmpeg.c index eadef4bd1c417..338063a8ceb33 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testffmpeg_videotoolbox.h b/test/testffmpeg_videotoolbox.h index 21242955cbca2..706ff77b1c0a3 100644 --- a/test/testffmpeg_videotoolbox.h +++ b/test/testffmpeg_videotoolbox.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testffmpeg_videotoolbox.m b/test/testffmpeg_videotoolbox.m index e7d580cae0fb8..4e7d98e69793d 100644 --- a/test/testffmpeg_videotoolbox.m +++ b/test/testffmpeg_videotoolbox.m @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testfile.c b/test/testfile.c index 157d6e8bec850..be04064bff859 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testfilesystem.c b/test/testfilesystem.c index 4792d563e4571..e1986698b033a 100644 --- a/test/testfilesystem.c +++ b/test/testfilesystem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testgeometry.c b/test/testgeometry.c index 46e5a5e341685..16d44ca576fad 100644 --- a/test/testgeometry.c +++ b/test/testgeometry.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testgl.c b/test/testgl.c index 0df67e73f9c14..d08a67e0823aa 100644 --- a/test/testgl.c +++ b/test/testgl.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testgles.c b/test/testgles.c index 4be391f99a1ba..36200e1005825 100644 --- a/test/testgles.c +++ b/test/testgles.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testgles2.c b/test/testgles2.c index ad4223c32cb70..af408eca87c54 100644 --- a/test/testgles2.c +++ b/test/testgles2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testgles2_sdf.c b/test/testgles2_sdf.c index 715ce718df6ca..7429aa06bda8e 100644 --- a/test/testgles2_sdf.c +++ b/test/testgles2_sdf.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testhittesting.c b/test/testhittesting.c index 03b83071e28cb..e65c2fa472202 100644 --- a/test/testhittesting.c +++ b/test/testhittesting.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testhotplug.c b/test/testhotplug.c index 82b389de953cc..434b18e85ca7b 100644 --- a/test/testhotplug.c +++ b/test/testhotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testiconv.c b/test/testiconv.c index 0fd5cfbfb2eaf..8bea7f589cd8e 100644 --- a/test/testiconv.c +++ b/test/testiconv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testime.c b/test/testime.c index 4e428a3e9ca74..7553014ed4f87 100644 --- a/test/testime.c +++ b/test/testime.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testintersections.c b/test/testintersections.c index 380c8e71026c6..126078fc71be6 100644 --- a/test/testintersections.c +++ b/test/testintersections.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testkeys.c b/test/testkeys.c index c64b09b2faf39..88f75050c9a14 100644 --- a/test/testkeys.c +++ b/test/testkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testloadso.c b/test/testloadso.c index 7a55f0a76e08a..fbd3fcc2b03de 100644 --- a/test/testloadso.c +++ b/test/testloadso.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testlocale.c b/test/testlocale.c index 8e7366bdb5f51..b2e0433452388 100644 --- a/test/testlocale.c +++ b/test/testlocale.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testlock.c b/test/testlock.c index 221bd4a708654..2437bd2776768 100644 --- a/test/testlock.c +++ b/test/testlock.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testmessage.c b/test/testmessage.c index 6723a6a7a4dab..056a1d5ea885c 100644 --- a/test/testmessage.c +++ b/test/testmessage.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testmouse.c b/test/testmouse.c index 18efbc0eb67b4..c92e162e72600 100644 --- a/test/testmouse.c +++ b/test/testmouse.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testmultiaudio.c b/test/testmultiaudio.c index 45da833513888..404dc3303b977 100644 --- a/test/testmultiaudio.c +++ b/test/testmultiaudio.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testnative.c b/test/testnative.c index e18195301f077..32af19b37c7b4 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testnative.h b/test/testnative.h index 41ed6ef5f25fd..a1f2d48426011 100644 --- a/test/testnative.h +++ b/test/testnative.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testnativew32.c b/test/testnativew32.c index d3cbe125b3a8b..94b04fcb61f49 100644 --- a/test/testnativew32.c +++ b/test/testnativew32.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testnativex11.c b/test/testnativex11.c index b33a60bf82ede..e10a6fbd24650 100644 --- a/test/testnativex11.c +++ b/test/testnativex11.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testoffscreen.c b/test/testoffscreen.c index 3c2fc83f85f80..74df28390725a 100644 --- a/test/testoffscreen.c +++ b/test/testoffscreen.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testoverlay.c b/test/testoverlay.c index 7d693aaaf4c8f..54f148c62f14a 100644 --- a/test/testoverlay.c +++ b/test/testoverlay.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testpen.c b/test/testpen.c index a193e0840856b..c0db56056eb27 100644 --- a/test/testpen.c +++ b/test/testpen.c @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testplatform.c b/test/testplatform.c index a1f5ee06aa2c9..a3cec4342a00e 100644 --- a/test/testplatform.c +++ b/test/testplatform.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testpopup.c b/test/testpopup.c index ec903d3ff58a3..32595e3a16c02 100644 --- a/test/testpopup.c +++ b/test/testpopup.c @@ -1,5 +1,5 @@ /* -Copyright (C) 1997-2023 Sam Lantinga +Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testpower.c b/test/testpower.c index a65334419cb84..715c6aef6d3de 100644 --- a/test/testpower.c +++ b/test/testpower.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testqsort.c b/test/testqsort.c index 7299e907ec348..f410a61675020 100644 --- a/test/testqsort.c +++ b/test/testqsort.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testrelative.c b/test/testrelative.c index 3ad4d70ea18c8..0854aee95d8a7 100644 --- a/test/testrelative.c +++ b/test/testrelative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testrendercopyex.c b/test/testrendercopyex.c index 7ca0b8aae1f1c..f349247a16be8 100644 --- a/test/testrendercopyex.c +++ b/test/testrendercopyex.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testrendertarget.c b/test/testrendertarget.c index 427351e48c71f..e68127a7d3f12 100644 --- a/test/testrendertarget.c +++ b/test/testrendertarget.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testresample.c b/test/testresample.c index b5c006d4c5ede..760d66ff6b9c6 100644 --- a/test/testresample.c +++ b/test/testresample.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testrumble.c b/test/testrumble.c index 624fbff51cba2..619f1fb07a79f 100644 --- a/test/testrumble.c +++ b/test/testrumble.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testrwlock.c b/test/testrwlock.c index 03c76470811d0..c3c8ebb09088e 100644 --- a/test/testrwlock.c +++ b/test/testrwlock.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testscale.c b/test/testscale.c index 091bb18c16d52..a69c9c1d8e304 100644 --- a/test/testscale.c +++ b/test/testscale.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testsem.c b/test/testsem.c index 12201cc474b65..8d595d394e071 100644 --- a/test/testsem.c +++ b/test/testsem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testsensor.c b/test/testsensor.c index e9d0e0883047a..0ab36b5909ffa 100644 --- a/test/testsensor.c +++ b/test/testsensor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testshader.c b/test/testshader.c index e28c12366f8f5..6b50bca6b7a05 100644 --- a/test/testshader.c +++ b/test/testshader.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testshape.c b/test/testshape.c index 23fc5cb42dbc3..302be4ea0afdb 100644 --- a/test/testshape.c +++ b/test/testshape.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testsprite.c b/test/testsprite.c index a754314149e5a..c186782a76d37 100644 --- a/test/testsprite.c +++ b/test/testsprite.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testspriteminimal.c b/test/testspriteminimal.c index 3981deec23951..6ffcc46b9454e 100644 --- a/test/testspriteminimal.c +++ b/test/testspriteminimal.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/teststreaming.c b/test/teststreaming.c index cf99bc4767689..bb0e02c913e39 100644 --- a/test/teststreaming.c +++ b/test/teststreaming.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testsurround.c b/test/testsurround.c index d263fdcb2c329..ea27cb172824a 100644 --- a/test/testsurround.c +++ b/test/testsurround.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testthread.c b/test/testthread.c index c840937d0952e..be1a6779de62c 100644 --- a/test/testthread.c +++ b/test/testthread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testtimer.c b/test/testtimer.c index 1901d5cdb3d9b..6fc02423a1d66 100644 --- a/test/testtimer.c +++ b/test/testtimer.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testurl.c b/test/testurl.c index e39674b35d0bd..8b4f1caa767d3 100644 --- a/test/testurl.c +++ b/test/testurl.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testutils.c b/test/testutils.c index 7b99cc8b40721..74ae6149e1622 100644 --- a/test/testutils.c +++ b/test/testutils.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/test/testutils.h b/test/testutils.h index 614d6b53ba8f1..5cbbf45a1ee8b 100644 --- a/test/testutils.h +++ b/test/testutils.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga Copyright 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/test/testver.c b/test/testver.c index 313ea8c8fe055..1cfe86d2fcc7f 100644 --- a/test/testver.c +++ b/test/testver.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testvideocapture.c b/test/testvideocapture.c index 62471a76300c3..d14fd485e7785 100644 --- a/test/testvideocapture.c +++ b/test/testvideocapture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testvideocaptureminimal.c b/test/testvideocaptureminimal.c index 3c29d47ce5350..67840d78d117a 100644 --- a/test/testvideocaptureminimal.c +++ b/test/testvideocaptureminimal.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testviewport.c b/test/testviewport.c index 4a900ad908c4b..abca0897962c4 100644 --- a/test/testviewport.c +++ b/test/testviewport.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testvulkan.c b/test/testvulkan.c index 6cd805cc4a9a5..cad7acaa5f220 100644 --- a/test/testvulkan.c +++ b/test/testvulkan.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testwm.c b/test/testwm.c index 72e77ef294512..b400e23de70f2 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testyuv.c b/test/testyuv.c index 6ba996fd0ea53..960d23219e6fa 100644 --- a/test/testyuv.c +++ b/test/testyuv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testyuv_cvt.c b/test/testyuv_cvt.c index 3bed561779238..80e873e271063 100644 --- a/test/testyuv_cvt.c +++ b/test/testyuv_cvt.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/testyuv_cvt.h b/test/testyuv_cvt.h index 781b632ea7f1d..fa736be3c3b2a 100644 --- a/test/testyuv_cvt.h +++ b/test/testyuv_cvt.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/test/torturethread.c b/test/torturethread.c index 033952619b44e..fd524b436d444 100644 --- a/test/torturethread.c +++ b/test/torturethread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages From c2951655ff05c874d454b690036111994a9aba78 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Jan 2024 14:55:42 -0800 Subject: [PATCH 657/725] Fixed warning: missing field 'window' initializer [-Wmissing-field-initializers] --- src/events/SDL_pen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index a4e9d30434b92..5907eeaf8cebe 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -121,9 +121,10 @@ SDL_Pen *SDL_GetPenPtr(Uint32 instance_id) } if (pen_handler.sorted) { - struct SDL_Pen_header key = { 0, 0 }; + struct SDL_Pen_header key; SDL_Pen *pen; + SDL_zero(key); key.id = instance_id; pen = SDL_bsearch(&key, pen_handler.pens, From 87b8f096579fc12727f6e6ba63ded0a4b7bf8d4a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Jan 2024 14:56:55 -0800 Subject: [PATCH 658/725] Fixed warning: no previous prototype for function 'SDL_PrivateGetGamepadButtonFromString' [-Wmissing-prototypes] --- src/joystick/SDL_gamepad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index acadfaa99d606..77852ee1970c1 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -1094,7 +1094,7 @@ SDL_COMPILE_TIME_ASSERT(map_StringForGamepadButton, SDL_arraysize(map_StringForG /* * convert a string to its enum equivalent */ -SDL_GamepadButton SDL_PrivateGetGamepadButtonFromString(const char *str, SDL_bool baxy) +static SDL_GamepadButton SDL_PrivateGetGamepadButtonFromString(const char *str, SDL_bool baxy) { int i; @@ -2818,7 +2818,7 @@ Uint8 SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) /** * Get the label of a button on a gamepad. */ -SDL_GamepadButtonLabel SDL_GetGamepadButtonLabelForFaceStyle(SDL_GamepadFaceStyle face_style, SDL_GamepadButton button) +static SDL_GamepadButtonLabel SDL_GetGamepadButtonLabelForFaceStyle(SDL_GamepadFaceStyle face_style, SDL_GamepadButton button) { SDL_GamepadButtonLabel label = SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN; From 8fe4a45edf7fcba60b15e44132d701a5afd1e70c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 Jan 2024 20:10:39 -0800 Subject: [PATCH 659/725] Use GetRawInputBuffer() instead processing raw input one at a time This is a huge performance improvement for high polling rate mice, like the Razer Viper 8K mouse. Fixes https://github.com/libsdl-org/SDL/issues/8756 --- src/video/windows/SDL_windowsevents.c | 314 ++++++++++++++++---------- src/video/windows/SDL_windowswindow.c | 1 + src/video/windows/SDL_windowswindow.h | 4 + 3 files changed, 203 insertions(+), 116 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 9f0d7f3696941..7d71980267e03 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -105,6 +105,10 @@ /* Used to compare Windows message timestamps */ #define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) +#ifdef _WIN64 +typedef Uint64 QWORD; // Needed for NEXTRAWINPUTBLOCK() +#endif + static SDL_bool SDL_processing_messages; static DWORD message_tick; static Uint64 timestamp_offset; @@ -187,7 +191,7 @@ static SDL_bool WIN_ShouldIgnoreFocusClick(SDL_WindowData *data) !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE); } -static void WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, Uint32 mouseFlags, SDL_bool bSwapButtons, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID) +static void WIN_CheckWParamMouseButton(Uint64 timestamp, SDL_bool bwParamMousePressed, Uint32 mouseFlags, SDL_bool bSwapButtons, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID) { if (bSwapButtons) { if (button == SDL_BUTTON_LEFT) { @@ -209,9 +213,9 @@ static void WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, Uint32 mous } if (bwParamMousePressed && !(mouseFlags & SDL_BUTTON(button))) { - SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, SDL_PRESSED, button); + SDL_SendMouseButton(timestamp, data->window, mouseID, SDL_PRESSED, button); } else if (!bwParamMousePressed && (mouseFlags & SDL_BUTTON(button))) { - SDL_SendMouseButton(WIN_GetEventTimestamp(), data->window, mouseID, SDL_RELEASED, button); + SDL_SendMouseButton(timestamp, data->window, mouseID, SDL_RELEASED, button); } } @@ -219,23 +223,23 @@ static void WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, Uint32 mous * Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also * so this function reconciles our view of the world with the current buttons reported by windows */ -static void WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID) +static void WIN_CheckWParamMouseButtons(Uint64 timestamp, WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID) { if (wParam != data->mouse_button_flags) { Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); /* WM_LBUTTONDOWN and friends handle button swapping for us. No need to check SM_SWAPBUTTON here. */ - WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_LEFT, mouseID); - WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_MIDDLE, mouseID); - WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_RIGHT, mouseID); - WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X1, mouseID); - WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X2, mouseID); + WIN_CheckWParamMouseButton(timestamp, (wParam & MK_LBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_LEFT, mouseID); + WIN_CheckWParamMouseButton(timestamp, (wParam & MK_MBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_MIDDLE, mouseID); + WIN_CheckWParamMouseButton(timestamp, (wParam & MK_RBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_RIGHT, mouseID); + WIN_CheckWParamMouseButton(timestamp, (wParam & MK_XBUTTON1), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X1, mouseID); + WIN_CheckWParamMouseButton(timestamp, (wParam & MK_XBUTTON2), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X2, mouseID); data->mouse_button_flags = wParam; } } -static void WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data, SDL_MouseID mouseID) +static void WIN_CheckRawMouseButtons(Uint64 timestamp, ULONG rawButtons, SDL_WindowData *data, SDL_MouseID mouseID) { // Add a flag to distinguish raw mouse buttons from wParam above rawButtons |= 0x8000000; @@ -244,40 +248,40 @@ static void WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data, SDL Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0; if (rawButtons & RI_MOUSE_BUTTON_1_DOWN) { - WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID); + WIN_CheckWParamMouseButton(timestamp, (rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_1_UP) { - WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID); + WIN_CheckWParamMouseButton(timestamp, !(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_2_DOWN) { - WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID); + WIN_CheckWParamMouseButton(timestamp, (rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_2_UP) { - WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID); + WIN_CheckWParamMouseButton(timestamp, !(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_3_DOWN) { - WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID); + WIN_CheckWParamMouseButton(timestamp, (rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_3_UP) { - WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID); + WIN_CheckWParamMouseButton(timestamp, !(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_4_DOWN) { - WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID); + WIN_CheckWParamMouseButton(timestamp, (rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_4_UP) { - WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID); + WIN_CheckWParamMouseButton(timestamp, !(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_5_DOWN) { - WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID); + WIN_CheckWParamMouseButton(timestamp, (rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID); } if (rawButtons & RI_MOUSE_BUTTON_5_UP) { - WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID); + WIN_CheckWParamMouseButton(timestamp, !(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID); } data->mouse_button_flags = rawButtons; } } -static void WIN_CheckAsyncMouseRelease(SDL_WindowData *data) +static void WIN_CheckAsyncMouseRelease(Uint64 timestamp, SDL_WindowData *data) { Uint32 mouseFlags; SHORT keyState; @@ -291,23 +295,23 @@ static void WIN_CheckAsyncMouseRelease(SDL_WindowData *data) keyState = GetAsyncKeyState(VK_LBUTTON); if (!(keyState & 0x8000)) { - WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0); + WIN_CheckWParamMouseButton(timestamp, SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0); } keyState = GetAsyncKeyState(VK_RBUTTON); if (!(keyState & 0x8000)) { - WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0); + WIN_CheckWParamMouseButton(timestamp, SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0); } keyState = GetAsyncKeyState(VK_MBUTTON); if (!(keyState & 0x8000)) { - WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0); + WIN_CheckWParamMouseButton(timestamp, SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0); } keyState = GetAsyncKeyState(VK_XBUTTON1); if (!(keyState & 0x8000)) { - WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0); + WIN_CheckWParamMouseButton(timestamp, SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0); } keyState = GetAsyncKeyState(VK_XBUTTON2); if (!(keyState & 0x8000)) { - WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0); + WIN_CheckWParamMouseButton(timestamp, SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0); } data->mouse_button_flags = (WPARAM)-1; } @@ -352,7 +356,7 @@ static void WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus) SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, 0, 0, (float)cursorPos.x, (float)cursorPos.y); } - WIN_CheckAsyncMouseRelease(data); + WIN_CheckAsyncMouseRelease(WIN_GetEventTimestamp(), data); WIN_UpdateClipCursor(window); /* @@ -510,6 +514,166 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ +static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, RAWMOUSE *rawmouse) +{ + SDL_MouseID mouseID; + + if (GetMouseMessageSource(rawmouse->ulExtraInformation) == SDL_MOUSE_EVENT_SOURCE_TOUCH) { + return; + } + + /* We do all of our mouse state checking against mouse ID 0 + * We would only use the actual hDevice if we were tracking + * all mouse motion independently, and never using mouse ID 0. + */ + mouseID = 0; /* (SDL_MouseID)(uintptr_t)inp.header.hDevice; */ + + if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) { + if (rawmouse->lLastX || rawmouse->lLastY) { + SDL_SendMouseMotion(timestamp, data->window, mouseID, 1, (float)rawmouse->lLastX, (float)rawmouse->lLastY); + } + } else if (rawmouse->lLastX || rawmouse->lLastY) { + /* This is absolute motion, either using a tablet or mouse over RDP + + Notes on how RDP appears to work, as of Windows 10 2004: + - SetCursorPos() calls are cached, with multiple calls coalesced into a single call that's sent to the RDP client. If the last call to SetCursorPos() has the same value as the last one that was sent to the client, it appears to be ignored and not sent. This means that we need to jitter the SetCursorPos() position slightly in order for the recentering to work correctly. + - User mouse motion is coalesced with SetCursorPos(), so the WM_INPUT positions we see will not necessarily match the position we requested with SetCursorPos(). + - SetCursorPos() outside of the bounds of the focus window appears not to do anything. + - SetCursorPos() while the cursor is NULL doesn't do anything + + We handle this by creating a safe area within the application window, and when the mouse leaves that safe area, we warp back to the opposite side. Any single motion > 50% of the safe area is assumed to be a warp and ignored. + */ + SDL_bool remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? SDL_TRUE : SDL_FALSE; + SDL_bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? SDL_TRUE : SDL_FALSE; + SDL_bool normalized_coordinates = !(rawmouse->usFlags & 0x40) ? SDL_TRUE : SDL_FALSE; + int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); + int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + int x = normalized_coordinates ? (int)(((float)rawmouse->lLastX / 65535.0f) * w) : (int)rawmouse->lLastX; + int y = normalized_coordinates ? (int)(((float)rawmouse->lLastY / 65535.0f) * h) : (int)rawmouse->lLastY; + int relX, relY; + + /* Calculate relative motion */ + if (data->last_raw_mouse_position.x == 0 && data->last_raw_mouse_position.y == 0) { + data->last_raw_mouse_position.x = x; + data->last_raw_mouse_position.y = y; + } + relX = x - data->last_raw_mouse_position.x; + relY = y - data->last_raw_mouse_position.y; + + if (remote_desktop) { + if (!data->in_title_click && !data->focus_click_pending) { + static int wobble; + float floatX = (float)x / w; + float floatY = (float)y / h; + + /* See if the mouse is at the edge of the screen, or in the RDP title bar area */ + if (floatX <= 0.01f || floatX >= 0.99f || floatY <= 0.01f || floatY >= 0.99f || y < 32) { + /* Wobble the cursor position so it's not ignored if the last warp didn't have any effect */ + RECT rect = data->cursor_clipped_rect; + int warpX = rect.left + ((rect.right - rect.left) / 2) + wobble; + int warpY = rect.top + ((rect.bottom - rect.top) / 2); + + WIN_SetCursorPos(warpX, warpY); + + ++wobble; + if (wobble > 1) { + wobble = -1; + } + } else { + /* Send relative motion if we didn't warp last frame (had good position data) + We also sometimes get large deltas due to coalesced mouse motion and warping, + so ignore those. + */ + const int MAX_RELATIVE_MOTION = (h / 6); + if (SDL_abs(relX) < MAX_RELATIVE_MOTION && + SDL_abs(relY) < MAX_RELATIVE_MOTION) { + SDL_SendMouseMotion(timestamp, data->window, mouseID, 1, (float)relX, (float)relY); + } + } + } + } else { + const int MAXIMUM_TABLET_RELATIVE_MOTION = 32; + if (SDL_abs(relX) > MAXIMUM_TABLET_RELATIVE_MOTION || + SDL_abs(relY) > MAXIMUM_TABLET_RELATIVE_MOTION) { + /* Ignore this motion, probably a pen lift and drop */ + } else { + SDL_SendMouseMotion(timestamp, data->window, mouseID, 1, (float)relX, (float)relY); + } + } + + data->last_raw_mouse_position.x = x; + data->last_raw_mouse_position.y = y; + } + WIN_CheckRawMouseButtons(timestamp, rawmouse->usButtonFlags, data, mouseID); +} + +static void WIN_PollRawMouseInput() +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Window *window; + SDL_WindowData *data; + UINT size, count, i, total = 0; + RAWINPUT *input; + Uint64 now, timestamp, increment; + + /* We only use raw mouse input in relative mode */ + if (!mouse->relative_mode || mouse->relative_mode_warp) { + return; + } + + /* Relative mouse motion is delivered to the window with keyboard focus */ + window = SDL_GetKeyboardFocus(); + if (!window) { + return; + } + data = window->driverdata; + + if (data->rawinput_size == 0) { + if (GetRawInputBuffer(NULL, &data->rawinput_size, sizeof(RAWINPUTHEADER)) == (UINT)-1) { + return; + } + if (data->rawinput_size == 0) { + return; + } + } + + /* Get all available events */ + for (;;) { + if (total == data->rawinput_count) { + count = total + 8; + input = (RAWINPUT *)SDL_malloc(count * data->rawinput_size); + if (!input) { + return; + } + data->rawinput = input; + data->rawinput_count = count; + } + + size = (data->rawinput_count - total) * data->rawinput_size; + count = GetRawInputBuffer(&data->rawinput[total], &size, sizeof(RAWINPUTHEADER)); + if (count == (UINT)-1 || count == 0) { + break; + } + total += count; + } + + now = SDL_GetTicksNS(); + if (total > 0) { + /* We'll spread these events over the time since the last poll */ + timestamp = data->last_rawinput_poll; + increment = (now - timestamp) / total; + for (i = 0, input = data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { + timestamp += increment; + if (input->header.dwType == RIM_TYPEMOUSE) { + RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + 24); + WIN_HandleRawMouseInput(timestamp, window->driverdata, rawmouse); + } + } + } + data->last_rawinput_poll = now; +} + + LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -643,11 +807,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (!mouse->relative_mode || mouse->relative_mode_warp) { if (GetMouseMessageSource((ULONG)GetMessageExtraInfo()) != SDL_MOUSE_EVENT_SOURCE_TOUCH && lParam != data->last_pointer_update) { - WIN_CheckWParamMouseButtons(wParam, data, 0); + WIN_CheckWParamMouseButtons(WIN_GetEventTimestamp(), wParam, data, 0); } } } break; +#if 0 /* We handle raw input all at once instead of using a syscall for each mouse event */ case WM_INPUT: { SDL_Mouse *mouse = SDL_GetMouse(); @@ -669,95 +834,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ if (inp.header.dwType == RIM_TYPEMOUSE) { - SDL_MouseID mouseID; - RAWMOUSE *rawmouse; - if (GetMouseMessageSource(inp.data.mouse.ulExtraInformation) == SDL_MOUSE_EVENT_SOURCE_TOUCH) { - break; - } - /* We do all of our mouse state checking against mouse ID 0 - * We would only use the actual hDevice if we were tracking - * all mouse motion independently, and never using mouse ID 0. - */ - mouseID = 0; /* (SDL_MouseID)(uintptr_t)inp.header.hDevice; */ - rawmouse = &inp.data.mouse; - - if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) { - SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, mouseID, 1, (float)rawmouse->lLastX, (float)rawmouse->lLastY); - } else if (rawmouse->lLastX || rawmouse->lLastY) { - /* This is absolute motion, either using a tablet or mouse over RDP - - Notes on how RDP appears to work, as of Windows 10 2004: - - SetCursorPos() calls are cached, with multiple calls coalesced into a single call that's sent to the RDP client. If the last call to SetCursorPos() has the same value as the last one that was sent to the client, it appears to be ignored and not sent. This means that we need to jitter the SetCursorPos() position slightly in order for the recentering to work correctly. - - User mouse motion is coalesced with SetCursorPos(), so the WM_INPUT positions we see will not necessarily match the position we requested with SetCursorPos(). - - SetCursorPos() outside of the bounds of the focus window appears not to do anything. - - SetCursorPos() while the cursor is NULL doesn't do anything - - We handle this by creating a safe area within the application window, and when the mouse leaves that safe area, we warp back to the opposite side. Any single motion > 50% of the safe area is assumed to be a warp and ignored. - */ - SDL_bool remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? SDL_TRUE : SDL_FALSE; - SDL_bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? SDL_TRUE : SDL_FALSE; - SDL_bool normalized_coordinates = !(rawmouse->usFlags & 0x40) ? SDL_TRUE : SDL_FALSE; - int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); - int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); - int x = normalized_coordinates ? (int)(((float)rawmouse->lLastX / 65535.0f) * w) : (int)rawmouse->lLastX; - int y = normalized_coordinates ? (int)(((float)rawmouse->lLastY / 65535.0f) * h) : (int)rawmouse->lLastY; - int relX, relY; - - /* Calculate relative motion */ - if (data->last_raw_mouse_position.x == 0 && data->last_raw_mouse_position.y == 0) { - data->last_raw_mouse_position.x = x; - data->last_raw_mouse_position.y = y; - } - relX = x - data->last_raw_mouse_position.x; - relY = y - data->last_raw_mouse_position.y; - - if (remote_desktop) { - if (!data->in_title_click && !data->focus_click_pending) { - static int wobble; - float floatX = (float)x / w; - float floatY = (float)y / h; - - /* See if the mouse is at the edge of the screen, or in the RDP title bar area */ - if (floatX <= 0.01f || floatX >= 0.99f || floatY <= 0.01f || floatY >= 0.99f || y < 32) { - /* Wobble the cursor position so it's not ignored if the last warp didn't have any effect */ - RECT rect = data->cursor_clipped_rect; - int warpX = rect.left + ((rect.right - rect.left) / 2) + wobble; - int warpY = rect.top + ((rect.bottom - rect.top) / 2); - - WIN_SetCursorPos(warpX, warpY); - - ++wobble; - if (wobble > 1) { - wobble = -1; - } - } else { - /* Send relative motion if we didn't warp last frame (had good position data) - We also sometimes get large deltas due to coalesced mouse motion and warping, - so ignore those. - */ - const int MAX_RELATIVE_MOTION = (h / 6); - if (SDL_abs(relX) < MAX_RELATIVE_MOTION && - SDL_abs(relY) < MAX_RELATIVE_MOTION) { - SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, mouseID, 1, (float)relX, (float)relY); - } - } - } - } else { - const int MAXIMUM_TABLET_RELATIVE_MOTION = 32; - if (SDL_abs(relX) > MAXIMUM_TABLET_RELATIVE_MOTION || - SDL_abs(relY) > MAXIMUM_TABLET_RELATIVE_MOTION) { - /* Ignore this motion, probably a pen lift and drop */ - } else { - SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, mouseID, 1, (float)relX, (float)relY); - } - } - - data->last_raw_mouse_position.x = x; - data->last_raw_mouse_position.y = y; - } - WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data, mouseID); + WIN_HandleRawMouseInput(WIN_GetEventTimestamp(), data, &inp.data.mouse); } } break; +#endif case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: @@ -900,7 +980,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) data->in_title_click = SDL_FALSE; /* The mouse may have been released during a modal loop */ - WIN_CheckAsyncMouseRelease(data); + WIN_CheckAsyncMouseRelease(WIN_GetEventTimestamp(), data); } break; #ifdef WM_GETMINMAXINFO @@ -1663,6 +1743,8 @@ void WIN_PumpEvents(SDL_VideoDevice *_this) SDL_Window *focusWindow; #endif + WIN_PollRawMouseInput(); + if (g_WindowsEnableMessageLoop) { SDL_processing_messages = SDL_TRUE; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 980fedb0ff60c..0f54a73dabd8b 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -518,6 +518,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window) #endif } } + SDL_free(data->rawinput); SDL_free(data); } window->driverdata = NULL; diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index ab8ab48522bf0..c5ff4ce8c7b92 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -66,6 +66,10 @@ struct SDL_WindowData SDL_bool windowed_mode_was_maximized; SDL_bool in_window_deactivation; RECT cursor_clipped_rect; + RAWINPUT *rawinput; + UINT rawinput_size; + UINT rawinput_count; + Uint64 last_rawinput_poll; SDL_Point last_raw_mouse_position; SDL_bool mouse_tracked; SDL_bool destroy_parent_with_window; From bec1b8f849b782ca7d815337380c5f2b42ed60ce Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 22 Dec 2023 19:48:41 -0800 Subject: [PATCH 660/725] Add basic rumble support to Steam Deck --- src/joystick/hidapi/SDL_hidapi_steamdeck.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index 7b606b8bf8bb6..b387add9afad1 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -363,8 +363,22 @@ static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, S static int HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { - /* You should use the full Steam Input API for rumble support */ - return SDL_Unsupported(); + int rc; + Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 }; + FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1); + + msg->header.type = ID_TRIGGER_RUMBLE_CMD; + msg->payload.simpleRumble.unRumbleType = 0; + msg->payload.simpleRumble.unIntensity = HAPTIC_INTENSITY_SYSTEM; + msg->payload.simpleRumble.unLeftMotorSpeed = low_frequency_rumble; + msg->payload.simpleRumble.unRightMotorSpeed = high_frequency_rumble; + msg->payload.simpleRumble.nLeftGain = 2; + msg->payload.simpleRumble.nRightGain = 0; + + rc = SDL_hid_send_feature_report(device->dev, buffer, sizeof(buffer)); + if (rc != sizeof(buffer)) + return -1; + return 0; } static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) @@ -374,7 +388,7 @@ static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *devi static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return 0; + return SDL_JOYCAP_RUMBLE; } static int HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) From 2b369a14abc2fd065a91a71cb0cb1830a231a9e9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 2 Jan 2024 09:25:28 -0800 Subject: [PATCH 661/725] Fixed allocation and alignment of raw input buffers --- src/video/windows/SDL_windowsevents.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 7d71980267e03..c0a1e4d41e859 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -607,6 +607,26 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, RAWM WIN_CheckRawMouseButtons(timestamp, rawmouse->usButtonFlags, data, mouseID); } +/* The layout of memory for data returned from GetRawInputBuffer(), documented here: + * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputbuffer + */ +typedef struct +{ + union + { + RAWINPUTHEADER header; + BYTE padding[24]; + } hdr; + + union + { + RAWMOUSE mouse; + RAWKEYBOARD keyboard; + RAWHID hid; + } data; + +} ALIGNED_RAWINPUT; + static void WIN_PollRawMouseInput() { SDL_Mouse *mouse = SDL_GetMouse(); @@ -641,7 +661,7 @@ static void WIN_PollRawMouseInput() for (;;) { if (total == data->rawinput_count) { count = total + 8; - input = (RAWINPUT *)SDL_malloc(count * data->rawinput_size); + input = (RAWINPUT *)SDL_realloc(data->rawinput, count * data->rawinput_size); if (!input) { return; } @@ -650,7 +670,7 @@ static void WIN_PollRawMouseInput() } size = (data->rawinput_count - total) * data->rawinput_size; - count = GetRawInputBuffer(&data->rawinput[total], &size, sizeof(RAWINPUTHEADER)); + count = GetRawInputBuffer((RAWINPUT *)((BYTE *)data->rawinput + (total * data->rawinput_size)), &size, sizeof(RAWINPUTHEADER)); if (count == (UINT)-1 || count == 0) { break; } @@ -665,7 +685,7 @@ static void WIN_PollRawMouseInput() for (i = 0, input = data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { timestamp += increment; if (input->header.dwType == RIM_TYPEMOUSE) { - RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + 24); + RAWMOUSE *rawmouse = &(((ALIGNED_RAWINPUT *)input)->data.mouse); WIN_HandleRawMouseInput(timestamp, window->driverdata, rawmouse); } } From 987744aae88404951cf7e5b8383c1d9b76929953 Mon Sep 17 00:00:00 2001 From: Nour Fouad Date: Wed, 3 Jan 2024 02:24:44 +0200 Subject: [PATCH 662/725] Fix Duplicated includes --- src/video/wayland/SDL_waylandvulkan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 9fcd575b44c26..7debe29f4e642 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -28,8 +28,6 @@ #if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WAYLAND) -#include "../SDL_vulkan_internal.h" - #include "SDL_waylandvideo.h" #include "SDL_waylandwindow.h" From 31851a50d2e30efa1a3c74ae83592d6a29ffc5b7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 3 Jan 2024 02:20:23 -0800 Subject: [PATCH 663/725] Fixed dropping raw input because of mixing GetRawInputBuffer() and WM_INPUT handling It turns out that when you enable raw input and then process Windows messages, you'll get the currently pending input in GetRawInputBuffer(), and you'll get any new input that occurs while processing messages as WM_INPUT. The fix for this is to create a dedicated thread to handle raw input and only use GetRawInputBuffer() in that thread. A nice side effect of this is that we'll get mouse input at the lowest latency possible, but raw mouse events will now occur on a separate thread, outside of the normal event loop processing. Improved fix for https://github.com/libsdl-org/SDL/issues/8756 --- src/video/windows/SDL_windowsevents.c | 50 +++++----- src/video/windows/SDL_windowsevents.h | 1 + src/video/windows/SDL_windowsmouse.c | 132 +++++++++++++++++++++++--- src/video/windows/SDL_windowswindow.h | 1 + 4 files changed, 141 insertions(+), 43 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index c0a1e4d41e859..63bc28a76e4ba 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -607,34 +607,14 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, RAWM WIN_CheckRawMouseButtons(timestamp, rawmouse->usButtonFlags, data, mouseID); } -/* The layout of memory for data returned from GetRawInputBuffer(), documented here: - * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputbuffer - */ -typedef struct -{ - union - { - RAWINPUTHEADER header; - BYTE padding[24]; - } hdr; - - union - { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; - -} ALIGNED_RAWINPUT; - -static void WIN_PollRawMouseInput() +void WIN_PollRawMouseInput(void) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *window; SDL_WindowData *data; UINT size, count, i, total = 0; RAWINPUT *input; - Uint64 now, timestamp, increment; + Uint64 now; /* We only use raw mouse input in relative mode */ if (!mouse->relative_mode || mouse->relative_mode_warp) { @@ -649,6 +629,14 @@ static void WIN_PollRawMouseInput() data = window->driverdata; if (data->rawinput_size == 0) { + BOOL isWow64; + + data->rawinput_offset = sizeof(RAWINPUTHEADER); + if (IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64) { + /* We're going to get 64-bit data, so use the 64-bit RAWINPUTHEADER size */ + data->rawinput_offset += 8; + } + if (GetRawInputBuffer(NULL, &data->rawinput_size, sizeof(RAWINPUTHEADER)) == (UINT)-1) { return; } @@ -679,13 +667,21 @@ static void WIN_PollRawMouseInput() now = SDL_GetTicksNS(); if (total > 0) { - /* We'll spread these events over the time since the last poll */ - timestamp = data->last_rawinput_poll; - increment = (now - timestamp) / total; + Uint64 timestamp, increment; + Uint64 delta = (now - data->last_rawinput_poll); + if (total > 1 && delta <= SDL_MS_TO_NS(100)) { + /* We'll spread these events over the time since the last poll */ + timestamp = data->last_rawinput_poll; + increment = delta / total; + } else { + /* Do we want to track the update rate per device? */ + timestamp = now; + increment = 0; + } for (i = 0, input = data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { timestamp += increment; if (input->header.dwType == RIM_TYPEMOUSE) { - RAWMOUSE *rawmouse = &(((ALIGNED_RAWINPUT *)input)->data.mouse); + RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset); WIN_HandleRawMouseInput(timestamp, window->driverdata, rawmouse); } } @@ -1763,8 +1759,6 @@ void WIN_PumpEvents(SDL_VideoDevice *_this) SDL_Window *focusWindow; #endif - WIN_PollRawMouseInput(); - if (g_WindowsEnableMessageLoop) { SDL_processing_messages = SDL_TRUE; diff --git a/src/video/windows/SDL_windowsevents.h b/src/video/windows/SDL_windowsevents.h index 414019ba9b581..77f1dd464a2c9 100644 --- a/src/video/windows/SDL_windowsevents.h +++ b/src/video/windows/SDL_windowsevents.h @@ -30,6 +30,7 @@ extern HINSTANCE SDL_Instance; extern LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam); extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern void WIN_PollRawMouseInput(void); extern void WIN_PumpEvents(SDL_VideoDevice *_this); extern void WIN_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window); extern int WIN_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 4ff7950406c1e..a078e039d2563 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -23,9 +23,11 @@ #if defined(SDL_VIDEO_DRIVER_WINDOWS) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) #include "SDL_windowsvideo.h" +#include "SDL_windowsevents.h" -#include "../../events/SDL_mouse_c.h" #include "../SDL_video_c.h" +#include "../../events/SDL_mouse_c.h" +#include "../../joystick/usb_ids.h" DWORD SDL_last_warp_time = 0; HCURSOR SDL_cursor = NULL; @@ -33,9 +35,84 @@ static SDL_Cursor *SDL_blank_cursor = NULL; static int rawInputEnableCount = 0; +typedef struct +{ + HANDLE ready_event; + HANDLE done_event; + HANDLE thread; +} RawMouseThreadData; + +static RawMouseThreadData thread_data = { + INVALID_HANDLE_VALUE, + INVALID_HANDLE_VALUE, + INVALID_HANDLE_VALUE +}; + +static DWORD WINAPI WIN_RawMouseThread(LPVOID param) +{ + RAWINPUTDEVICE rawMouse; + HWND window; + + window = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); + if (!window) { + return 0; + } + + rawMouse.usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP; + rawMouse.usUsage = USB_USAGE_GENERIC_MOUSE; + rawMouse.dwFlags = 0; + rawMouse.hwndTarget = window; + + if (!RegisterRawInputDevices(&rawMouse, 1, sizeof(rawMouse))) { + DestroyWindow(window); + return 0; + } + + /* Tell the parent we're ready to go! */ + SetEvent(thread_data.ready_event); + + for ( ; ; ) { + if (MsgWaitForMultipleObjects(1, &thread_data.done_event, 0, INFINITE, QS_RAWINPUT) != WAIT_OBJECT_0 + 1) { + break; + } + + /* Clear the queue status so MsgWaitForMultipleObjects() will wait again */ + (void)GetQueueStatus(QS_RAWINPUT); + + WIN_PollRawMouseInput(); + } + + rawMouse.dwFlags |= RIDEV_REMOVE; + RegisterRawInputDevices(&rawMouse, 1, sizeof(rawMouse)); + + DestroyWindow(window); + + return 0; +} + +static void CleanupRawMouseThreadData(void) +{ + if (thread_data.thread != INVALID_HANDLE_VALUE) { + SetEvent(thread_data.done_event); + WaitForSingleObject(thread_data.thread, 500); + CloseHandle(thread_data.thread); + thread_data.thread = INVALID_HANDLE_VALUE; + } + + if (thread_data.ready_event != INVALID_HANDLE_VALUE) { + CloseHandle(thread_data.ready_event); + thread_data.ready_event = INVALID_HANDLE_VALUE; + } + + if (thread_data.done_event != INVALID_HANDLE_VALUE) { + CloseHandle(thread_data.done_event); + thread_data.done_event = INVALID_HANDLE_VALUE; + } +} + static int ToggleRawInput(SDL_bool enabled) { - RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */ + int result = -1; if (enabled) { rawInputEnableCount++; @@ -52,23 +129,48 @@ static int ToggleRawInput(SDL_bool enabled) } } - if (!enabled) { - rawMouse.dwFlags |= RIDEV_REMOVE; - } + if (enabled) { + HANDLE handles[2]; - /* (Un)register raw input for mice */ - if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) { - /* Reset the enable count, otherwise subsequent enable calls will - believe raw input is enabled */ - rawInputEnableCount = 0; + thread_data.ready_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (thread_data.ready_event == INVALID_HANDLE_VALUE) { + WIN_SetError("CreateEvent"); + goto done; + } + + thread_data.done_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (thread_data.done_event == INVALID_HANDLE_VALUE) { + WIN_SetError("CreateEvent"); + goto done; + } - /* Only return an error when registering. If we unregister and fail, - then it's probably that we unregistered twice. That's OK. */ - if (enabled) { - return SDL_Unsupported(); + thread_data.thread = CreateThread(NULL, 0, WIN_RawMouseThread, &thread_data, 0, NULL); + if (thread_data.thread == INVALID_HANDLE_VALUE) { + WIN_SetError("CreateThread"); + goto done; } + + /* Wait for the thread to signal ready or exit */ + handles[0] = thread_data.ready_event; + handles[1] = thread_data.thread; + if (WaitForMultipleObjects(2, handles, FALSE, INFINITE) != WAIT_OBJECT_0) { + SDL_SetError("Couldn't set up raw input handling"); + goto done; + } + result = 0; + } else { + CleanupRawMouseThreadData(); + result = 0; } - return 0; + +done: + if (enabled && result < 0) { + CleanupRawMouseThreadData(); + + /* Reset rawInputEnableCount so we can try again */ + rawInputEnableCount = 0; + } + return result; } static SDL_Cursor *WIN_CreateDefaultCursor() diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index c5ff4ce8c7b92..835ba622db60d 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -67,6 +67,7 @@ struct SDL_WindowData SDL_bool in_window_deactivation; RECT cursor_clipped_rect; RAWINPUT *rawinput; + UINT rawinput_offset; UINT rawinput_size; UINT rawinput_count; Uint64 last_rawinput_poll; From b4b5dbd92f2d6af930b0f137d6d29f53004e3e04 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 3 Jan 2024 14:40:20 +0300 Subject: [PATCH 664/725] testcontroller.c: fixed warnings. --- test/testcontroller.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testcontroller.c b/test/testcontroller.c index bcd9c6be3514a..d62030dcc2a40 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -460,8 +460,8 @@ static void CommitBindingElement(const char *binding, SDL_bool force) } } if (native_axis) { - AxisInfo current_axis_info; - AxisInfo proposed_axis_info; + AxisInfo current_axis_info = { 0, 0 }; + AxisInfo proposed_axis_info = { 0, 0 }; SDL_bool current_axis = ParseAxisInfo(current, ¤t_axis_info); SDL_bool proposed_axis = ParseAxisInfo(binding, &proposed_axis_info); @@ -1318,7 +1318,7 @@ static void DrawGamepadInfo(SDL_Renderer *renderer) if (display_mode == CONTROLLER_MODE_TESTING) { Uint64 steam_handle = SDL_GetGamepadSteamHandle(controller->gamepad); if (steam_handle) { - SDL_snprintf(text, SDL_arraysize(text), "Steam: 0x%.16llx", (unsigned long long)steam_handle); + SDL_snprintf(text, SDL_arraysize(text), "Steam: 0x%.16" SDL_PRIx64 "", steam_handle); y = (float)SCREEN_HEIGHT - 2 * (8.0f + FONT_LINE_HEIGHT); x = (float)SCREEN_WIDTH - 8.0f - (FONT_CHARACTER_SIZE * SDL_strlen(text)); SDLTest_DrawString(renderer, x, y, text); From ed62d6e7deb7684c8a59e5d77908fc762fdacccf Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 3 Jan 2024 19:56:57 -0500 Subject: [PATCH 665/725] cocoa: Set the titled flag on fullscreen space windows For some reason, fullscreen space windows won't get any mouse button events unless the NSWindowStyleMaskTitled flag is set when entering fullscreen, even though they successfully become key and receive mouse motion events. Make sure the flag is always set when entering fullscreen space state. --- src/video/cocoa/SDL_cocoawindow.h | 1 + src/video/cocoa/SDL_cocoawindow.m | 37 +++++++++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 46a27b6829a95..96fec957abb5e 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -140,6 +140,7 @@ typedef enum @property(nonatomic) SDL_CocoaVideoData *videodata; @property(nonatomic) SDL_bool send_floating_size; @property(nonatomic) SDL_bool send_floating_position; +@property(nonatomic) SDL_bool border_toggled; @property(nonatomic) BOOL checking_zoom; #ifdef SDL_VIDEO_OPENGL_EGL @property(nonatomic) EGLSurface egl_surface; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 0b0c8113c8f70..d2745db04c257 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1140,18 +1140,12 @@ - (void)windowDidChangeScreen:(NSNotification *)aNotification - (void)windowWillEnterFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data.window; - NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; + const NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable | NSWindowStyleMaskTitled; - /* Don't set the titled flag on a fullscreen window if the windowed-mode window - * is borderless, or the window can wind up in a weird, pseudo-decorated state - * when leaving fullscreen if the border flag was toggled on. + /* For some reason, the fullscreen window won't get any mouse button events + * without the NSWindowStyleMaskTitled flag being set when entering fullscreen, + * so it's needed even if the window is borderless. */ - if (!(window->flags & SDL_WINDOW_BORDERLESS)) { - flags |= NSWindowStyleMaskTitled; - } else { - flags |= NSWindowStyleMaskBorderless; - } - SetWindowStyle(window, flags); _data.was_zoomed = !!(window->flags & SDL_WINDOW_MAXIMIZED); @@ -1212,6 +1206,19 @@ - (void)windowDidEnterFullScreen:(NSNotification *)aNotification - (void)windowWillExitFullScreen:(NSNotification *)aNotification { + SDL_Window *window = _data.window; + + /* If the windowed mode borders were toggled on while in a fullscreen space, + * NSWindowStyleMaskTitled has to be cleared here, or the window can end up + * in a weird, semi-decorated state upon returning to windowed mode. + */ + if (_data.border_toggled && !(window->flags & SDL_WINDOW_BORDERLESS)) { + const NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; + + SetWindowStyle(window, flags); + _data.border_toggled = SDL_FALSE; + } + isFullscreenSpace = NO; inFullscreenTransition = YES; } @@ -1219,17 +1226,11 @@ - (void)windowWillExitFullScreen:(NSNotification *)aNotification - (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data.window; - NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; + const NSUInteger flags = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; if (window->is_destroying) { return; } - - if (!(window->flags & SDL_WINDOW_BORDERLESS)) { - flags |= NSWindowStyleMaskTitled; - } else { - flags |= NSWindowStyleMaskBorderless; - } SetWindowStyle(window, flags); @@ -2455,6 +2456,8 @@ void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_boo Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */ } } + } else { + data.border_toggled = SDL_TRUE; } } } From 5cbdeab7997809c517683efbcc0d563f19c9d326 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 4 Jan 2024 17:46:00 +0100 Subject: [PATCH 666/725] Rename SDL_mslibc_x64.asm -> SDL_mslibc_x64.masm The .masm suffix should give meson sufficient info about the file being MASM instead of NASM/YASM. --- CMakeLists.txt | 2 +- VisualC-GDK/SDL/SDL.vcxproj | 2 +- VisualC-GDK/SDL/SDL.vcxproj.filters | 2 +- VisualC-WinRT/SDL-UWP.vcxproj | 2 +- VisualC-WinRT/SDL-UWP.vcxproj.filters | 2 +- VisualC/SDL/SDL.vcxproj | 2 +- VisualC/SDL/SDL.vcxproj.filters | 2 +- src/stdlib/{SDL_mslibc_x64.asm => SDL_mslibc_x64.masm} | 0 8 files changed, 7 insertions(+), 7 deletions(-) rename src/stdlib/{SDL_mslibc_x64.asm => SDL_mslibc_x64.masm} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74c2102b6163e..5910154ad6264 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -497,7 +497,7 @@ sdl_glob_sources( if(MSVC AND TARGET SDL3-shared) if(SDL_CPU_X64) enable_language(ASM_MASM) - set(asm_src "${SDL3_SOURCE_DIR}/src/stdlib/SDL_mslibc_x64.asm") + set(asm_src "${SDL3_SOURCE_DIR}/src/stdlib/SDL_mslibc_x64.masm") target_compile_options(SDL3-shared PRIVATE "$<$:/nologo>") set_property(SOURCE "${asm_src}" PROPERTY LANGUAGE "ASM_MASM") target_sources(SDL3-shared PRIVATE "${asm_src}") diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 7fe307986cd10..b7b5a72c02ff8 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -733,7 +733,7 @@ - + NotUsing diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 08257eaf35f4c..e9f4d52c5064b 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -1397,7 +1397,7 @@ stdlib - + stdlib diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 2e1701a4d627b..715c6020448c7 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -419,7 +419,7 @@ - + NotUsing diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index d92ce733801ea..728fdbbcc1d3f 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -899,7 +899,7 @@ Source Files - + stdlib diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 3f38d13f89f93..0b5345789220e 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -613,7 +613,7 @@ - + NotUsing diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 6002a968c609b..e53a8eb40d685 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1387,7 +1387,7 @@ stdlib - + stdlib diff --git a/src/stdlib/SDL_mslibc_x64.asm b/src/stdlib/SDL_mslibc_x64.masm similarity index 100% rename from src/stdlib/SDL_mslibc_x64.asm rename to src/stdlib/SDL_mslibc_x64.masm From c03c01e9b21cb9c38fe7f09899895708ca95d128 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Jan 2024 09:12:37 -0800 Subject: [PATCH 667/725] Make sure we get mouse events as soon as possible --- src/video/windows/SDL_windowsmouse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index a078e039d2563..07625887db45f 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -68,6 +68,9 @@ static DWORD WINAPI WIN_RawMouseThread(LPVOID param) return 0; } + /* Make sure we get mouse events as soon as possible */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + /* Tell the parent we're ready to go! */ SetEvent(thread_data.ready_event); From 73d02184d7426dc40216f44cfe88f188e8827ad1 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 4 Jan 2024 13:55:57 -0500 Subject: [PATCH 668/725] docs: Add Wayland to the SysWM migration example Wayland will be increasingly encountered going forward and needs to be handled by applications requesting window handles to initialize the Vulkan WSI and such, so include it in the migration example to reflect current best practices. --- docs/README-migration.md | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 5eb8b506d8c15..0bdde8fdaa034 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1219,14 +1219,20 @@ The information previously available in SDL_GetWindowWMInfo() is now available a ... } #elif defined(__LINUX__) - Display *xdisplay = NULL; - Window xwindow = 0; - if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_X11) { - xdisplay = info.info.x11.display; - xwindow = info.info.x11.window; - } - if (xdisplay && xwindow) { - ... + if (SDL_GetWindowWMInfo(window, &info)) { + if (info.subsystem == SDL_SYSWM_X11) { + Display *xdisplay = info.info.x11.display; + Window xwindow = info.info.x11.window; + if (xdisplay && xwindow) { + ... + } + } else if (info.subsystem == SDL_SYSWM_WAYLAND) { + struct wl_display *display = info.info.wl.display; + struct wl_surface *surface = info.info.wl.surface; + if (display && surface) { + ... + } + } } #endif ``` @@ -1243,10 +1249,18 @@ becomes: ... } #elif defined(__LINUX__) - Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.x11.display", NULL); - Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); - if (xdisplay && xwindow) { - ... + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.x11.display", NULL); + Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); + if (xdisplay && xwindow) { + ... + } + } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { + struct wl_display *display = (struct wl_display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.display", NULL); + struct wl_surface *surface = (struct wl_surface *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.surface", NULL); + if (display && surface) { + ... + } } #endif ``` From 7c5e69402299e255fbb5b2ae6e2fd4bff06838e4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Jan 2024 12:44:48 -0800 Subject: [PATCH 669/725] Ignore a new warning in Visual Studio 2022 --- src/joystick/windows/SDL_rawinputjoystick.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index cd0e16ca36c68..77add5397b5d0 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -520,6 +520,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_InvokeRemoved(__FIEv #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4028) /* formal parameter 3 different from declaration, when using older buggy WGI headers */ +#pragma warning(disable : 4113) /* X differs in parameter lists from Y, when using older buggy WGI headers */ #endif static __FIEventHandler_1_Windows__CGaming__CInput__CGamepadVtbl gamepad_added_vtbl = { From d6b1fc95765e67e84e56f4e081fada33adc3be93 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Jan 2024 12:44:54 -0800 Subject: [PATCH 670/725] Add SDL_MAC_REGISTER_ACTIVATION_HANDLERS hint to allow disabling the normal application startup/activation/deactivation handlers --- src/video/cocoa/SDL_cocoaevents.m | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index c48c9544dcbfd..a3c3199157ce9 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -142,18 +142,21 @@ - (id)init self = [super init]; if (self) { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + SDL_bool registerActivationHandlers = SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", SDL_TRUE); seenFirstActivate = NO; - [center addObserver:self - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:nil]; + if (registerActivationHandlers) { + [center addObserver:self + selector:@selector(windowWillClose:) + name:NSWindowWillCloseNotification + object:nil]; - [center addObserver:self - selector:@selector(focusSomeWindow:) - name:NSApplicationDidBecomeActiveNotification - object:nil]; + [center addObserver:self + selector:@selector(focusSomeWindow:) + name:NSApplicationDidBecomeActiveNotification + object:nil]; + } [center addObserver:self selector:@selector(localeDidChange:) @@ -293,6 +296,9 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam - (void)applicationDidFinishLaunching:(NSNotification *)notification { + if (!SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", SDL_TRUE)) + return; + /* The menu bar of SDL apps which don't have the typical .app bundle * structure fails to work the first time a window is created (until it's * de-focused and re-focused), if this call is in Cocoa_RegisterApp instead From 787a15f76005158bf64517ccf24f3f4b9baf415c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Jan 2024 12:44:57 -0800 Subject: [PATCH 671/725] Fix Mac child windows that are created hidden showing if their parent window is shown - Child windows are added and removed dynamically from the window hierarchy when they're shown/hidden. Adding a hidden child window to a visible parent is fine, but adding a hidden child window to a hidden parent will cause the child to show when the parent window is shown as it's still a part of the window hierarchy. - For some reason, not adding the child window to the parent entirely causes the child to not focus correctly the first time it's shown. Adding then immediately calling orderOut to remove the child window from the hierarchy does work correctly so we do this to work around the weird issue. --- src/video/cocoa/SDL_cocoawindow.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index d2745db04c257..5dbc04b46d423 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1926,6 +1926,16 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow Cocoa_SetKeyboardFocus(window); } } + + /* FIXME: Should not need to call addChildWindow then orderOut. + Attaching a hidden child window to a hidden parent window will cause the child window + to show when the parent does. We therefore shouldn't attach the child window here as we're + going to do so when the child window is explicitly shown later but skipping the addChildWindow + entirely causes the child window to not get key focus correctly the first time it's shown. Adding + then immediately ordering out (removing) the window does work. */ + if (window->flags & SDL_WINDOW_HIDDEN) { + [nswindow orderOut:nil]; + } } if (nswindow.isOpaque) { From 21c80ac8432500ddb4dd456cee64537a1e7701d3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Jan 2024 22:51:13 -0800 Subject: [PATCH 672/725] Added a practical example of confirm/cancel gamepad button handling --- docs/README-migration.md | 66 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 0bdde8fdaa034..c8b0b9274b8b3 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -396,7 +396,71 @@ The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the w The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads. -The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications will now need to provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. Using South as the accept button and East as the cancel button is a good default. +The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications should provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. You can use an approach similar to the following to handle this: + +```c +#define CONFIRM_BUTTON SDL_GAMEPAD_BUTTON_SOUTH +#define CANCEL_BUTTON SDL_GAMEPAD_BUTTON_EAST + +SDL_bool flipped_buttons; + +void InitMappedButtons(SDL_Gamepad *gamepad) +{ + if (!GetFlippedButtonSetting(&flipped_buttons)) { + if (SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B) { + flipped_buttons = SDL_TRUE; + } else { + flipped_buttons = SDL_FALSE; + } + } +} + +SDL_GamepadButton GetMappedButton(SDL_GamepadButton button) +{ + if (flipped_buttons) { + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: + return SDL_GAMEPAD_BUTTON_EAST; + case SDL_GAMEPAD_BUTTON_EAST: + return SDL_GAMEPAD_BUTTON_SOUTH; + case SDL_GAMEPAD_BUTTON_WEST: + return SDL_GAMEPAD_BUTTON_NORTH; + case SDL_GAMEPAD_BUTTON_NORTH: + return SDL_GAMEPAD_BUTTON_WEST; + default: + break; + } + } + return button; +} + +SDL_GamepadButtonLabel GetConfirmActionLabel(SDL_Gamepad *gamepad) +{ + return SDL_GetGamepadButtonLabel(gamepad, GetMappedButton(CONFIRM_BUTTON)); +} + +SDL_GamepadButtonLabel GetCancelActionLabel(SDL_Gamepad *gamepad) +{ + return SDL_GetGamepadButtonLabel(gamepad, GetMappedButton(CANCEL_BUTTON)); +} + +void HandleGamepadEvent(SDL_Event *event) +{ + if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) { + switch (GetMappedButton(event->gbutton.button)) { + case CONFIRM_BUTTON: + /* Handle confirm action */ + break; + case CANCEL_BUTTON: + /* Handle cancel action */ + break; + default: + /* ... */ + break; + } + } +} +``` SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events. From 139a0931a3ee9808f13e7faecdf9fc4590348f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Neusch=C3=A4fer?= Date: Fri, 5 Jan 2024 06:30:54 +0100 Subject: [PATCH 673/725] Fix memory barriers on ARMv5 The ARM926EJ-S Technical Reference Manual states: > You can only access CP15 registers with MRC and MCR instructions in a > privileged mode. CDP, LDC, STC, MCRR, and MRRC instructions, and unprivileged > MRC or MCR instructions to CP15 cause the Undefined instruction exception to > be taken. Furthermore, `MCR p15, 0, , c7, c10, 5` (later called Data Memory Barrier) is not specified for the ARM926. Thus, SDL should not use these cache instructions on ARMv5. --- include/SDL3/SDL_atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL3/SDL_atomic.h b/include/SDL3/SDL_atomic.h index 8198e923e7d18..255417238bdc9 100644 --- a/include/SDL3/SDL_atomic.h +++ b/include/SDL3/SDL_atomic.h @@ -213,7 +213,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") -#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ #define SDL_MEMORY_BARRIER_USES_FUNCTION From e100992c17ac58c243aa5b57151189963f6d1d4b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 6 Jan 2024 06:18:13 -0800 Subject: [PATCH 674/725] Added mapping for the RX Gamepad, e.g. Pandora Box 7 Fixes https://github.com/libsdl-org/SDL/issues/8217 --- src/joystick/SDL_gamepad_db.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index a554c9cd151b9..971cc0e9bbb30 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -252,6 +252,7 @@ static const char *s_GamepadMappings[] = { "03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,", "03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,", "03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,", + "030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,", "03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000321500000204000000000000,Razer Panthera (PS3),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:a3,start:b9,x:b0,y:b3,", "03000000321500000104000000000000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", From 3a9a52fe6c40aee8d174bb756b4a339d35386633 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 6 Jan 2024 07:31:10 -0800 Subject: [PATCH 675/725] updateKeyboard should use the SDL window's screen instead of the view window's screen, which may be nil. Fixes https://github.com/libsdl-org/SDL/issues/8200 --- src/video/uikit/SDL_uikitviewcontroller.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index f1594ed740178..9874b93cfd001 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -511,12 +511,14 @@ - (void)textFieldTextDidChange:(NSNotification *)notification - (void)updateKeyboard { + SDL_UIKitWindowData *data = (__bridge SDL_UIKitWindowData *) window->driverdata; + CGAffineTransform t = self.view.transform; CGPoint offset = CGPointMake(0.0, 0.0); #if TARGET_OS_XR CGRect frame = UIKit_ComputeViewFrame(window); #else - CGRect frame = UIKit_ComputeViewFrame(window, self.view.window.screen); + CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen); #endif if (self.keyboardHeight) { From 014a63b4b5b94ce50f329eddb345f5434654305b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 6 Jan 2024 08:11:22 -0800 Subject: [PATCH 676/725] Renamed ShowTextInput/HideTextInput to ShowScreenKeyboard/HideScreenKeyboard on Android This better reflects the actual implementation and makes SDL_HINT_ENABLE_SCREEN_KEYBOARD work on Android. Fixes https://github.com/libsdl-org/SDL/issues/8652 --- src/core/android/SDL_android.c | 4 ++-- src/core/android/SDL_android.h | 4 ++-- src/video/android/SDL_androidevents.c | 10 ++++++---- src/video/android/SDL_androidkeyboard.c | 14 +++++++------- src/video/android/SDL_androidkeyboard.h | 5 ++--- src/video/android/SDL_androidvideo.c | 4 ++-- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 8b3dc1507c5f0..b4ee8b7a0f2f3 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -2239,7 +2239,7 @@ int Android_JNI_SuspendScreenSaver(SDL_bool suspend) return Android_JNI_SendMessage(COMMAND_SET_KEEP_SCREEN_ON, (suspend == SDL_FALSE) ? 0 : 1); } -void Android_JNI_ShowTextInput(SDL_Rect *inputRect) +void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput, @@ -2249,7 +2249,7 @@ void Android_JNI_ShowTextInput(SDL_Rect *inputRect) inputRect->h); } -void Android_JNI_HideTextInput(void) +void Android_JNI_HideScreenKeyboard(void) { /* has to match Activity constant */ const int COMMAND_TEXTEDIT_HIDE = 3; diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index c1256306b3465..af8ed1d47ba28 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -43,8 +43,8 @@ extern void Android_JNI_MinizeWindow(void); extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void); extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]); -extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect); -extern void Android_JNI_HideTextInput(void); +extern void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect); +extern void Android_JNI_HideScreenKeyboard(void); extern SDL_bool Android_JNI_IsScreenKeyboardShown(void); extern ANativeWindow *Android_JNI_GetNativeWindow(void); diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index a24a9f150eb87..6f92e347eca2f 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -132,8 +132,9 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this) #endif /* Make sure SW Keyboard is restored when an app becomes foreground */ - if (SDL_TextInputActive()) { - Android_StartTextInput(_this); /* Only showTextInput */ + if (SDL_TextInputActive() && + SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) { + Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */ } SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); @@ -212,8 +213,9 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this) #endif /* Make sure SW Keyboard is restored when an app becomes foreground */ - if (SDL_TextInputActive()) { - Android_StartTextInput(_this); /* Only showTextInput */ + if (SDL_TextInputActive() && + SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) { + Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */ } SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); diff --git a/src/video/android/SDL_androidkeyboard.c b/src/video/android/SDL_androidkeyboard.c index 4325faa3b6a7e..4d80397f001b5 100644 --- a/src/video/android/SDL_androidkeyboard.c +++ b/src/video/android/SDL_androidkeyboard.c @@ -341,20 +341,20 @@ SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this) return SDL_TRUE; } -SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window) +void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) { - return Android_JNI_IsScreenKeyboardShown(); + SDL_VideoData *videodata = _this->driverdata; + Android_JNI_ShowScreenKeyboard(&videodata->textRect); } -void Android_StartTextInput(SDL_VideoDevice *_this) +void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_VideoData *videodata = _this->driverdata; - Android_JNI_ShowTextInput(&videodata->textRect); + Android_JNI_HideScreenKeyboard(); } -void Android_StopTextInput(SDL_VideoDevice *_this) +SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window) { - Android_JNI_HideTextInput(); + return Android_JNI_IsScreenKeyboardShown(); } int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) diff --git a/src/video/android/SDL_androidkeyboard.h b/src/video/android/SDL_androidkeyboard.h index 0a194d63d6917..2693fa0e182e0 100644 --- a/src/video/android/SDL_androidkeyboard.h +++ b/src/video/android/SDL_androidkeyboard.h @@ -26,8 +26,7 @@ extern int Android_OnKeyDown(int keycode); extern int Android_OnKeyUp(int keycode); extern SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this); +extern void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); +extern void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); extern SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window); - -extern void Android_StartTextInput(SDL_VideoDevice *_this); -extern void Android_StopTextInput(SDL_VideoDevice *_this); extern int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index eea89b8b07c60..e000ec6963dd3 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -142,12 +142,12 @@ static SDL_VideoDevice *Android_CreateDevice(void) device->SuspendScreenSaver = Android_SuspendScreenSaver; /* Text input */ - device->StartTextInput = Android_StartTextInput; - device->StopTextInput = Android_StopTextInput; device->SetTextInputRect = Android_SetTextInputRect; /* Screen keyboard */ device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport; + device->ShowScreenKeyboard = Android_ShowScreenKeyboard; + device->HideScreenKeyboard = Android_HideScreenKeyboard; device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown; /* Clipboard */ From d3daba791aafa9a10db5b948fc33e62f75dff7e4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 6 Jan 2024 08:29:01 -0800 Subject: [PATCH 677/725] Don't try to send the PS third-party feature request to the Logitech G815 keyboard Fixes https://github.com/libsdl-org/SDL/issues/8373 --- src/joystick/hidapi/SDL_hidapijoystick.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index a3c6872b0ac46..bb1f9376f0325 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -152,8 +152,13 @@ SDL_bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product) case USB_VENDOR_HORI: return SDL_TRUE; case USB_VENDOR_LOGITECH: - /* Most Logitech devices are fine with this, but the F310 will lock up */ + /* Most Logitech devices are fine with this, but there are a few exceptions */ if (product == USB_PRODUCT_LOGITECH_F310) { + /* The Logitech F310 gamepad will lock up */ + return SDL_FALSE; + } + if (product == 0xc33f) { + /* The Logitech G815 keyboard will reset the LEDs */ return SDL_FALSE; } return SDL_TRUE; From 2348e8b6a2598af2790937a62ee49cdb02d6bd28 Mon Sep 17 00:00:00 2001 From: Semphris Date: Tue, 2 Jan 2024 13:15:32 -0500 Subject: [PATCH 678/725] Add hint to make SDL handle dbus_shutdown() --- include/SDL3/SDL_hints.h | 17 ++++++++++++++++- src/SDL.c | 6 +++--- src/core/linux/SDL_dbus.c | 10 ++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index e12093360e952..b7faa5a686ca3 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2706,7 +2706,6 @@ extern "C" { */ #define SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" - /** * Request SDL_AppIterate() be called at a specific rate. * @@ -2721,6 +2720,22 @@ extern "C" { */ #define SDL_HINT_MAIN_CALLBACK_RATE "SDL_MAIN_CALLBACK_RATE" +/** + * Let SDL handle dbus_shutdown(). + * + * Only enable this option if no other dependency uses D-Bus. + * + * This option tells SDL that it can safely call dbus_shutdown() when + * SDL_Quit() is called. You must ensure that no other library still uses + * D-Bus when SDL_Quit() is called, otherwise resources will be freed while + * they are still in use, which results in undefined behavior and likely a + * crash. + * + * Use this option to prevent memory leaks if your application doesn't use + * D-Bus other than through SDL. + */ +#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" + /** * An enumeration of hint priorities diff --git a/src/SDL.c b/src/SDL.c index d39303ffe12d4..b6b20fb97d0a5 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -517,13 +517,13 @@ void SDL_Quit(void) SDL_QuitTicks(); #endif - SDL_ClearHints(); - SDL_AssertionsQuit(); - #ifdef SDL_USE_LIBDBUS SDL_DBus_Quit(); #endif + SDL_ClearHints(); + SDL_AssertionsQuit(); + SDL_QuitProperties(); SDL_QuitLog(); diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index 8bfbec8ad0634..22b7bdea2cd1e 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -183,14 +183,12 @@ void SDL_DBus_Quit(void) dbus.connection_close(dbus.session_conn); dbus.connection_unref(dbus.session_conn); } -/* Don't do this - bug 3950 - dbus_shutdown() is a debug feature which closes all global resources in the dbus library. Calling this should be done by the app, not a library, because if there are multiple users of dbus in the process then SDL could shut it down even though another part is using it. -*/ -#if 0 - if (dbus.shutdown) { + + SDL_bool q = SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, SDL_FALSE); + if (q == SDL_TRUE && dbus.shutdown) { dbus.shutdown(); } -#endif + SDL_zero(dbus); UnloadDBUSLibrary(); SDL_free(inhibit_handle); From 3deefa6b438922d5d55cb881482f8550f51978b7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 7 Jan 2024 14:20:16 -0800 Subject: [PATCH 679/725] Updated documentation for SDL_HINT_SHUTDOWN_DBUS_ON_QUIT --- include/SDL3/SDL_hints.h | 18 +++++++++--------- src/core/linux/SDL_dbus.c | 7 ++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index b7faa5a686ca3..3319a149e39be 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2721,18 +2721,18 @@ extern "C" { #define SDL_HINT_MAIN_CALLBACK_RATE "SDL_MAIN_CALLBACK_RATE" /** - * Let SDL handle dbus_shutdown(). + * Cause SDL to call dbus_shutdown() on quit. * - * Only enable this option if no other dependency uses D-Bus. + * This is useful as a debug tool to validate memory leaks, but shouldn't ever + * be set in production applications, as other libraries used by the application + * might use dbus under the hood and this cause cause crashes if they continue + * after SDL_Quit(). * - * This option tells SDL that it can safely call dbus_shutdown() when - * SDL_Quit() is called. You must ensure that no other library still uses - * D-Bus when SDL_Quit() is called, otherwise resources will be freed while - * they are still in use, which results in undefined behavior and likely a - * crash. + * This variable can be set to the following values: + * "0" - SDL will not call dbus_shutdown() on quit (default) + * "1" - SDL will call dbus_shutdown() on quit * - * Use this option to prevent memory leaks if your application doesn't use - * D-Bus other than through SDL. + * This hint is available since SDL 3.0.0. */ #define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index 22b7bdea2cd1e..f7f5b6d62be0f 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -184,9 +184,10 @@ void SDL_DBus_Quit(void) dbus.connection_unref(dbus.session_conn); } - SDL_bool q = SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, SDL_FALSE); - if (q == SDL_TRUE && dbus.shutdown) { - dbus.shutdown(); + if (SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, SDL_FALSE)) { + if (dbus.shutdown) { + dbus.shutdown(); + } } SDL_zero(dbus); From 1a13dae2197cb4d63a21b2abe15fdd881d5f9a9a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 7 Jan 2024 16:59:41 -0800 Subject: [PATCH 680/725] Added constant definitions for SDL properties Fixes https://github.com/libsdl-org/SDL/issues/8622 --- docs/README-migration.md | 22 +-- include/SDL3/SDL_render.h | 168 +++++++---------- include/SDL3/SDL_video.h | 208 +++++++++------------ src/core/linux/SDL_fcitx.c | 6 +- src/core/linux/SDL_ibus.c | 6 +- src/render/SDL_render.c | 34 ++-- src/render/direct3d/SDL_render_d3d.c | 6 +- src/render/direct3d11/SDL_render_d3d11.c | 12 +- src/render/direct3d11/SDL_render_winrt.cpp | 2 +- src/render/direct3d12/SDL_render_d3d12.c | 18 +- src/render/metal/SDL_render_metal.m | 10 +- src/render/opengl/SDL_render_gl.c | 22 +-- src/render/opengles2/SDL_render_gles2.c | 20 +- src/render/ps2/SDL_render_ps2.c | 2 +- src/render/psp/SDL_render_psp.c | 2 +- src/render/software/SDL_render_sw.c | 2 +- src/render/vitagxm/SDL_render_vita_gxm.c | 2 +- src/test/SDL_test_common.c | 10 +- src/video/SDL_video.c | 62 +++--- src/video/android/SDL_androidwindow.c | 4 +- src/video/cocoa/SDL_cocoawindow.m | 8 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 6 +- src/video/uikit/SDL_uikitwindow.m | 4 +- src/video/vivante/SDL_vivantevideo.c | 6 +- src/video/wayland/SDL_waylandwindow.c | 32 ++-- src/video/windows/SDL_windowswindow.c | 10 +- src/video/winrt/SDL_winrtvideo.cpp | 2 +- src/video/x11/SDL_x11window.c | 8 +- test/testautomation_video.c | 14 +- test/testffmpeg.c | 4 +- 30 files changed, 322 insertions(+), 390 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index c8b0b9274b8b3..20c7216841e1a 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -1303,25 +1303,25 @@ The information previously available in SDL_GetWindowWMInfo() is now available a becomes: ```c #if defined(__WIN32__) - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL); + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); if (hwnd) { ... } #elif defined(__MACOS__) - NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL); + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER, NULL); if (nswindow) { ... } #elif defined(__LINUX__) if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.x11.display", NULL); - Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.x11.window", 0); + Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); + Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); if (xdisplay && xwindow) { ... } } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { - struct wl_display *display = (struct wl_display *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.display", NULL); - struct wl_surface *surface = (struct wl_surface *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.surface", NULL); + struct wl_display *display = (struct wl_display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, NULL); + struct wl_surface *surface = (struct wl_surface *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER, NULL); if (display && surface) { ... } @@ -1404,11 +1404,11 @@ Rather than iterating over displays using display index, there is a new function SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it, e.g. ```c SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetStringProperty(props, "title", title); - SDL_SetNumberProperty(props, "x", x); - SDL_SetNumberProperty(props, "y", y); - SDL_SetNumberProperty(props, "width", width); - SDL_SetNumberProperty(props, "height", height); + SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, title); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, x); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, y); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, width); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, height); SDL_SetNumberProperty(props, "flags", flags); pWindow = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 3923350968286..07bd031237242 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -239,15 +239,12 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * Create a 2D rendering context for a window, with the specified properties. * * These are the supported properties: - * - * - "window" (pointer) - the window where rendering is displayed - * - "surface" (pointer) - the surface where rendering is displayed, if you - * want a software renderer without a window - * - "name" (string) - the name of the rendering driver to use, if a specific - * one is desired - * - "present_vsync" (boolean) - true if you want present synchronized with - * the refresh rate - * + */ +#define SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER "window" /* the window where rendering is displayed */ +#define SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER "surface" /* the surface where rendering is displayed, if you want a software renderer without a window */ +#define SDL_PROPERTY_RENDERER_CREATE_NAME_STRING "name" /* the name of the rendering driver to use, if a specific one is desired */ +#define SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" /* true if you want present synchronized with the refresh rate */ +/* * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. @@ -325,14 +322,12 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * Get the properties associated with a renderer. * * The following read-only properties are provided by SDL: - * - * ``` - * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer - * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer - * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer - * ``` - * + */ +#define SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" /* the IDirect3DDevice9 associated with the renderer */ +#define SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" /* the ID3D11Device associated with the renderer */ +#define SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" /* the ID3D12Device associated with the renderer */ +#define SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" /* the ID3D12CommandQueue associated with the renderer */ +/* * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -439,54 +434,39 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * Create a texture for a rendering context with the specified properties. * * These are the supported properties: - * - * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, - * defaults to the best RGBA format for the renderer - * - "access" (number) - one of the enumerated values in SDL_TextureAccess, - * defaults to SDL_TEXTUREACCESS_STATIC - * - "width" (number) - the width of the texture in pixels, required - * - "height" (number) - the height of the texture in pixels, required - * + */ +#define SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER "format" /* one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer */ +#define SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER "access" /* one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC */ +#define SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER "width" /* the width of the texture in pixels, required */ +#define SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER "height" /* the height of the texture in pixels, required */ +/* * With the direct3d11 renderer: - * - * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the - * texture, if you want to wrap an existing texture. - * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. - * + */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture" /* the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ +/* * With the direct3d12 renderer: - * - * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the - * texture, if you want to wrap an existing texture. - * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. - * + */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "d3d12.texture" /* the ID3D12Resource associated with the texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ +/* * With the opengl renderer: - * - * - "opengl.texture" (number) - the GLuint texture associated with the - * texture, if you want to wrap an existing texture. - * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV - * plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengl.texture_u" (number) - the GLuint texture associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "opengl.texture_v" (number) - the GLuint texture associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. - * + */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "opengl.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ +/* * With the opengles2 renderer: - * - * - "opengles2.texture" (number) - the GLuint texture associated with the - * texture, if you want to wrap an existing texture. - * - "opengles2.texture_uv" (number) - the GLuint texture associated with the - * UV plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengles2.texture_u" (number) - the GLuint texture associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "opengles2.texture_v" (number) - the GLuint texture associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. - * + */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ +/* * \param renderer the rendering context * \param props the properties to use * \returns a pointer to the created texture or NULL if no rendering context @@ -507,51 +487,37 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * Get the properties associated with a texture. * * The following read-only properties are provided by SDL: - * + */ +/* * With the direct3d11 renderer: - * - * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated - * with the texture - * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated - * with the U plane of a YUV texture - * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated - * with the V plane of a YUV texture - * + */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" /* the ID3D11Texture2D associated with the texture */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture */ +/* * With the direct3d12 renderer: - * - * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated - * with the texture - * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated - * with the U plane of a YUV texture - * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated - * with the V plane of a YUV texture - * + */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" /* the ID3D12Resource associated with the texture */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture */ +/* * With the opengl renderer: - * - * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated - * with the texture - * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated - * with the UV plane of an NV12 texture - * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated - * with the U plane of a YUV texture - * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated - * with the V plane of a YUV texture - * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the - * texture (0.0 - 1.0) - * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the - * texture (0.0 - 1.0) - * + */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" /* the GLuint texture associated with the texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" /* the texture coordinate width of the texture (0.0 - 1.0) */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" /* the texture coordinate height of the texture (0.0 - 1.0) */ +/* * With the opengles2 renderer: - * - * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated - * with the texture - * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture - * associated with the UV plane of an NV12 texture - * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture - * associated with the U plane of a YUV texture - * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture + */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" /* the GLuint texture associated with the texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ +/* * associated with the V plane of a YUV texture - * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index d20bd0ee9ad66..c83762f10bf5f 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -808,63 +808,46 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * Create a window with the specified properties. * * These are the supported properties: - * - * - "always-on-top" (boolean) - true if the window should be always on top - * - "borderless" (boolean) - true if the window has no window decoration - * - "focusable" (boolean) - true if the window should accept keyboard input - * (defaults true) - * - "fullscreen" (boolean) - true if the window should start in fullscreen - * mode at desktop resolution - * - "height" (number) - the height of the window - * - "hidden" (boolean) - true if the window should start hidden - * - "high-pixel-density" (boolean) - true if the window uses a high pixel - * density buffer if possible - * - "maximized" (boolean) - true if the window should start maximized - * - "menu" (boolean) - true if the window is a popup menu - * - "metal" (string) - true if the window will be used with Metal rendering - * - "minimized" (boolean) - true if the window should start minimized - * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse - * focus - * - "opengl" (boolean) - true if the window will be used with OpenGL - * rendering - * - "parent" (pointer) - an SDL_Window that will be the parent of this - * window, required for windows with the "toolip" and "menu" properties - * - "resizable" (boolean) - true if the window should be resizable - * - "title" (string) - the title of the window, in UTF-8 encoding - * - "transparent" (string) - true if the window show transparent in the areas - * with alpha of 0 - * - "tooltip" (boolean) - true if the window is a tooltip - * - "utility" (boolean) - true if the window is a utility window, not showing - * in the task bar and window list - * - "vulkan" (string) - true if the window will be used with Vulkan rendering - * - "width" (number) - the width of the window - * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, - * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for - * windows with the "parent" property set. - * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, - * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for - * windows with the "parent" property set. - * - * On macOS: - * - * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated - * with the window, if you want to wrap an existing window. - * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with - * the window, defaults to [window contentView] - * - * On Windows: - * - * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want - * to wrap an existing window. - * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share - * pixel format with, useful for OpenGL windows - * - * On X11: - * - * - "x11.window" (number) - the X11 Window associated with the window, if you - * want to wrap an existing window. - * - * The SDL_Window is implicitly shown if the "hidden" property is not set. + */ +#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" /* true if the window should be always on top */ +#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" /* true if the window has no window decoration */ +#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" /* true if the window should accept keyboard input (defaults true) */ +#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" /* true if the window should start in fullscreen mode at desktop resolution */ +#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" /* the height of the window */ +#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" /* true if the window should start hidden */ +#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" /* true if the window uses a high pixel density buffer if possible */ +#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" /* true if the window should start maximized */ +#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" /* true if the window is a popup menu */ +#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" /* true if the window will be used with Metal rendering */ +#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" /* true if the window should start minimized */ +#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" /* true if the window starts with grabbed mouse focus */ +#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" /* true if the window will be used with OpenGL rendering */ +#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" /* an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties */ +#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" /* true if the window should be resizable */ +#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" /* the title of the window, in UTF-8 encoding */ +#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" /* true if the window show transparent in the areas with alpha of 0 */ +#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" /* true if the window is a tooltip */ +#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" /* true if the window is a utility window, not showing in the task bar and window list */ +#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" /* true if the window will be used with Vulkan rendering */ +#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" /* the width of the window */ +#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" /* the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. */ +#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" /* the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. */ +/* + * These are additional supported properties on macOS: + */ +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" /* the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. */ +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" /* the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] */ +/* + * These are additional supported properties on Windows: + */ +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" /* the HWND associated with the window, if you want to wrap an existing window. */ +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" /* optional, another window to share pixel format with, useful for OpenGL windows */ +/* + * These are additional supported properties with X11: + */ +#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" /* the X11 Window associated with the window, if you want to wrap an existing window. */ +/* + * The window is implicitly shown if the "hidden" property is not set. * * Windows with the "tooltip" and "menu" properties are popup windows and have * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. @@ -929,83 +912,66 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * Get the properties associated with a window. * * The following read-only properties are provided by SDL: - * + */ +/* * On Android: - * - * ``` - * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window - * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" /* the ANativeWindow associated with the window */ +#define SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" /* the EGLSurface associated with the window */ +/* * On iOS: - * - * ``` - * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window - * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" /* the (__unsafe_unretained) UIWindow associated with the window */ +#define SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" /* the NSInteger tag assocated with metal views on the window */ +/* * On KMS/DRM: - * - * ``` - * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX) - * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window - * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" /* the device index associated with the window (e.g. the X in /dev/dri/cardX) */ +#define SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" /* the DRM FD associated with the window */ +#define SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" /* the GBM device associated with the window */ +/* * On macOS: - * - * ``` - * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window - * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" /* the (__unsafe_unretained) NSWindow associated with the window */ +#define SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" /* the NSInteger tag assocated with metal views on the window */ +/* * On Vivante: - * - * ``` - * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window - * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window - * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" /* the EGLNativeDisplayType associated with the window */ +#define SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" /* the EGLNativeWindowType associated with the window */ +#define SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" /* the EGLSurface associated with the window */ +/* * On UWP: - * - * ``` - * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" /* the IInspectable CoreWindow associated with the window */ +/* * On Windows: - * - * ``` - * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window - * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window - * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" /* the HWND associated with the window */ +#define SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" /* the HDC associated with the window */ +#define SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" /* the HINSTANCE associated with the window */ +/* * On Wayland: * - * ``` - * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window - * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window - * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window - * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window - * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window - * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window - * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode - * ``` - * * Note: The xdg_* window objects do not internally persist across window * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. - * + */ +#define SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER "SDL.window.wayland.registry" /* the wl_registry associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" /* the wl_display associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" /* the wl_surface associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" /* the wl_egl_window associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" /* the xdg_surface associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" /* the xdg_toplevel role associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" /* the xdg_popup role associated with the window */ +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" /* the xdg_positioner associated with the window, in popup mode */ +/* * On X11: - * - * ``` - * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window - * "SDL.window.x11.screen" (number) - the screen number associated with the window - * "SDL.window.x11.window" (number) - the X11 Window associated with the window - * ``` - * + */ +#define SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" /* the X11 Display associated with the window */ +#define SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" /* the screen number associated with the window */ +#define SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" /* the X11 Window associated with the window */ +/* * \param window the window to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index af1689607998a..a3de3c6886dc6 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -428,9 +428,9 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL); - int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0); - Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0); + Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); + int x_screen = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER, 0); + Window x_win = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); Window unused; if (x_disp && x_win) { X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused); diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 6313f537ce5c2..a919735e7e36c 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -705,9 +705,9 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL); - int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0); - Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0); + Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); + int x_screen = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER, 0); + Window x_win = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); Window unused; if (x_disp && x_win) { diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 45ed877be0c6e..6c2a351202de6 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -805,9 +805,9 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) { #ifndef SDL_RENDER_DISABLED - SDL_Window *window = SDL_GetProperty(props, "window", NULL); - SDL_Surface *surface = SDL_GetProperty(props, "surface", NULL); - const char *name = SDL_GetStringProperty(props, "name", NULL); + SDL_Window *window = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, NULL); + SDL_Surface *surface = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER, NULL); + const char *name = SDL_GetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, NULL); SDL_Renderer *renderer = NULL; const int n = SDL_GetNumRenderDrivers(); const char *hint; @@ -838,7 +838,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); if (hint && *hint) { - SDL_SetBooleanProperty(props, "present_vsync", SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); + SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); } if (!name) { @@ -871,7 +871,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) goto error; } - if (SDL_GetBooleanProperty(props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { renderer->wanted_vsync = SDL_TRUE; if (!(renderer->info.flags & SDL_RENDERER_PRESENTVSYNC)) { @@ -947,14 +947,14 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl { SDL_Renderer *renderer; SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetProperty(props, "window", window); + SDL_SetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, window); if (flags & SDL_RENDERER_SOFTWARE) { - SDL_SetStringProperty(props, "name", "software"); + SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, "software"); } else { - SDL_SetStringProperty(props, "name", name); + SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, name); } if (flags & SDL_RENDERER_PRESENTVSYNC) { - SDL_SetBooleanProperty(props, "present_vsync", SDL_TRUE); + SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE); } renderer = SDL_CreateRendererWithProperties(props); SDL_DestroyProperties(props); @@ -1124,10 +1124,10 @@ static SDL_ScaleMode SDL_GetScaleMode(void) SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props) { SDL_Texture *texture; - Uint32 format = (Uint32)SDL_GetNumberProperty(props, "format", SDL_PIXELFORMAT_UNKNOWN); - int access = (int)SDL_GetNumberProperty(props, "access", SDL_TEXTUREACCESS_STATIC); - int w = (int)SDL_GetNumberProperty(props, "width", 0); - int h = (int)SDL_GetNumberProperty(props, "height", 0); + Uint32 format = (Uint32)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN); + int access = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); + int w = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, 0); + int h = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, 0); SDL_bool texture_is_fourcc_and_target; CHECK_RENDERER_MAGIC(renderer, NULL); @@ -1244,10 +1244,10 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access { SDL_Texture *texture; SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, "format", format); - SDL_SetNumberProperty(props, "access", access); - SDL_SetNumberProperty(props, "width", w); - SDL_SetNumberProperty(props, "height", h); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, format); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, access); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, h); texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); return texture; diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 1e15ae8f2c992..8c5ef457430e1 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1610,7 +1610,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } SDL_zero(pparams); - pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL); + pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; pparams.BackBufferCount = 1; @@ -1625,7 +1625,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro pparams.BackBufferFormat = D3DFMT_UNKNOWN; pparams.FullScreen_RefreshRateInHz = 0; } - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; @@ -1709,7 +1709,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } #endif - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d9.device", data->device); + SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER, data->device); return renderer; } diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 05052be568754..007f833c36986 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -665,7 +665,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0); ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants); - SDL_SetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", data->d3dDevice); + SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER, data->d3dDevice); done: SAFE_RELEASE(d3dDevice); @@ -829,7 +829,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) #endif } else { #if defined(__WIN32__) || defined(__WINGDK__) - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL); + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory, (IUnknown *)data->d3dDevice, @@ -1137,7 +1137,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture", textureData->mainTexture); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER, textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { @@ -1159,7 +1159,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_u", textureData->mainTextureU); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER, textureData->mainTextureU); if (GetTextureProperty(create_props, "d3d11.texture_v", &textureData->mainTextureV) < 0) { return -1; @@ -1174,7 +1174,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_v", textureData->mainTextureV); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER, textureData->mainTextureV); } if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { @@ -2488,7 +2488,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p */ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; #else - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D11_SetVSync; diff --git a/src/render/direct3d11/SDL_render_winrt.cpp b/src/render/direct3d11/SDL_render_winrt.cpp index 6c5bec8e64c32..0378ee280e4d2 100644 --- a/src/render/direct3d11/SDL_render_winrt.cpp +++ b/src/render/direct3d11/SDL_render_winrt.cpp @@ -44,7 +44,7 @@ using namespace Windows::Graphics::Display; extern "C" void * D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer) { - IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window", NULL); + IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER, NULL); ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL; if (!window || FAILED(window->QueryInterface(&coreWindow))) { return NULL; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 4c590eac7562c..1f5dafd38667b 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -324,8 +324,8 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer) SDL_Texture *texture = NULL; SDL_PropertiesID props = SDL_GetRendererProperties(renderer); - SDL_SetProperty(props, "SDL.renderer.d3d12.device", NULL); - SDL_SetProperty(props, "SDL.renderer.d3d12.command_queue", NULL); + SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER, NULL); + SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER, NULL); /* Release all textures */ for (texture = renderer->textures; texture; texture = texture->next) { @@ -1074,8 +1074,8 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) data->srvPoolHead = &data->srvPoolNodes[0]; SDL_PropertiesID props = SDL_GetRendererProperties(renderer); - SDL_SetProperty(props, "SDL.renderer.d3d12.device", data->d3dDevice); - SDL_SetProperty(props, "SDL.renderer.d3d12.command_queue", data->commandQueue); + SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER, data->d3dDevice); + SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER, data->commandQueue); done: SAFE_RELEASE(d3dDevice); @@ -1179,7 +1179,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h) swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | /* To support SetMaximumFrameLatency */ DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; /* To support presenting with allow tearing on */ - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL); + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); result = D3D_CALL(data->dxgiFactory, CreateSwapChainForHwnd, (IUnknown *)data->commandQueue, @@ -1506,7 +1506,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL } } textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST; - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture", textureData->mainTexture); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER, textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { @@ -1533,7 +1533,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL } } textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST; - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_u", textureData->mainTextureU); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER, textureData->mainTextureU); if (GetTextureProperty(create_props, "d3d12.texture_v", &textureData->mainTextureV) < 0) { return -1; @@ -1553,7 +1553,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL } } textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST; - SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_v", textureData->mainTextureV); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER, textureData->mainTextureV); } if (texture->format == SDL_PIXELFORMAT_NV12 || @@ -3027,7 +3027,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->driverdata = data; D3D12_InvalidateCachedState(renderer); - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D12_SetVSync; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 2b631540b2ae9..b471cfba50e5a 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1630,8 +1630,8 @@ static int METAL_SetVSync(SDL_Renderer *renderer, const int vsync) static SDL_MetalView GetWindowView(SDL_Window *window) { #ifdef SDL_VIDEO_DRIVER_COCOA - NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL); - NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag", 0); + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER, NULL); + NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, 0); if (nswindow && tag) { NSView *view = nswindow.contentView; if (view.subviews.count > 0) { @@ -1644,8 +1644,8 @@ static SDL_MetalView GetWindowView(SDL_Window *window) #endif #ifdef SDL_VIDEO_DRIVER_UIKIT - UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window", NULL); - NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag", 0); + UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER, NULL); + NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER, 0); if (uiwindow && tag) { UIView *view = uiwindow.rootViewController.view; if (view.tag == tag) { @@ -1924,7 +1924,7 @@ in case we want to use it later (recreating the renderer) #if (defined(__MACOS__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST if (@available(macOS 10.13, *)) { - data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE); + data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE); if (data.mtllayer.displaySyncEnabled) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index d033130b9a0ae..dc66b18c076e9 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -498,7 +498,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr data->fbo = NULL; } - data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture", 0); + data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER, 0); if (data->texture) { data->texture_external = SDL_TRUE; } else { @@ -531,9 +531,9 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr data->texh = (GLfloat)texture->h / texture_h; } SDL_PropertiesID props = SDL_GetTextureProperties(texture); - SDL_SetNumberProperty(props, "SDL.texture.opengl.texture", data->texture); - SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_w", data->texw); - SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_h", data->texh); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER, data->texture); + SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT, data->texw); + SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT, data->texh); data->format = format; data->formattype = type; @@ -592,13 +592,13 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr texture->format == SDL_PIXELFORMAT_IYUV) { data->yuv = SDL_TRUE; - data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_u", 0); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER, 0); if (data->utexture) { data->utexture_external = SDL_TRUE; } else { renderdata->glGenTextures(1, &data->utexture); } - data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_v", 0); + data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER, 0); if (data->vtexture) { data->vtexture_external = SDL_TRUE; } else { @@ -616,7 +616,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); - SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_u", data->utexture); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture); renderdata->glBindTexture(textype, data->vtexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, @@ -629,14 +629,14 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); - SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_v", data->vtexture); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture); } if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { data->nv12 = SDL_TRUE; - data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_uv", 0); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER, 0); if (data->utexture) { data->utexture_external = SDL_TRUE; } else { @@ -653,7 +653,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr GL_CLAMP_TO_EDGE); 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.texture.opengl.texture_uv", data->utexture); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture); } #endif @@ -1867,7 +1867,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea */ #endif - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index bae60b7f97495..fe6cf72cc3081 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1508,7 +1508,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL #if SDL_HAVE_YUV if (data->yuv) { - data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_v", 0); + data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER, 0); if (data->texture_v) { data->texture_v_external = SDL_TRUE; } else { @@ -1524,9 +1524,9 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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.texture.opengles2.texture_v", data->texture_v); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v); - data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_u", 0); + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER, 0); if (data->texture_u) { data->texture_u_external = SDL_TRUE; } else { @@ -1545,10 +1545,10 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } - SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", data->texture_u); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u); } else if (data->nv12) { - data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_uv", 0); + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER, 0); if (data->texture_u) { data->texture_u_external = SDL_TRUE; } else { @@ -1567,11 +1567,11 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } - SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", data->texture_u); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u); } #endif - data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture", 0); + data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER, 0); if (data->texture) { data->texture_external = SDL_TRUE; } else { @@ -1593,7 +1593,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL return -1; } } - SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", data->texture); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, data->texture); if (texture->access == SDL_TEXTUREACCESS_TARGET) { data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); @@ -2155,10 +2155,10 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c * is turned on. Not doing so will freeze the screen's contents to that * of the first drawn frame. */ - SDL_SetBooleanProperty(create_props, "present_vsync", SDL_TRUE); + SDL_SetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE); #endif - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index 1052ff4055ff3..acf177e0d5503 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -643,7 +643,7 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre data->gsGlobal = gsGlobal; dynamicVsync = SDL_GetHintBoolean(SDL_HINT_PS2_DYNAMIC_VSYNC, SDL_FALSE); - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { data->vsync = (dynamicVsync ? 2 : 1); } diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 7b88642ef3422..aa6434fd174f0 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -1345,7 +1345,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro data->most_recent_target = NULL; data->least_recent_target = NULL; - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { data->vsync = SDL_TRUE; } else { data->vsync = SDL_FALSE; diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 95bc2f57ae9bc..18c8b36e84439 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -1168,7 +1168,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea } if (no_hint_set) { - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); } else { SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0"); diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index b665543d6d808..5b902b275d260 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -260,7 +260,7 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat data->initialized = SDL_TRUE; - if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { data->displayData.wait_vblank = SDL_TRUE; renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } else { diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index b5a258f8fb862..ffca4030d4969 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1451,11 +1451,11 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state) SDL_strlcpy(title, state->window_title, SDL_arraysize(title)); } props = SDL_CreateProperties(); - SDL_SetStringProperty(props, "title", title); - SDL_SetNumberProperty(props, "x", r.x); - SDL_SetNumberProperty(props, "y", r.y); - SDL_SetNumberProperty(props, "width", r.w); - SDL_SetNumberProperty(props, "height", r.h); + SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, title); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, r.x); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, r.y); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, r.w); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, r.h); SDL_SetNumberProperty(props, "flags", state->window_flags); state->windows[i] = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 464490e922633..8efd6f0dd7481 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1916,23 +1916,23 @@ static struct { Uint32 flag; SDL_bool invert_value; } SDL_WindowFlagProperties[] = { - { "always-on-top", SDL_WINDOW_ALWAYS_ON_TOP, SDL_FALSE }, - { "borderless", SDL_WINDOW_BORDERLESS, SDL_FALSE }, - { "focusable", SDL_WINDOW_NOT_FOCUSABLE, SDL_TRUE }, - { "fullscreen", SDL_WINDOW_FULLSCREEN, SDL_FALSE }, - { "hidden", SDL_WINDOW_HIDDEN, SDL_FALSE }, - { "high-pixel-density", SDL_WINDOW_HIGH_PIXEL_DENSITY, SDL_FALSE }, - { "maximized", SDL_WINDOW_MAXIMIZED, SDL_FALSE }, - { "menu", SDL_WINDOW_POPUP_MENU, SDL_FALSE }, - { "metal", SDL_WINDOW_METAL, SDL_FALSE }, - { "minimized", SDL_WINDOW_MINIMIZED, SDL_FALSE }, - { "mouse-grabbed", SDL_WINDOW_MOUSE_GRABBED, SDL_FALSE }, - { "opengl", SDL_WINDOW_OPENGL, SDL_FALSE }, - { "resizable", SDL_WINDOW_RESIZABLE, SDL_FALSE }, - { "transparent", SDL_WINDOW_TRANSPARENT, SDL_FALSE }, - { "tooltip", SDL_WINDOW_TOOLTIP, SDL_FALSE }, - { "utility", SDL_WINDOW_UTILITY, SDL_FALSE }, - { "vulkan", SDL_WINDOW_VULKAN, SDL_FALSE } + { SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN, SDL_WINDOW_ALWAYS_ON_TOP, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN, SDL_WINDOW_BORDERLESS, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN, SDL_WINDOW_NOT_FOCUSABLE, SDL_TRUE }, + { SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN, SDL_WINDOW_FULLSCREEN, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN, SDL_WINDOW_HIDDEN, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, SDL_WINDOW_HIGH_PIXEL_DENSITY, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN, SDL_WINDOW_MAXIMIZED, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN, SDL_WINDOW_POPUP_MENU, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN, SDL_WINDOW_METAL, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN, SDL_WINDOW_MINIMIZED, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN, SDL_WINDOW_MOUSE_GRABBED, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN, SDL_WINDOW_OPENGL, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN, SDL_WINDOW_RESIZABLE, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN, SDL_WINDOW_TRANSPARENT, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN, SDL_WINDOW_TOOLTIP, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN, SDL_WINDOW_UTILITY, SDL_FALSE }, + { SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN, SDL_WINDOW_VULKAN, SDL_FALSE } }; static Uint32 SDL_GetWindowFlagProperties(SDL_PropertiesID props) @@ -1957,12 +1957,12 @@ static Uint32 SDL_GetWindowFlagProperties(SDL_PropertiesID props) SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) { SDL_Window *window; - const char *title = SDL_GetStringProperty(props, "title", NULL); - int x = (int)SDL_GetNumberProperty(props, "x", SDL_WINDOWPOS_UNDEFINED); - int y = (int)SDL_GetNumberProperty(props, "y", SDL_WINDOWPOS_UNDEFINED); - int w = (int)SDL_GetNumberProperty(props, "width", 0); - int h = (int)SDL_GetNumberProperty(props, "height", 0); - SDL_Window *parent = SDL_GetProperty(props, "parent", NULL); + const char *title = SDL_GetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, NULL); + int x = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_UNDEFINED); + int y = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_UNDEFINED); + int w = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, 0); + int h = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, 0); + SDL_Window *parent = SDL_GetProperty(props, SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER, NULL); Uint32 flags = SDL_GetWindowFlagProperties(props); Uint32 type_flags, graphics_flags; SDL_bool undefined_x = SDL_FALSE; @@ -2173,10 +2173,10 @@ SDL_Window *SDL_CreateWindow(const char *title, int w, int h, Uint32 flags) SDL_Window *window; SDL_PropertiesID props = SDL_CreateProperties(); if (title && *title) { - SDL_SetStringProperty(props, "title", title); + SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, title); } - SDL_SetNumberProperty(props, "width", w); - SDL_SetNumberProperty(props, "height", h); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, h); SDL_SetNumberProperty(props, "flags", flags); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); @@ -2194,11 +2194,11 @@ SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y return NULL; } - SDL_SetProperty(props, "parent", parent); - SDL_SetNumberProperty(props, "x", offset_x); - SDL_SetNumberProperty(props, "y", offset_y); - SDL_SetNumberProperty(props, "width", w); - SDL_SetNumberProperty(props, "height", h); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER, parent); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, offset_x); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, offset_y); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, h); SDL_SetNumberProperty(props, "flags", flags); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index 858aca0f483cf..3ef3022864a70 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -72,7 +72,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert retval = SDL_SetError("Could not fetch native window"); goto endfunction; } - SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.android.window", data->native_window); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER, data->native_window); /* Do not create EGLSurface for Vulkan window since it will then make the window incompatible with vkCreateAndroidSurfaceKHR */ @@ -87,7 +87,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert goto endfunction; } } - SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.android.surface", data->egl_surface); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface); #endif window->driverdata = data; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 5dbc04b46d423..85b1866268144 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1964,8 +1964,8 @@ then immediately ordering out (removing) the window does work. */ } SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.cocoa.window", (__bridge void *)data.nswindow); - SDL_SetNumberProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER, (__bridge void *)data.nswindow); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, SDL_METALVIEW_TAG); /* All done! */ window->driverdata = (SDL_WindowData *)CFBridgingRetain(data); @@ -1990,8 +1990,8 @@ int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie SDL_assert(false); } } else { - nswindow = (__bridge NSWindow *)SDL_GetProperty(create_props, "cocoa.window", NULL); - nsview = (__bridge NSView *)SDL_GetProperty(create_props, "cocoa.view", NULL); + nswindow = (__bridge NSWindow *)SDL_GetProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER, NULL); + nsview = (__bridge NSView *)SDL_GetProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER, NULL); } if (nswindow && !nsview) { nsview = [nswindow contentView]; diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 70dd2681393aa..d55d38cf45caf 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1465,9 +1465,9 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti window->driverdata = windata; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetNumberProperty(props, "SDL.window.kmsdrm.dev_index", viddata->devindex); - SDL_SetNumberProperty(props, "SDL.window.kmsdrm.drm_fd", viddata->drm_fd); - SDL_SetProperty(props, "SDL.window.kmsdrm.gbm_dev", viddata->gbm_dev); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER, viddata->devindex); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER, viddata->drm_fd); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER, viddata->gbm_dev); if (!is_vulkan && !vulkan_mode) { /* NON-Vulkan block. */ diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index e786ffc146a02..f16ef5b0eb84b 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -146,8 +146,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow [view setSDLWindow:window]; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.uikit.window", (__bridge void *)data.uiwindow); - SDL_SetNumberProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER, (__bridge void *)data.uiwindow); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER, SDL_METALVIEW_TAG); return 0; } diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c index ac570bc381eab..49f1525099897 100644 --- a/src/video/vivante/SDL_vivantevideo.c +++ b/src/video/vivante/SDL_vivantevideo.c @@ -254,7 +254,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert window->driverdata = data; SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.vivante.display", displaydata->native_display); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER, displaydata->native_display); #ifdef SDL_VIDEO_DRIVER_VIVANTE_VDK data->native_window = vdkCreateWindow(displaydata->native_display, window->x, window->y, window->w, window->h); @@ -264,7 +264,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert if (!data->native_window) { return SDL_SetError("VIVANTE: Can't create native window"); } - SDL_SetProperty(props, "SDL.window.vivante.window", data->native_window); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER, data->native_window); #ifdef SDL_VIDEO_OPENGL_EGL if (window->flags & SDL_WINDOW_OPENGL) { @@ -275,7 +275,7 @@ int VIVANTE_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } else { data->egl_surface = EGL_NO_SURFACE; } - SDL_SetProperty(props, "SDL.window.vivante.surface", data->egl_surface); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER, data->egl_surface); #endif /* Window has been successfully created */ diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index b7a3ce0bf297e..249cbcb34b13d 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1471,8 +1471,8 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id); libdecor_frame_map(data->shell_surface.libdecor.frame); - SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame)); - SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame)); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame)); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame)); } } else #endif @@ -1480,7 +1480,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface); xdg_surface_set_user_data(data->shell_surface.xdg.surface, data); xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data); - SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.wayland.xdg_surface", data->shell_surface.xdg.surface); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, data->shell_surface.xdg.surface); if (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { SDL_Window *parent = window->parent; @@ -1533,13 +1533,13 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - SDL_SetProperty(props, "SDL.window.wayland.xdg_popup", data->shell_surface.xdg.roleobj.popup.popup); - SDL_SetProperty(props, "SDL.window.wayland.xdg_positioner", data->shell_surface.xdg.roleobj.popup.positioner); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.roleobj.popup.popup); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER, data->shell_surface.xdg.roleobj.popup.positioner); } else { data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface); xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id); xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data); - SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", data->shell_surface.xdg.roleobj.toplevel); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.roleobj.toplevel); } } @@ -1675,8 +1675,8 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup) popupdata->shell_surface.xdg.roleobj.popup.positioner = NULL; SDL_PropertiesID props = SDL_GetWindowProperties(popup); - SDL_SetProperty(props, "SDL.window.wayland.xdg_popup", NULL); - SDL_SetProperty(props, "SDL.window.wayland.xdg_positioner", NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER, NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER, NULL); } void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) @@ -1711,8 +1711,8 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) libdecor_frame_unref(wind->shell_surface.libdecor.frame); wind->shell_surface.libdecor.frame = NULL; - SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", NULL); - SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL); } } else #endif @@ -1722,12 +1722,12 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) } else if (wind->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel); wind->shell_surface.xdg.roleobj.toplevel = NULL; - SDL_SetProperty(props, "SDL.window.wayland.xdg_toplevel", NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL); } if (wind->shell_surface.xdg.surface) { xdg_surface_destroy(wind->shell_surface.xdg.surface); wind->shell_surface.xdg.surface = NULL; - SDL_SetProperty(props, "SDL.window.wayland.xdg_surface", NULL); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL); } } @@ -2158,10 +2158,10 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.wayland.registry", c->registry); - SDL_SetProperty(props, "SDL.window.wayland.display", data->waylandData->display); - SDL_SetProperty(props, "SDL.window.wayland.surface", data->surface); - SDL_SetProperty(props, "SDL.window.wayland.egl_window", data->egl_window); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER, c->registry); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, data->waylandData->display); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER, data->surface); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER, data->egl_window); data->hit_test_result = SDL_HITTEST_NORMAL; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 0f54a73dabd8b..38a9055a3f4f4 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -476,9 +476,9 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd } SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, "SDL.window.win32.hwnd", data->hwnd); - SDL_SetProperty(props, "SDL.window.win32.hdc", data->hdc); - SDL_SetProperty(props, "SDL.window.win32.instance", data->hinstance); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, data->hwnd); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER, data->hdc); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER, data->hinstance); /* All done! */ return 0; @@ -578,7 +578,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window) int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { - HWND hwnd = (HWND)SDL_GetProperty(create_props, "win32.hwnd", SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL)); + HWND hwnd = (HWND)SDL_GetProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER, SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL)); HWND parent = NULL; if (hwnd) { window->flags |= SDL_WINDOW_EXTERNAL; @@ -655,7 +655,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI } } - HWND share_hwnd = (HWND)SDL_GetProperty(create_props, "win32.pixel_format_hwnd", NULL); + HWND share_hwnd = (HWND)SDL_GetProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER, NULL); if (share_hwnd) { HDC hdc = GetDC(share_hwnd); int pixel_format = GetPixelFormat(hdc); diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index b2b307f2a69f1..973730e1b9b67 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -606,7 +606,7 @@ int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie data->appView = ApplicationView::GetForCurrentView(); #endif } - SDL_SetProperty(SDL_GetWindowProperties(window), "SDL.window.winrt.window", reinterpret_cast(data->coreWindow.Get())); + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER, reinterpret_cast(data->coreWindow.Get())); /* Make note of the requested window flags, before they start getting changed. */ const Uint32 requestedFlags = window->flags; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 7e95621ca5ae8..cda57897b9f08 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -392,9 +392,9 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) SDL_PropertiesID props = SDL_GetWindowProperties(window); int screen = (displaydata ? displaydata->screen : 0); - SDL_SetProperty(props, "SDL.window.x11.display", data->videodata->display); - SDL_SetNumberProperty(props, "SDL.window.x11.screen", screen); - SDL_SetNumberProperty(props, "SDL.window.x11.window", data->xwindow); + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, data->videodata->display); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER, screen); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, data->xwindow); /* All done! */ window->driverdata = data; @@ -433,7 +433,7 @@ static void SetWindowBordered(Display *display, int screen, Window window, SDL_b int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) { - Window w = (Window)SDL_GetNumberProperty(create_props, "x11.window", + Window w = (Window)SDL_GetNumberProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER, (Window)SDL_GetProperty(create_props, "sdl2-compat.external_window", NULL)); if (w) { window->flags |= SDL_WINDOW_EXTERNAL; diff --git a/test/testautomation_video.c b/test/testautomation_video.c index beaeee5fd03cf..6c4001d7c7c0c 100644 --- a/test/testautomation_video.c +++ b/test/testautomation_video.c @@ -1764,12 +1764,12 @@ static int video_setWindowCenteredOnDisplay(void *arg) expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2)); props = SDL_CreateProperties(); - SDL_SetStringProperty(props, "title", title); - SDL_SetNumberProperty(props, "x", x); - SDL_SetNumberProperty(props, "w", y); - SDL_SetNumberProperty(props, "width", w); - SDL_SetNumberProperty(props, "height", h); - SDL_SetBooleanProperty(props, "borderless", SDL_TRUE); + SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, title); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, x); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, y); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, h); + SDL_SetBooleanProperty(props, SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN, SDL_TRUE); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); @@ -1961,7 +1961,7 @@ static int video_getSetWindowState(void *arg) SDL_GetWindowSize(window, &windowedW, &windowedH); SDLTest_AssertPass("SDL_GetWindowSize()"); - + SDL_GetWindowPosition(window, &windowedX, &windowedY); SDLTest_AssertPass("SDL_GetWindowPosition()"); diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 338063a8ceb33..db7c2accb752a 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -145,7 +145,7 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver) #endif #ifdef __WIN32__ - d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", NULL); + d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER, NULL); if (d3d11_device) { ID3D11Device_AddRef(d3d11_device); ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context); @@ -622,7 +622,7 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) } } - ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture", NULL); + ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER, NULL); if (!dx11_resource) { SDL_SetError("Couldn't get texture ID3D11Resource interface"); return SDL_FALSE; From 4d5bffc3230576434bf8b46a756054d6bcab2d11 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 01:02:25 +0000 Subject: [PATCH 681/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 173 ++++++++++++++++++++++++++++++++++++++ include/SDL3/SDL_video.h | 166 ++++++++++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 07bd031237242..5780c29b904dc 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -256,6 +256,31 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * \sa SDL_DestroyRenderer * \sa SDL_GetRendererInfo */ + +/** + * Create a 2D rendering context for a window, with the specified properties. + * + * These are the supported properties: + * + * - "window" (pointer) - the window where rendering is displayed + * - "surface" (pointer) - the surface where rendering is displayed, if you + * want a software renderer without a window + * - "name" (string) - the name of the rendering driver to use, if a specific + * one is desired + * - "present_vsync" (boolean) - true if you want present synchronized with + * the refresh rate + * + * \param props the properties to use + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_CreateSoftwareRenderer + * \sa SDL_DestroyRenderer + * \sa SDL_GetRendererInfo + */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); /** @@ -337,6 +362,28 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * \sa SDL_GetProperty * \sa SDL_SetProperty */ + +/** + * Get the properties associated with a renderer. + * + * The following read-only properties are provided by SDL: + * + * ``` + * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer + * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer + * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer + * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer + * ``` + * + * \param renderer the rendering context + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); /** @@ -481,6 +528,73 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * \sa SDL_QueryTexture * \sa SDL_UpdateTexture */ + +/** + * Create a texture for a rendering context with the specified properties. + * + * These are the supported properties: + * + * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, + * defaults to the best RGBA format for the renderer + * - "access" (number) - one of the enumerated values in SDL_TextureAccess, + * defaults to SDL_TEXTUREACCESS_STATIC + * - "width" (number) - the width of the texture in pixels, required + * - "height" (number) - the height of the texture in pixels, required + * + * With the direct3d11 renderer: + * + * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the + * texture, if you want to wrap an existing texture. + * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. + * + * With the direct3d12 renderer: + * + * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the + * texture, if you want to wrap an existing texture. + * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. + * + * With the opengl renderer: + * + * - "opengl.texture" (number) - the GLuint texture associated with the + * texture, if you want to wrap an existing texture. + * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV + * plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengl.texture_u" (number) - the GLuint texture associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "opengl.texture_v" (number) - the GLuint texture associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. + * + * With the opengles2 renderer: + * + * - "opengles2.texture" (number) - the GLuint texture associated with the + * texture, if you want to wrap an existing texture. + * - "opengles2.texture_uv" (number) - the GLuint texture associated with the + * UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengles2.texture_u" (number) - the GLuint texture associated with the U + * plane of a YUV texture, if you want to wrap an existing texture. + * - "opengles2.texture_v" (number) - the GLuint texture associated with the V + * plane of a YUV texture, if you want to wrap an existing texture. + * + * \param renderer the rendering context + * \param props the properties to use + * \returns a pointer to the created texture or NULL if no rendering context + * was active, the format was unsupported, or the width or height + * were out of range; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTexture + * \sa SDL_DestroyTexture + * \sa SDL_QueryTexture + * \sa SDL_UpdateTexture + */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); /** @@ -527,6 +641,65 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * \sa SDL_GetProperty * \sa SDL_SetProperty */ + +/** + * Get the properties associated with a texture. + * + * The following read-only properties are provided by SDL: + * + * With the direct3d11 renderer: + * + * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated + * with the texture + * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated + * with the U plane of a YUV texture + * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated + * with the V plane of a YUV texture + * + * With the direct3d12 renderer: + * + * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated + * with the texture + * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated + * with the U plane of a YUV texture + * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated + * with the V plane of a YUV texture + * + * With the opengl renderer: + * + * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated + * with the texture + * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated + * with the UV plane of an NV12 texture + * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated + * with the U plane of a YUV texture + * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated + * with the V plane of a YUV texture + * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the + * texture (0.0 - 1.0) + * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the + * texture (0.0 - 1.0) + * + * With the opengles2 renderer: + * + * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated + * with the texture + * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture + * associated with the UV plane of an NV12 texture + * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture + * associated with the U plane of a YUV texture + * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture + * associated with the V plane of a YUV texture + * + * \param texture the texture to query + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); /** diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index c83762f10bf5f..6c21be09c9ec7 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -861,6 +861,81 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * \sa SDL_CreateWindow * \sa SDL_DestroyWindow */ + +/** + * Create a window with the specified properties. + * + * These are the supported properties: + * + * - "always-on-top" (boolean) - true if the window should be always on top + * - "borderless" (boolean) - true if the window has no window decoration + * - "focusable" (boolean) - true if the window should accept keyboard input + * (defaults true) + * - "fullscreen" (boolean) - true if the window should start in fullscreen + * mode at desktop resolution + * - "height" (number) - the height of the window + * - "hidden" (boolean) - true if the window should start hidden + * - "high-pixel-density" (boolean) - true if the window uses a high pixel + * density buffer if possible + * - "maximized" (boolean) - true if the window should start maximized + * - "menu" (boolean) - true if the window is a popup menu + * - "metal" (string) - true if the window will be used with Metal rendering + * - "minimized" (boolean) - true if the window should start minimized + * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse + * focus + * - "opengl" (boolean) - true if the window will be used with OpenGL + * rendering + * - "parent" (pointer) - an SDL_Window that will be the parent of this + * window, required for windows with the "toolip" and "menu" properties + * - "resizable" (boolean) - true if the window should be resizable + * - "title" (string) - the title of the window, in UTF-8 encoding + * - "transparent" (string) - true if the window show transparent in the areas + * with alpha of 0 + * - "tooltip" (boolean) - true if the window is a tooltip + * - "utility" (boolean) - true if the window is a utility window, not showing + * in the task bar and window list + * - "vulkan" (string) - true if the window will be used with Vulkan rendering + * - "width" (number) - the width of the window + * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, + * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for + * windows with the "parent" property set. + * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, + * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for + * windows with the "parent" property set. + * + * On macOS: + * + * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated + * with the window, if you want to wrap an existing window. + * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with + * the window, defaults to [window contentView] + * + * On Windows: + * + * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want + * to wrap an existing window. + * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share + * pixel format with, useful for OpenGL windows + * + * On X11: + * + * - "x11.window" (number) - the X11 Window associated with the window, if you + * want to wrap an existing window. + * + * The SDL_Window is implicitly shown if the "hidden" property is not set. + * + * Windows with the "tooltip" and "menu" properties are popup windows and have + * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. + * + * \param props the properties to use + * \returns the window that was created or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateWindow + * \sa SDL_DestroyWindow + */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); /** @@ -981,6 +1056,97 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * \sa SDL_GetProperty * \sa SDL_SetProperty */ + +/** + * Get the properties associated with a window. + * + * The following read-only properties are provided by SDL: + * + * On Android: + * + * ``` + * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window + * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window + * ``` + * + * On iOS: + * + * ``` + * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window + * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window + * ``` + * + * On KMS/DRM: + * + * ``` + * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX) + * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window + * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window + * ``` + * + * On macOS: + * + * ``` + * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window + * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window + * ``` + * + * On Vivante: + * + * ``` + * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window + * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window + * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window + * ``` + * + * On UWP: + * + * ``` + * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window + * ``` + * + * On Windows: + * + * ``` + * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window + * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window + * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window + * ``` + * + * On Wayland: + * + * ``` + * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window + * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window + * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window + * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window + * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window + * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window + * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window + * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode + * ``` + * + * Note: The xdg_* window objects do not internally persist across window + * show/hide calls. They will be null if the window is hidden and must be + * queried each time it is shown. + * + * On X11: + * + * ``` + * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window + * "SDL.window.x11.screen" (number) - the screen number associated with the window + * "SDL.window.x11.window" (number) - the X11 Window associated with the window + * ``` + * + * \param window the window to query + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetProperty + * \sa SDL_SetProperty + */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); /** From 7eae08cfc4d7bb7642590a573c1263247c95ea22 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 7 Jan 2024 18:02:49 -0800 Subject: [PATCH 682/725] Removed SDL_GL_BindTexture() and SDL_GL_UnbindTexture() Now that we have the OpenGL texture properties, you can directly bind them yourself. Fixes https://github.com/libsdl-org/SDL/issues/2124 --- docs/README-migration.md | 2 + include/SDL3/SDL_render.h | 54 ------------- src/dynapi/SDL_dynapi.sym | 2 - src/dynapi/SDL_dynapi_overrides.h | 2 - src/dynapi/SDL_dynapi_procs.h | 2 - src/render/SDL_render.c | 32 -------- src/render/SDL_sysrender.h | 3 - src/render/opengl/SDL_render_gl.c | 103 +----------------------- src/render/opengles2/SDL_render_gles2.c | 53 ------------ test/testffmpeg.c | 14 +++- 10 files changed, 13 insertions(+), 254 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 20c7216841e1a..959fd0def2522 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -959,6 +959,8 @@ The following functions have been renamed: * SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow() The following functions have been removed: +* SDL_GL_BindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and bind the texture directly +* SDL_GL_UnbindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and unbind the texture directly * SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead * SDL_RenderGetIntegerScale() * SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 5780c29b904dc..e689b94c202d1 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1746,60 +1746,6 @@ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); */ extern DECLSPEC int SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer); - -/** - * Bind an OpenGL/ES/ES2 texture to the current context. - * - * This is for use with OpenGL instructions when rendering OpenGL primitives - * directly. - * - * If not NULL, `texw` and `texh` will be filled with the width and height - * values suitable for the provided texture. In most cases, both will be 1.0, - * however, on systems that support the GL_ARB_texture_rectangle extension, - * these values will actually be the pixel width and height used to create the - * texture, so this factor needs to be taken into account when providing - * texture coordinates to OpenGL. - * - * You need a renderer to create an SDL_Texture, therefore you can only use - * this function with an implicit OpenGL context from SDL_CreateRenderer(), - * not with your own OpenGL context. If you need control over your OpenGL - * context, you need to write your own texture-loading methods. - * - * Also note that SDL may upload RGB textures as BGR (or vice-versa), and - * re-order the color channels in the shaders phase, so the uploaded texture - * may have swapped color channels. - * - * \param texture the texture to bind to the current OpenGL/ES/ES2 context - * \param texw a pointer to a float value which will be filled with the - * texture width or NULL if you don't need that value - * \param texh a pointer to a float value which will be filled with the - * texture height or NULL if you don't need that value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GL_MakeCurrent - * \sa SDL_GL_UnbindTexture - */ -extern DECLSPEC int SDLCALL SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh); - -/** - * Unbind an OpenGL/ES/ES2 texture from the current context. - * - * See SDL_GL_BindTexture() for examples on how to use these functions - * - * \param texture the texture to unbind from the current OpenGL/ES/ES2 context - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GL_BindTexture - * \sa SDL_GL_MakeCurrent - */ -extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture); - /** * Get the CAMetalLayer associated with the given Metal renderer. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index a72032cd281e7..4e3ea9e52ae16 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -110,7 +110,6 @@ SDL3_0.0.0 { SDL_FlushRenderer; SDL_GDKGetTaskQueue; SDL_GDKSuspendComplete; - SDL_GL_BindTexture; SDL_GL_CreateContext; SDL_GL_DeleteContext; SDL_GL_ExtensionSupported; @@ -125,7 +124,6 @@ SDL3_0.0.0 { SDL_GL_SetAttribute; SDL_GL_SetSwapInterval; SDL_GL_SwapWindow; - SDL_GL_UnbindTexture; SDL_GL_UnloadLibrary; SDL_GUIDFromString; SDL_GUIDToString; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 52abfed6b9c11..0e2636fa4f4f6 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -134,7 +134,6 @@ #define SDL_FlushRenderer SDL_FlushRenderer_REAL #define SDL_GDKGetTaskQueue SDL_GDKGetTaskQueue_REAL #define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL -#define SDL_GL_BindTexture SDL_GL_BindTexture_REAL #define SDL_GL_CreateContext SDL_GL_CreateContext_REAL #define SDL_GL_DeleteContext SDL_GL_DeleteContext_REAL #define SDL_GL_ExtensionSupported SDL_GL_ExtensionSupported_REAL @@ -149,7 +148,6 @@ #define SDL_GL_SetAttribute SDL_GL_SetAttribute_REAL #define SDL_GL_SetSwapInterval SDL_GL_SetSwapInterval_REAL #define SDL_GL_SwapWindow SDL_GL_SwapWindow_REAL -#define SDL_GL_UnbindTexture SDL_GL_UnbindTexture_REAL #define SDL_GL_UnloadLibrary SDL_GL_UnloadLibrary_REAL #define SDL_GUIDFromString SDL_GUIDFromString_REAL #define SDL_GUIDToString SDL_GUIDToString_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 04cb56bc7c107..fbd18f1b8ef8a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -194,7 +194,6 @@ SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, SDL_FlashOperation b),(a,b), SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),) SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),) SDL_DYNAPI_PROC(int,SDL_FlushRenderer,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_BindTexture,(SDL_Texture *a, float *b, float *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GL_DeleteContext,(SDL_GLContext a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GL_ExtensionSupported,(const char *a),(a),return) @@ -209,7 +208,6 @@ SDL_DYNAPI_PROC(void,SDL_GL_ResetAttributes,(void),(),) SDL_DYNAPI_PROC(int,SDL_GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GL_SetSwapInterval,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_GL_SwapWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_UnbindTexture,(SDL_Texture *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GL_UnloadLibrary,(void),(),) SDL_DYNAPI_PROC(SDL_GUID,SDL_GUIDFromString,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GUIDToString,(SDL_GUID a, char *b, int c),(a,b,c),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 6c2a351202de6..76f8074e8ae8d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -4153,38 +4153,6 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) renderer->DestroyRenderer(renderer); } -int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh) -{ - SDL_Renderer *renderer; - - CHECK_TEXTURE_MAGIC(texture, -1); - renderer = texture->renderer; - if (texture->native) { - return SDL_GL_BindTexture(texture->native, texw, texh); - } else if (renderer && renderer->GL_BindTexture) { - FlushRenderCommandsIfTextureNeeded(texture); /* in case the app is going to mess with it. */ - return renderer->GL_BindTexture(renderer, texture, texw, texh); - } else { - return SDL_Unsupported(); - } -} - -int SDL_GL_UnbindTexture(SDL_Texture *texture) -{ - SDL_Renderer *renderer; - - CHECK_TEXTURE_MAGIC(texture, -1); - renderer = texture->renderer; - if (texture->native) { - return SDL_GL_UnbindTexture(texture->native); - } else if (renderer && renderer->GL_UnbindTexture) { - FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */ - return renderer->GL_UnbindTexture(renderer, texture); - } - - return SDL_Unsupported(); -} - void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index b1f82cb8534a7..ec4b34ab0bacf 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -209,9 +209,6 @@ struct SDL_Renderer int (*SetVSync)(SDL_Renderer *renderer, int vsync); - int (*GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh); - int (*GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture); - void *(*GetMetalLayer)(SDL_Renderer *renderer); void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer); diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index dc66b18c076e9..5baa897255365 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1145,7 +1145,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const } /* This is a little awkward but should avoid texcoord arrays getting into - a bad state if SDL_GL_BindTexture/UnbindTexture are called. */ + a bad state if the application is manually binding textures */ if (texture_array != data->drawstate.texture_array) { if (texture_array) { data->glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1610,105 +1610,6 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer); } -static int GL_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh) -{ - GL_RenderData *data = (GL_RenderData *)renderer->driverdata; - GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata; - const GLenum textype = data->textype; - - GL_ActivateRenderer(renderer); - - data->glEnable(textype); -#if SDL_HAVE_YUV - if (texturedata->yuv) { - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE2_ARB); - } - data->glBindTexture(textype, texturedata->vtexture); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } - data->glBindTexture(textype, texturedata->utexture); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - } - if (texturedata->nv12) { - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } - data->glBindTexture(textype, texturedata->utexture); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - } -#endif - data->glBindTexture(textype, texturedata->texture); - - data->drawstate.texturing = SDL_TRUE; - data->drawstate.texture = texture; - - if (texw) { - *texw = (float)texturedata->texw; - } - if (texh) { - *texh = (float)texturedata->texh; - } - return 0; -} - -static int GL_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture) -{ - GL_RenderData *data = (GL_RenderData *)renderer->driverdata; - const GLenum textype = data->textype; -#if SDL_HAVE_YUV - GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata; -#endif - - GL_ActivateRenderer(renderer); - -#if SDL_HAVE_YUV - if (texturedata->yuv) { - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE2_ARB); - } - data->glBindTexture(textype, 0); - data->glDisable(textype); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } - data->glBindTexture(textype, 0); - data->glDisable(textype); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - } - if (texturedata->nv12) { - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } - data->glBindTexture(textype, 0); - data->glDisable(textype); - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE0_ARB); - } - } -#endif - data->glBindTexture(textype, 0); - data->glDisable(textype); - - data->drawstate.texturing = SDL_FALSE; - data->drawstate.texture = NULL; - - return 0; -} - static int GL_SetVSync(SDL_Renderer *renderer, const int vsync) { int retval; @@ -1828,8 +1729,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea renderer->DestroyTexture = GL_DestroyTexture; renderer->DestroyRenderer = GL_DestroyRenderer; renderer->SetVSync = GL_SetVSync; - renderer->GL_BindTexture = GL_BindTexture; - renderer->GL_UnbindTexture = GL_UnbindTexture; renderer->info = GL_RenderDriver.info; renderer->info.flags = 0; /* will set some flags below. */ renderer->driverdata = data; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index fe6cf72cc3081..49e0139c634bb 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -2013,57 +2013,6 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync) return retval; } -/************************************************************************************************* - * Bind/unbinding of textures - *************************************************************************************************/ -static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh) -{ - GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; - GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; - GLES2_ActivateRenderer(renderer); - -#if SDL_HAVE_YUV - if (texturedata->yuv) { - data->glActiveTexture(GL_TEXTURE2); - data->glBindTexture(texturedata->texture_type, texturedata->texture_v); - - data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(texturedata->texture_type, texturedata->texture_u); - - data->glActiveTexture(GL_TEXTURE0); - } else if (texturedata->nv12) { - data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(texturedata->texture_type, texturedata->texture_u); - - data->glActiveTexture(GL_TEXTURE0); - } -#endif - - data->glBindTexture(texturedata->texture_type, texturedata->texture); - data->drawstate.texture = texture; - - if (texw) { - *texw = 1.0; - } - if (texh) { - *texh = 1.0; - } - - return 0; -} - -static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture) -{ - GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata; - GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; - GLES2_ActivateRenderer(renderer); - - data->glBindTexture(texturedata->texture_type, 0); - data->drawstate.texture = NULL; - - return 0; -} - /************************************************************************************************* * Renderer instantiation * *************************************************************************************************/ @@ -2220,8 +2169,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c renderer->DestroyTexture = GLES2_DestroyTexture; renderer->DestroyRenderer = GLES2_DestroyRenderer; renderer->SetVSync = GLES2_SetVSync; - renderer->GL_BindTexture = GLES2_BindTexture; - renderer->GL_UnbindTexture = GLES2_UnbindTexture; #if SDL_HAVE_YUV renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; diff --git a/test/testffmpeg.c b/test/testffmpeg.c index db7c2accb752a..d865a8d30d295 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -508,6 +508,8 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0]; int i, j, image_index, num_planes; EGLDisplay display = eglGetCurrentDisplay(); + SDL_PropertiesID props; + GLuint textures[2]; /* FIXME: Assuming NV12 data format */ num_planes = 0; @@ -536,8 +538,13 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE); SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR); - /* Bind the texture for importing */ - SDL_GL_BindTexture(*texture, NULL, NULL); + props = SDL_GetTextureProperties(*texture); + textures[0] = (GLuint)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0); + textures[1] = (GLuint)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0); + if (!textures[0] || !textures[1]) { + SDL_SetError("Couldn't get NV12 OpenGL textures"); + return SDL_FALSE; + } /* import the frame into OpenGL */ image_index = 0; @@ -559,13 +566,12 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) EGLImage pImage = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr); glActiveTextureARBFunc(GL_TEXTURE0_ARB + image_index); + glBindTexture(GL_TEXTURE_2D, textures[image_index]); glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, pImage); ++image_index; } } - SDL_GL_UnbindTexture(*texture); - return SDL_TRUE; #else return SDL_FALSE; From 9bc7cfc755baf055b0ac133712c4c5b3049fa302 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jan 2024 10:17:38 -0500 Subject: [PATCH 683/725] render: Added SDL_GetTextureRenderer(). --- include/SDL3/SDL_render.h | 17 +++++++++++++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/render/SDL_render.c | 6 ++++++ 5 files changed, 26 insertions(+) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index e689b94c202d1..7005f78f837e0 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -702,6 +702,23 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); +/** + * Get the renderer that created an SDL_Texture. + * + * \param texture the texture to query + * \returns a pointer to the SDL_Renderer that created the texture, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateTexture + * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTextureWithProperties + */ +extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetTextureRenderer(SDL_Texture *texture); + /** * Query the attributes of a texture. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 4e3ea9e52ae16..51f3629b81514 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -961,6 +961,7 @@ SDL3_0.0.0 { SDL_wcsnstr; SDL_SyncWindow; SDL_GetGamepadSteamHandle; + SDL_GetTextureRenderer; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 0e2636fa4f4f6..ddd57de6a69ac 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -986,3 +986,4 @@ #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_SyncWindow SDL_SyncWindow_REAL #define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL +#define SDL_GetTextureRenderer SDL_GetTextureRenderer_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index fbd18f1b8ef8a..7d92febecd76f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1011,3 +1011,4 @@ SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b, SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetTextureRenderer,(SDL_Texture *a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 76f8074e8ae8d..66453024b5261 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1396,6 +1396,12 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s return texture; } +SDL_Renderer *SDL_GetTextureRenderer(SDL_Texture *texture) +{ + CHECK_TEXTURE_MAGIC(texture, NULL); + return texture->renderer; +} + SDL_PropertiesID SDL_GetTextureProperties(SDL_Texture *texture) { CHECK_TEXTURE_MAGIC(texture, 0); From 4ffec098b769e59784191239268c1d232f068657 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 15:18:26 +0000 Subject: [PATCH 684/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 7005f78f837e0..cf66dae187a25 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -706,8 +706,8 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t * Get the renderer that created an SDL_Texture. * * \param texture the texture to query - * \returns a pointer to the SDL_Renderer that created the texture, or NULL - * on failure; call SDL_GetError() for more information. + * \returns a pointer to the SDL_Renderer that created the texture, or NULL on + * failure; call SDL_GetError() for more information. * * \threadsafety It is safe to call this function from any thread. * From adef35b9ec385e8f68289acfd2cb7a5252feacbb Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jan 2024 12:13:18 -0500 Subject: [PATCH 685/725] include: Attempt to make new properties documentation wiki bridge friendly. --- include/SDL3/SDL_render.h | 308 ++++++++++----------------------- include/SDL3/SDL_video.h | 346 +++++++++++++------------------------- 2 files changed, 210 insertions(+), 444 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index cf66dae187a25..69a5d612927b2 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -239,36 +239,12 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * Create a 2D rendering context for a window, with the specified properties. * * These are the supported properties: - */ -#define SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER "window" /* the window where rendering is displayed */ -#define SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER "surface" /* the surface where rendering is displayed, if you want a software renderer without a window */ -#define SDL_PROPERTY_RENDERER_CREATE_NAME_STRING "name" /* the name of the rendering driver to use, if a specific one is desired */ -#define SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" /* true if you want present synchronized with the refresh rate */ -/* - * \param props the properties to use - * \returns a valid rendering context or NULL if there was an error; call - * SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateRenderer - * \sa SDL_CreateSoftwareRenderer - * \sa SDL_DestroyRenderer - * \sa SDL_GetRendererInfo - */ - -/** - * Create a 2D rendering context for a window, with the specified properties. - * - * These are the supported properties: + * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER` ("window"): the window where rendering is displayed + * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER` ("surface"): the surface where rendering is displayed, if you want a software renderer without a window + * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING` ("name"): the name of the rendering driver to use, if a specific one is desired + * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN` ("present_vsync"): true if you want present synchronized with the refresh rate * - * - "window" (pointer) - the window where rendering is displayed - * - "surface" (pointer) - the surface where rendering is displayed, if you - * want a software renderer without a window - * - "name" (string) - the name of the rendering driver to use, if a specific - * one is desired - * - "present_vsync" (boolean) - true if you want present synchronized with - * the refresh rate * * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call @@ -283,6 +259,11 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); +#define SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER "window" +#define SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER "surface" +#define SDL_PROPERTY_RENDERER_CREATE_NAME_STRING "name" +#define SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" + /** * Create a 2D software rendering context for a surface. * @@ -347,34 +328,12 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * Get the properties associated with a renderer. * * The following read-only properties are provided by SDL: - */ -#define SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" /* the IDirect3DDevice9 associated with the renderer */ -#define SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" /* the ID3D11Device associated with the renderer */ -#define SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" /* the ID3D12Device associated with the renderer */ -#define SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" /* the ID3D12CommandQueue associated with the renderer */ -/* - * \param renderer the rendering context - * \returns a valid property ID on success or 0 on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty - */ - -/** - * Get the properties associated with a renderer. - * - * The following read-only properties are provided by SDL: - * - * ``` - * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer - * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer - * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer - * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer - * ``` * + * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER` ("SDL.renderer.d3d9.device"): the IDirect3DDevice9 associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER` ("SDL.renderer.d3d11.device"): the ID3D11Device associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER` ("SDL.renderer.d3d12.device"): the ID3D12Device associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER` ("SDL.renderer.d3d12.command_queue"): the ID3D12CommandQueue associated with the renderer +/* * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -386,6 +345,11 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); +#define SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" +#define SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" +#define SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" +#define SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" + /** * Get the output size in pixels of a rendering context. * @@ -481,105 +445,38 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * Create a texture for a rendering context with the specified properties. * * These are the supported properties: - */ -#define SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER "format" /* one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer */ -#define SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER "access" /* one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC */ -#define SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER "width" /* the width of the texture in pixels, required */ -#define SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER "height" /* the height of the texture in pixels, required */ -/* - * With the direct3d11 renderer: - */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture" /* the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ -/* - * With the direct3d12 renderer: - */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "d3d12.texture" /* the ID3D12Resource associated with the texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ -/* - * With the opengl renderer: - */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "opengl.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ -/* - * With the opengles2 renderer: - */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" /* the GLuint texture associated with the texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. */ -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. */ -/* - * \param renderer the rendering context - * \param props the properties to use - * \returns a pointer to the created texture or NULL if no rendering context - * was active, the format was unsupported, or the width or height - * were out of range; call SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateTextureFromSurface - * \sa SDL_CreateTexture - * \sa SDL_DestroyTexture - * \sa SDL_QueryTexture - * \sa SDL_UpdateTexture - */ - -/** - * Create a texture for a rendering context with the specified properties. - * - * These are the supported properties: - * - * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, - * defaults to the best RGBA format for the renderer - * - "access" (number) - one of the enumerated values in SDL_TextureAccess, - * defaults to SDL_TEXTUREACCESS_STATIC - * - "width" (number) - the width of the texture in pixels, required - * - "height" (number) - the height of the texture in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER` ("format"): one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer + * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER` ("access"): one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC + * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER` ("width"): the width of the texture in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER` ("height"): the height of the texture in pixels, required * * With the direct3d11 renderer: * - * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the - * texture, if you want to wrap an existing texture. - * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER` ("d3d11.texture"): the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER` ("d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER` ("d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the direct3d12 renderer: * - * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the - * texture, if you want to wrap an existing texture. - * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER` ("d3d12.texture"): the ID3D12Resource associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER` ("d3d12.texture_u"): the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER` ("d3d12.texture_v"): the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * - "opengl.texture" (number) - the GLuint texture associated with the - * texture, if you want to wrap an existing texture. - * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV - * plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengl.texture_u" (number) - the GLuint texture associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "opengl.texture_v" (number) - the GLuint texture associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER` ("opengl.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER` ("opengl.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER` ("opengl.texture_u"): the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER` ("opengl.texture_v"): the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * - "opengles2.texture" (number) - the GLuint texture associated with the - * texture, if you want to wrap an existing texture. - * - "opengles2.texture_uv" (number) - the GLuint texture associated with the - * UV plane of an NV12 texture, if you want to wrap an existing texture. - * - "opengles2.texture_u" (number) - the GLuint texture associated with the U - * plane of a YUV texture, if you want to wrap an existing texture. - * - "opengles2.texture_v" (number) - the GLuint texture associated with the V - * plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` ("opengles2.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` ("opengles2.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER` ("opengles2.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER` ("opengles2.texture_u"): the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER` ("opengles2.texture_v"): the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * \param renderer the rendering context * \param props the properties to use @@ -597,50 +494,26 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); -/** - * Get the properties associated with a texture. - * - * The following read-only properties are provided by SDL: - */ -/* - * With the direct3d11 renderer: - */ -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" /* the ID3D11Texture2D associated with the texture */ -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture */ -/* - * With the direct3d12 renderer: - */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" /* the ID3D12Resource associated with the texture */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture */ -/* - * With the opengl renderer: - */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" /* the GLuint texture associated with the texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" /* the texture coordinate width of the texture (0.0 - 1.0) */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" /* the texture coordinate height of the texture (0.0 - 1.0) */ -/* - * With the opengles2 renderer: - */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" /* the GLuint texture associated with the texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ -/* - * associated with the V plane of a YUV texture - * \param texture the texture to query - * \returns a valid property ID on success or 0 on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty - */ +#define SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER "format" +#define SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER "access" +#define SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER "width" +#define SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER "height" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "d3d12.texture" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "d3d12.texture_u" +#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "d3d12.texture_v" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "opengl.texture" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "opengl.texture_uv" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "opengl.texture_u" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "opengl.texture_v" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u" +#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v" + /** * Get the properties associated with a texture. @@ -649,47 +522,31 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * * With the direct3d11 renderer: * - * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated - * with the texture - * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated - * with the U plane of a YUV texture - * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated - * with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER` ("SDL.texture.d3d11.texture"): the ID3D11Texture2D associated with the texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER` ("SDL.texture.d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER` ("SDL.texture.d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a YUV texture * * With the direct3d12 renderer: * - * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated - * with the texture - * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated - * with the U plane of a YUV texture - * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated - * with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER` ("SDL.texture.d3d12.texture"): the ID3D12Resource associated with the texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER` ("SDL.texture.d3d12.texture_u"): the ID3D12Resource associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER` ("SDL.texture.d3d12.texture_v"): the ID3D12Resource associated with the V plane of a YUV texture * * With the opengl renderer: * - * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated - * with the texture - * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated - * with the UV plane of an NV12 texture - * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated - * with the U plane of a YUV texture - * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated - * with the V plane of a YUV texture - * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the - * texture (0.0 - 1.0) - * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the - * texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER` ("SDL.texture.opengl.texture"): the GLuint texture associated with the texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER` ("SDL.texture.opengl.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER` ("SDL.texture.opengl.texture_u"): the GLuint texture associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER` ("SDL.texture.opengl.texture_v"): the GLuint texture associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT` ("SDL.texture.opengl.tex_w"): the texture coordinate width of the texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT` ("SDL.texture.opengl.tex_h"): the texture coordinate height of the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated - * with the texture - * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture - * associated with the UV plane of an NV12 texture - * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture - * associated with the U plane of a YUV texture - * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture - * associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER` ("SDL.texture.opengles2.texture"): the GLuint texture associated with the texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER` ("SDL.texture.opengles2.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER` ("SDL.texture.opengles2.texture_u"): the GLuint texture associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER` ("SDL.texture.opengles2.texture_v"): the GLuint texture associated with the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call @@ -702,6 +559,23 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" /* the ID3D11Texture2D associated with the texture */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" /* the ID3D12Resource associated with the texture */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" /* the GLuint texture associated with the texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" /* the texture coordinate width of the texture (0.0 - 1.0) */ +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" /* the texture coordinate height of the texture (0.0 - 1.0) */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" /* the GLuint texture associated with the texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ + /** * Get the renderer that created an SDL_Texture. * diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 6c21be09c9ec7..0ff626733fb56 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -808,121 +808,46 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * Create a window with the specified properties. * * These are the supported properties: - */ -#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" /* true if the window should be always on top */ -#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" /* true if the window has no window decoration */ -#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" /* true if the window should accept keyboard input (defaults true) */ -#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" /* true if the window should start in fullscreen mode at desktop resolution */ -#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" /* the height of the window */ -#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" /* true if the window should start hidden */ -#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" /* true if the window uses a high pixel density buffer if possible */ -#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" /* true if the window should start maximized */ -#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" /* true if the window is a popup menu */ -#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" /* true if the window will be used with Metal rendering */ -#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" /* true if the window should start minimized */ -#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" /* true if the window starts with grabbed mouse focus */ -#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" /* true if the window will be used with OpenGL rendering */ -#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" /* an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties */ -#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" /* true if the window should be resizable */ -#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" /* the title of the window, in UTF-8 encoding */ -#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" /* true if the window show transparent in the areas with alpha of 0 */ -#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" /* true if the window is a tooltip */ -#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" /* true if the window is a utility window, not showing in the task bar and window list */ -#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" /* true if the window will be used with Vulkan rendering */ -#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" /* the width of the window */ -#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" /* the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. */ -#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" /* the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. */ -/* - * These are additional supported properties on macOS: - */ -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" /* the (__unsafe_unretained) NSWindow associated with the window, if you want to wrap an existing window. */ -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" /* the (__unsafe_unretained) NSView associated with the window, defaults to [window contentView] */ -/* - * These are additional supported properties on Windows: - */ -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" /* the HWND associated with the window, if you want to wrap an existing window. */ -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" /* optional, another window to share pixel format with, useful for OpenGL windows */ -/* - * These are additional supported properties with X11: - */ -#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" /* the X11 Window associated with the window, if you want to wrap an existing window. */ -/* - * The window is implicitly shown if the "hidden" property is not set. * - * Windows with the "tooltip" and "menu" properties are popup windows and have - * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. + * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN` ("always-on-top"): true if the window should be always on top + * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN` ("borderless"): true if the window has no window decoration + * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN` ("focusable"): true if the window should accept keyboard input (defaults true) + * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN` ("fullscreen"): true if the window should start in fullscreen mode at desktop resolution + * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER` ("height"): the height of the window + * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN` ("hidden"): true if the window should start hidden + * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` ("high-pixel-density"): true if the window uses a high pixel density buffer if possible + * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN` ("maximized"): true if the window should start maximized + * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN` ("menu"): true if the window is a popup menu + * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN` ("metal"): true if the window will be used with Metal rendering + * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN` ("minimized"): true if the window should start minimized + * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN` ("mouse-grabbed"): true if the window starts with grabbed mouse focus + * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN` ("opengl"): true if the window will be used with OpenGL rendering + * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER` ("parent"): an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties + * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN` ("resizable"): true if the window should be resizable + * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING` ("title"): the title of the window, in UTF-8 encoding + * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN` ("transparent"): true if the window show transparent in the areas with alpha of 0 + * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN` ("tooltip"): true if the window is a tooltip + * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN` ("utility"): true if the window is a utility window, not showing in the task bar and window list + * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN` ("vulkan"): true if the window will be used with Vulkan rendering + * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER` ("width"): the width of the window + * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER` ("x"): the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. + * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER` ("y"): the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. * - * \param props the properties to use - * \returns the window that was created or NULL on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateWindow - * \sa SDL_DestroyWindow - */ - -/** - * Create a window with the specified properties. - * - * These are the supported properties: - * - * - "always-on-top" (boolean) - true if the window should be always on top - * - "borderless" (boolean) - true if the window has no window decoration - * - "focusable" (boolean) - true if the window should accept keyboard input - * (defaults true) - * - "fullscreen" (boolean) - true if the window should start in fullscreen - * mode at desktop resolution - * - "height" (number) - the height of the window - * - "hidden" (boolean) - true if the window should start hidden - * - "high-pixel-density" (boolean) - true if the window uses a high pixel - * density buffer if possible - * - "maximized" (boolean) - true if the window should start maximized - * - "menu" (boolean) - true if the window is a popup menu - * - "metal" (string) - true if the window will be used with Metal rendering - * - "minimized" (boolean) - true if the window should start minimized - * - "mouse-grabbed" (boolean) - true if the window starts with grabbed mouse - * focus - * - "opengl" (boolean) - true if the window will be used with OpenGL - * rendering - * - "parent" (pointer) - an SDL_Window that will be the parent of this - * window, required for windows with the "toolip" and "menu" properties - * - "resizable" (boolean) - true if the window should be resizable - * - "title" (string) - the title of the window, in UTF-8 encoding - * - "transparent" (string) - true if the window show transparent in the areas - * with alpha of 0 - * - "tooltip" (boolean) - true if the window is a tooltip - * - "utility" (boolean) - true if the window is a utility window, not showing - * in the task bar and window list - * - "vulkan" (string) - true if the window will be used with Vulkan rendering - * - "width" (number) - the width of the window - * - "x" (number) - the x position of the window, or `SDL_WINDOWPOS_CENTERED`, - * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for - * windows with the "parent" property set. - * - "y" (number) - the y position of the window, or `SDL_WINDOWPOS_CENTERED`, - * defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for - * windows with the "parent" property set. - * - * On macOS: + * These are additional supported properties on macOS: * - * - "cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated - * with the window, if you want to wrap an existing window. - * - "cocoa.view" (pointer) - the (__unsafe_unretained) NSView associated with - * the window, defaults to [window contentView] + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER` ("cocoa.window"): the `(__unsafe_unretained)` NSWindow associated with the window, if you want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER` ("cocoa.view"): the `(__unsafe_unretained)` NSView associated with the window, defaults to `[window contentView]` * - * On Windows: + * These are additional supported properties on Windows: * - * - "win32.hwnd" (pointer) - the HWND associated with the window, if you want - * to wrap an existing window. - * - "win32.pixel_format_hwnd" (pointer) - optional, another window to share - * pixel format with, useful for OpenGL windows + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER` ("win32.hwnd"): the HWND associated with the window, if you want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER` ("win32.pixel_format_hwnd"): optional, another window to share pixel format with, useful for OpenGL windows * - * On X11: + * These are additional supported properties with X11: * - * - "x11.window" (number) - the X11 Window associated with the window, if you - * want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER` ("x11.window"): the X11 Window associated with the window, if you want to wrap an existing window. * - * The SDL_Window is implicitly shown if the "hidden" property is not set. + * The window is implicitly shown if the "hidden" property is not set. * * Windows with the "tooltip" and "menu" properties are popup windows and have * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. @@ -938,6 +863,36 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); +#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" +#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" +#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" +#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" +#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" +#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" +#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" +#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" +#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" +#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" +#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" +#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" +#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" +#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" +#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" +#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" +#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" +#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" +#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" +#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" +#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" +#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" +#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" +#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" + + /** * Get the numeric ID of a window. * @@ -987,156 +942,65 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * Get the properties associated with a window. * * The following read-only properties are provided by SDL: - */ -/* - * On Android: - */ -#define SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" /* the ANativeWindow associated with the window */ -#define SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" /* the EGLSurface associated with the window */ -/* - * On iOS: - */ -#define SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" /* the (__unsafe_unretained) UIWindow associated with the window */ -#define SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" /* the NSInteger tag assocated with metal views on the window */ -/* - * On KMS/DRM: - */ -#define SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" /* the device index associated with the window (e.g. the X in /dev/dri/cardX) */ -#define SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" /* the DRM FD associated with the window */ -#define SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" /* the GBM device associated with the window */ -/* - * On macOS: - */ -#define SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" /* the (__unsafe_unretained) NSWindow associated with the window */ -#define SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" /* the NSInteger tag assocated with metal views on the window */ -/* - * On Vivante: - */ -#define SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" /* the EGLNativeDisplayType associated with the window */ -#define SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" /* the EGLNativeWindowType associated with the window */ -#define SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" /* the EGLSurface associated with the window */ -/* - * On UWP: - */ -#define SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" /* the IInspectable CoreWindow associated with the window */ -/* - * On Windows: - */ -#define SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" /* the HWND associated with the window */ -#define SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" /* the HDC associated with the window */ -#define SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" /* the HINSTANCE associated with the window */ -/* - * On Wayland: * - * Note: The xdg_* window objects do not internally persist across window - * show/hide calls. They will be null if the window is hidden and must be - * queried each time it is shown. - */ -#define SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER "SDL.window.wayland.registry" /* the wl_registry associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" /* the wl_display associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" /* the wl_surface associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" /* the wl_egl_window associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" /* the xdg_surface associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" /* the xdg_toplevel role associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" /* the xdg_popup role associated with the window */ -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" /* the xdg_positioner associated with the window, in popup mode */ -/* - * On X11: - */ -#define SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" /* the X11 Display associated with the window */ -#define SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" /* the screen number associated with the window */ -#define SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" /* the X11 Window associated with the window */ -/* - * \param window the window to query - * \returns a valid property ID on success or 0 on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty - */ - -/** - * Get the properties associated with a window. - * - * The following read-only properties are provided by SDL: * * On Android: * - * ``` - * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window - * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER` ("SDL.window.android.window"): the ANativeWindow associated with the window + * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER` ("SDL.window.android.surface"): the EGLSurface associated with the window * * On iOS: * - * ``` - * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window - * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window - * ``` + * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER` ("SDL.window.uikit.window"): the `(__unsafe_unretained)` UIWindow associated with the window + * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER` ("SDL.window.uikit.metal_view_tag"): the NSInteger tag assocated with metal views on the window * * On KMS/DRM: * - * ``` - * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX) - * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window - * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER` ("SDL.window.kmsdrm.dev_index"): the device index associated with the window (e.g. the X in /dev/dri/cardX) + * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER` ("SDL.window.kmsdrm.drm_fd"): the DRM FD associated with the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER` ("SDL.window.kmsdrm.gbm_dev"): the GBM device associated with the window * * On macOS: * - * ``` - * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window - * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window - * ``` + * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER` ("SDL.window.cocoa.window"): the `(__unsafe_unretained)` NSWindow associated with the window + * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER` ("SDL.window.cocoa.metal_view_tag"): the NSInteger tag assocated with metal views on the window * * On Vivante: * - * ``` - * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window - * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window - * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER` ("SDL.window.vivante.display"): the EGLNativeDisplayType associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER` ("SDL.window.vivante.window"): the EGLNativeWindowType associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER` ("SDL.window.vivante.surface"): the EGLSurface associated with the window * * On UWP: * - * ``` - * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER` ("SDL.window.winrt.window"): the IInspectable CoreWindow associated with the window * * On Windows: * - * ``` - * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window - * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window - * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER` ("SDL.window.win32.hwnd"): the HWND associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER` ("SDL.window.win32.hdc"): the HDC associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER` ("SDL.window.win32.instance"): the HINSTANCE associated with the window * * On Wayland: * - * ``` - * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window - * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window - * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window - * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window - * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window - * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window - * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window - * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode - * ``` - * - * Note: The xdg_* window objects do not internally persist across window + * Note: The `xdg_*` window objects do not internally persist across window * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * + * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER` ("SDL.window.wayland.registry"): the wl_registry associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` ("SDL.window.wayland.display"): the wl_display associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` ("SDL.window.wayland.surface"): the wl_surface associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER` ("SDL.window.wayland.egl_window"): the wl_egl_window associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER` ("SDL.window.wayland.xdg_surface"): the xdg_surface associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER` ("SDL.window.wayland.xdg_toplevel"): the xdg_toplevel role associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER` ("SDL.window.wayland.xdg_popup"): the xdg_popup role associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER` ("SDL.window.wayland.xdg_positioner"): the xdg_positioner associated with the window, in popup mode + * * On X11: * - * ``` - * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window - * "SDL.window.x11.screen" (number) - the screen number associated with the window - * "SDL.window.x11.window" (number) - the X11 Window associated with the window - * ``` + * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER` ("SDL.window.x11.display"): the X11 Display associated with the window + * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER` ("SDL.window.x11.screen"): the screen number associated with the window + * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER` ("SDL.window.x11.window"): the X11 Window associated with the window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call @@ -1149,6 +1013,34 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); +#define SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" +#define SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" +#define SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" +#define SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" +#define SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" +#define SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" +#define SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" +#define SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" +#define SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" +#define SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" +#define SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" +#define SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" +#define SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" +#define SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" +#define SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" +#define SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" +#define SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER "SDL.window.wayland.registry" +#define SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" +#define SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" +#define SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" +#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" +#define SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" +#define SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" +#define SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" + /** * Get the window flags. * From e8c595af5cd0cf152239bc33564357d223005d0a Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 17:16:19 +0000 Subject: [PATCH 686/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 167 ++++++++++++++++++++++++--------- include/SDL3/SDL_video.h | 188 ++++++++++++++++++++++++++------------ 2 files changed, 254 insertions(+), 101 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 69a5d612927b2..55c74019a087a 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -240,11 +240,15 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * * These are the supported properties: * - * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER` ("window"): the window where rendering is displayed - * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER` ("surface"): the surface where rendering is displayed, if you want a software renderer without a window - * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING` ("name"): the name of the rendering driver to use, if a specific one is desired - * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN` ("present_vsync"): true if you want present synchronized with the refresh rate - * + * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER` ("window"): the window + * where rendering is displayed + * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER` ("surface"): the surface + * where rendering is displayed, if you want a software renderer without a + * window + * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING` ("name"): the name of the + * rendering driver to use, if a specific one is desired + * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN` ("present_vsync"): + * true if you want present synchronized with the refresh rate * * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call @@ -329,11 +333,18 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * The following read-only properties are provided by SDL: * - * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER` ("SDL.renderer.d3d9.device"): the IDirect3DDevice9 associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER` ("SDL.renderer.d3d11.device"): the ID3D11Device associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER` ("SDL.renderer.d3d12.device"): the ID3D12Device associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER` ("SDL.renderer.d3d12.command_queue"): the ID3D12CommandQueue associated with the renderer -/* + * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER` ("SDL.renderer.d3d9.device"): + * the IDirect3DDevice9 associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER` + * ("SDL.renderer.d3d11.device"): the ID3D11Device associated with the + * renderer + * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER` + * ("SDL.renderer.d3d12.device"): the ID3D12Device associated with the + * renderer + * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER` + * ("SDL.renderer.d3d12.command_queue"): the ID3D12CommandQueue associated + * with the renderer /* + * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -446,37 +457,73 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * These are the supported properties: * - * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER` ("format"): one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer - * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER` ("access"): one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC - * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER` ("width"): the width of the texture in pixels, required - * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER` ("height"): the height of the texture in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER` ("format"): one of the + * enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA + * format for the renderer + * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER` ("access"): one of the + * enumerated values in SDL_TextureAccess, defaults to + * SDL_TEXTUREACCESS_STATIC + * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER` ("width"): the width of the + * texture in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER` ("height"): the height of the + * texture in pixels, required * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER` ("d3d11.texture"): the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER` ("d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER` ("d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER` ("d3d11.texture"): + * the ID3D11Texture2D associated with the texture, if you want to wrap an + * existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER` + * ("d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a + * YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER` + * ("d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a + * YUV texture, if you want to wrap an existing texture. * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER` ("d3d12.texture"): the ID3D12Resource associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER` ("d3d12.texture_u"): the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER` ("d3d12.texture_v"): the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER` ("d3d12.texture"): + * the ID3D12Resource associated with the texture, if you want to wrap an + * existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER` + * ("d3d12.texture_u"): the ID3D12Resource associated with the U plane of a + * YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER` + * ("d3d12.texture_v"): the ID3D12Resource associated with the V plane of a + * YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER` ("opengl.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER` ("opengl.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER` ("opengl.texture_u"): the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER` ("opengl.texture_v"): the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER` ("opengl.texture"): + * the GLuint texture associated with the texture, if you want to wrap an + * existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER` + * ("opengl.texture_uv"): the GLuint texture associated with the UV plane of + * an NV12 texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER` + * ("opengl.texture_u"): the GLuint texture associated with the U plane of a + * YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER` + * ("opengl.texture_v"): the GLuint texture associated with the V plane of a + * YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` ("opengles2.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` ("opengles2.texture"): the GLuint texture associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER` ("opengles2.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER` ("opengles2.texture_u"): the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER` ("opengles2.texture_v"): the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` + * ("opengles2.texture"): the GLuint texture associated with the texture, if + * you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` + * ("opengles2.texture"): the GLuint texture associated with the texture, if + * you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER` + * ("opengles2.texture_uv"): the GLuint texture associated with the UV plane + * of an NV12 texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER` + * ("opengles2.texture_u"): the GLuint texture associated with the U plane + * of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER` + * ("opengles2.texture_v"): the GLuint texture associated with the V plane + * of a YUV texture, if you want to wrap an existing texture. * * \param renderer the rendering context * \param props the properties to use @@ -522,31 +569,61 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER` ("SDL.texture.d3d11.texture"): the ID3D11Texture2D associated with the texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER` ("SDL.texture.d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER` ("SDL.texture.d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER` + * ("SDL.texture.d3d11.texture"): the ID3D11Texture2D associated with the + * texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER` + * ("SDL.texture.d3d11.texture_u"): the ID3D11Texture2D associated with the + * U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER` + * ("SDL.texture.d3d11.texture_v"): the ID3D11Texture2D associated with the + * V plane of a YUV texture * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER` ("SDL.texture.d3d12.texture"): the ID3D12Resource associated with the texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER` ("SDL.texture.d3d12.texture_u"): the ID3D12Resource associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER` ("SDL.texture.d3d12.texture_v"): the ID3D12Resource associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER` + * ("SDL.texture.d3d12.texture"): the ID3D12Resource associated with the + * texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER` + * ("SDL.texture.d3d12.texture_u"): the ID3D12Resource associated with the U + * plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER` + * ("SDL.texture.d3d12.texture_v"): the ID3D12Resource associated with the V + * plane of a YUV texture * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER` ("SDL.texture.opengl.texture"): the GLuint texture associated with the texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER` ("SDL.texture.opengl.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER` ("SDL.texture.opengl.texture_u"): the GLuint texture associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER` ("SDL.texture.opengl.texture_v"): the GLuint texture associated with the V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT` ("SDL.texture.opengl.tex_w"): the texture coordinate width of the texture (0.0 - 1.0) - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT` ("SDL.texture.opengl.tex_h"): the texture coordinate height of the texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER` + * ("SDL.texture.opengl.texture"): the GLuint texture associated with the + * texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER` + * ("SDL.texture.opengl.texture_uv"): the GLuint texture associated with the + * UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER` + * ("SDL.texture.opengl.texture_u"): the GLuint texture associated with the + * U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER` + * ("SDL.texture.opengl.texture_v"): the GLuint texture associated with the + * V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT` ("SDL.texture.opengl.tex_w"): + * the texture coordinate width of the texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT` ("SDL.texture.opengl.tex_h"): + * the texture coordinate height of the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER` ("SDL.texture.opengles2.texture"): the GLuint texture associated with the texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER` ("SDL.texture.opengles2.texture_uv"): the GLuint texture associated with the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER` ("SDL.texture.opengles2.texture_u"): the GLuint texture associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER` ("SDL.texture.opengles2.texture_v"): the GLuint texture associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER` + * ("SDL.texture.opengles2.texture"): the GLuint texture associated with the + * texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER` + * ("SDL.texture.opengles2.texture_uv"): the GLuint texture associated with + * the UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER` + * ("SDL.texture.opengles2.texture_u"): the GLuint texture associated with + * the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER` + * ("SDL.texture.opengles2.texture_v"): the GLuint texture associated with + * the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 0ff626733fb56..f11514c3e72de 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -809,43 +809,81 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * These are the supported properties: * - * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN` ("always-on-top"): true if the window should be always on top - * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN` ("borderless"): true if the window has no window decoration - * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN` ("focusable"): true if the window should accept keyboard input (defaults true) - * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN` ("fullscreen"): true if the window should start in fullscreen mode at desktop resolution - * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER` ("height"): the height of the window - * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN` ("hidden"): true if the window should start hidden - * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` ("high-pixel-density"): true if the window uses a high pixel density buffer if possible - * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN` ("maximized"): true if the window should start maximized - * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN` ("menu"): true if the window is a popup menu - * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN` ("metal"): true if the window will be used with Metal rendering - * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN` ("minimized"): true if the window should start minimized - * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN` ("mouse-grabbed"): true if the window starts with grabbed mouse focus - * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN` ("opengl"): true if the window will be used with OpenGL rendering - * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER` ("parent"): an SDL_Window that will be the parent of this window, required for windows with the "toolip" and "menu" properties - * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN` ("resizable"): true if the window should be resizable - * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING` ("title"): the title of the window, in UTF-8 encoding - * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN` ("transparent"): true if the window show transparent in the areas with alpha of 0 - * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN` ("tooltip"): true if the window is a tooltip - * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN` ("utility"): true if the window is a utility window, not showing in the task bar and window list - * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN` ("vulkan"): true if the window will be used with Vulkan rendering - * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER` ("width"): the width of the window - * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER` ("x"): the x position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. - * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER` ("y"): the y position of the window, or `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows with the "parent" property set. + * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN` ("always-on-top"): + * true if the window should be always on top + * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN` ("borderless"): true if + * the window has no window decoration + * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN` ("focusable"): true if the + * window should accept keyboard input (defaults true) + * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN` ("fullscreen"): true if + * the window should start in fullscreen mode at desktop resolution + * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER` ("height"): the height of the + * window + * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN` ("hidden"): true if the + * window should start hidden + * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` + * ("high-pixel-density"): true if the window uses a high pixel density + * buffer if possible + * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN` ("maximized"): true if the + * window should start maximized + * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN` ("menu"): true if the window is + * a popup menu + * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN` ("metal"): true if the window + * will be used with Metal rendering + * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN` ("minimized"): true if the + * window should start minimized + * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN` ("mouse-grabbed"): + * true if the window starts with grabbed mouse focus + * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN` ("opengl"): true if the + * window will be used with OpenGL rendering + * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER` ("parent"): an SDL_Window + * that will be the parent of this window, required for windows with the + * "toolip" and "menu" properties + * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN` ("resizable"): true if the + * window should be resizable + * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING` ("title"): the title of the + * window, in UTF-8 encoding + * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN` ("transparent"): true if + * the window show transparent in the areas with alpha of 0 + * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN` ("tooltip"): true if the + * window is a tooltip + * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN` ("utility"): true if the + * window is a utility window, not showing in the task bar and window list + * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN` ("vulkan"): true if the + * window will be used with Vulkan rendering + * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER` ("width"): the width of the + * window + * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER` ("x"): the x position of the + * window, or `SDL_WINDOWPOS_CENTERED`, defaults to + * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows + * with the "parent" property set. + * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER` ("y"): the y position of the + * window, or `SDL_WINDOWPOS_CENTERED`, defaults to + * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows + * with the "parent" property set. * * These are additional supported properties on macOS: * - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER` ("cocoa.window"): the `(__unsafe_unretained)` NSWindow associated with the window, if you want to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER` ("cocoa.view"): the `(__unsafe_unretained)` NSView associated with the window, defaults to `[window contentView]` + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER` ("cocoa.window"): the + * `(__unsafe_unretained)` NSWindow associated with the window, if you want + * to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER` ("cocoa.view"): the + * `(__unsafe_unretained)` NSView associated with the window, defaults to + * `[window contentView]` * * These are additional supported properties on Windows: * - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER` ("win32.hwnd"): the HWND associated with the window, if you want to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER` ("win32.pixel_format_hwnd"): optional, another window to share pixel format with, useful for OpenGL windows + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER` ("win32.hwnd"): the HWND + * associated with the window, if you want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER` + * ("win32.pixel_format_hwnd"): optional, another window to share pixel + * format with, useful for OpenGL windows * * These are additional supported properties with X11: * - * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER` ("x11.window"): the X11 Window associated with the window, if you want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER` ("x11.window"): the X11 + * Window associated with the window, if you want to wrap an existing + * window. * * The window is implicitly shown if the "hidden" property is not set. * @@ -943,43 +981,64 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following read-only properties are provided by SDL: * - * * On Android: * - * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER` ("SDL.window.android.window"): the ANativeWindow associated with the window - * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER` ("SDL.window.android.surface"): the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER` + * ("SDL.window.android.window"): the ANativeWindow associated with the + * window + * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER` + * ("SDL.window.android.surface"): the EGLSurface associated with the window * * On iOS: * - * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER` ("SDL.window.uikit.window"): the `(__unsafe_unretained)` UIWindow associated with the window - * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER` ("SDL.window.uikit.metal_view_tag"): the NSInteger tag assocated with metal views on the window + * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER` ("SDL.window.uikit.window"): + * the `(__unsafe_unretained)` UIWindow associated with the window + * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER` + * ("SDL.window.uikit.metal_view_tag"): the NSInteger tag assocated with + * metal views on the window * * On KMS/DRM: * - * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER` ("SDL.window.kmsdrm.dev_index"): the device index associated with the window (e.g. the X in /dev/dri/cardX) - * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER` ("SDL.window.kmsdrm.drm_fd"): the DRM FD associated with the window - * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER` ("SDL.window.kmsdrm.gbm_dev"): the GBM device associated with the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER` + * ("SDL.window.kmsdrm.dev_index"): the device index associated with the + * window (e.g. the X in /dev/dri/cardX) + * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER` ("SDL.window.kmsdrm.drm_fd"): + * the DRM FD associated with the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER` + * ("SDL.window.kmsdrm.gbm_dev"): the GBM device associated with the window * * On macOS: * - * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER` ("SDL.window.cocoa.window"): the `(__unsafe_unretained)` NSWindow associated with the window - * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER` ("SDL.window.cocoa.metal_view_tag"): the NSInteger tag assocated with metal views on the window + * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER` ("SDL.window.cocoa.window"): + * the `(__unsafe_unretained)` NSWindow associated with the window + * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER` + * ("SDL.window.cocoa.metal_view_tag"): the NSInteger tag assocated with + * metal views on the window * * On Vivante: * - * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER` ("SDL.window.vivante.display"): the EGLNativeDisplayType associated with the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER` ("SDL.window.vivante.window"): the EGLNativeWindowType associated with the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER` ("SDL.window.vivante.surface"): the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER` + * ("SDL.window.vivante.display"): the EGLNativeDisplayType associated with + * the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER` + * ("SDL.window.vivante.window"): the EGLNativeWindowType associated with + * the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER` + * ("SDL.window.vivante.surface"): the EGLSurface associated with the window * * On UWP: * - * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER` ("SDL.window.winrt.window"): the IInspectable CoreWindow associated with the window + * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER` ("SDL.window.winrt.window"): + * the IInspectable CoreWindow associated with the window * * On Windows: * - * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER` ("SDL.window.win32.hwnd"): the HWND associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER` ("SDL.window.win32.hdc"): the HDC associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER` ("SDL.window.win32.instance"): the HINSTANCE associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER` ("SDL.window.win32.hwnd"): the + * HWND associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER` ("SDL.window.win32.hdc"): the HDC + * associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER` + * ("SDL.window.win32.instance"): the HINSTANCE associated with the window * * On Wayland: * @@ -987,20 +1046,37 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * - * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER` ("SDL.window.wayland.registry"): the wl_registry associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` ("SDL.window.wayland.display"): the wl_display associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` ("SDL.window.wayland.surface"): the wl_surface associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER` ("SDL.window.wayland.egl_window"): the wl_egl_window associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER` ("SDL.window.wayland.xdg_surface"): the xdg_surface associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER` ("SDL.window.wayland.xdg_toplevel"): the xdg_toplevel role associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER` ("SDL.window.wayland.xdg_popup"): the xdg_popup role associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER` ("SDL.window.wayland.xdg_positioner"): the xdg_positioner associated with the window, in popup mode + * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER` + * ("SDL.window.wayland.registry"): the wl_registry associated with the + * window + * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` + * ("SDL.window.wayland.display"): the wl_display associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` + * ("SDL.window.wayland.surface"): the wl_surface associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER` + * ("SDL.window.wayland.egl_window"): the wl_egl_window associated with the + * window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER` + * ("SDL.window.wayland.xdg_surface"): the xdg_surface associated with the + * window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER` + * ("SDL.window.wayland.xdg_toplevel"): the xdg_toplevel role associated + * with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER` + * ("SDL.window.wayland.xdg_popup"): the xdg_popup role associated with the + * window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER` + * ("SDL.window.wayland.xdg_positioner"): the xdg_positioner associated with + * the window, in popup mode * * On X11: * - * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER` ("SDL.window.x11.display"): the X11 Display associated with the window - * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER` ("SDL.window.x11.screen"): the screen number associated with the window - * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER` ("SDL.window.x11.window"): the X11 Window associated with the window + * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER` ("SDL.window.x11.display"): the + * X11 Display associated with the window + * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER` ("SDL.window.x11.screen"): the + * screen number associated with the window + * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER` ("SDL.window.x11.window"): the + * X11 Window associated with the window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call From e056f52f7d8ed041adb9b6a22dcfdb9ebf996d73 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jan 2024 12:33:29 -0500 Subject: [PATCH 687/725] include: Remove string literals from properties documentation. I'm going to let the wiki bridge clean up the word wrapping for me, here. :) --- include/SDL3/SDL_render.h | 126 ++++++++++++++---------------------- include/SDL3/SDL_video.h | 130 ++++++++++++++++---------------------- 2 files changed, 104 insertions(+), 152 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 55c74019a087a..12ac17e27b65d 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -240,14 +240,14 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * * These are the supported properties: * - * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER` ("window"): the window + * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER`: the window * where rendering is displayed - * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER` ("surface"): the surface + * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER`: the surface * where rendering is displayed, if you want a software renderer without a * window - * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING` ("name"): the name of the + * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING`: the name of the * rendering driver to use, if a specific one is desired - * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN` ("present_vsync"): + * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: * true if you want present synchronized with the refresh rate * * \param props the properties to use @@ -333,17 +333,14 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * The following read-only properties are provided by SDL: * - * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER` ("SDL.renderer.d3d9.device"): - * the IDirect3DDevice9 associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER` - * ("SDL.renderer.d3d11.device"): the ID3D11Device associated with the - * renderer - * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER` - * ("SDL.renderer.d3d12.device"): the ID3D12Device associated with the - * renderer - * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER` - * ("SDL.renderer.d3d12.command_queue"): the ID3D12CommandQueue associated - * with the renderer /* + * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 + * associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device + * associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device + * associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the + * ID3D12CommandQueue associated with the renderer * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call @@ -457,72 +454,61 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * These are the supported properties: * - * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER` ("format"): one of the + * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER`: one of the * enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA * format for the renderer - * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER` ("access"): one of the + * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER`: one of the * enumerated values in SDL_TextureAccess, defaults to * SDL_TEXTUREACCESS_STATIC - * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER` ("width"): the width of the - * texture in pixels, required - * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER` ("height"): the height of the + * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER`: the width of the * texture in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture + * in pixels, required * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER` ("d3d11.texture"): + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER`: * the ID3D11Texture2D associated with the texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER` - * ("d3d11.texture_u"): the ID3D11Texture2D associated with the U plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D associated with the U plane of a * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER` - * ("d3d11.texture_v"): the ID3D11Texture2D associated with the V plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D associated with the V plane of a * YUV texture, if you want to wrap an existing texture. * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER` ("d3d12.texture"): + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER`: * the ID3D12Resource associated with the texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER` - * ("d3d12.texture_u"): the ID3D12Resource associated with the U plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER`: the + * ID3D12Resource associated with the U plane of a * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER` - * ("d3d12.texture_v"): the ID3D12Resource associated with the V plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource associated with the V plane of a * YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER` ("opengl.texture"): + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER`: * the GLuint texture associated with the texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER` - * ("opengl.texture_uv"): the GLuint texture associated with the UV plane of + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture associated with the UV plane of * an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER` - * ("opengl.texture_u"): the GLuint texture associated with the U plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture associated with the U plane of a * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER` - * ("opengl.texture_v"): the GLuint texture associated with the V plane of a + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture associated with the V plane of a * YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` - * ("opengles2.texture"): the GLuint texture associated with the texture, if + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the texture, if * you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER` - * ("opengles2.texture"): the GLuint texture associated with the texture, if + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the texture, if * you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER` - * ("opengles2.texture_uv"): the GLuint texture associated with the UV plane + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture associated with the UV plane * of an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER` - * ("opengles2.texture_u"): the GLuint texture associated with the U plane + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture associated with the U plane * of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER` - * ("opengles2.texture_v"): the GLuint texture associated with the V plane + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture associated with the V plane * of a YUV texture, if you want to wrap an existing texture. * * \param renderer the rendering context @@ -569,60 +555,46 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER` - * ("SDL.texture.d3d11.texture"): the ID3D11Texture2D associated with the + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D associated with the * texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER` - * ("SDL.texture.d3d11.texture_u"): the ID3D11Texture2D associated with the + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D associated with the * U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER` - * ("SDL.texture.d3d11.texture_v"): the ID3D11Texture2D associated with the + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D associated with the * V plane of a YUV texture * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER` - * ("SDL.texture.d3d12.texture"): the ID3D12Resource associated with the + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER`: the ID3D12Resource associated with the * texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER` - * ("SDL.texture.d3d12.texture_u"): the ID3D12Resource associated with the U + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource associated with the U * plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER` - * ("SDL.texture.d3d12.texture_v"): the ID3D12Resource associated with the V + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource associated with the V * plane of a YUV texture * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER` - * ("SDL.texture.opengl.texture"): the GLuint texture associated with the + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER`: the GLuint texture associated with the * texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER` - * ("SDL.texture.opengl.texture_uv"): the GLuint texture associated with the + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture associated with the * UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER` - * ("SDL.texture.opengl.texture_u"): the GLuint texture associated with the + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture associated with the * U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER` - * ("SDL.texture.opengl.texture_v"): the GLuint texture associated with the + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture associated with the * V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT` ("SDL.texture.opengl.tex_w"): + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT`: * the texture coordinate width of the texture (0.0 - 1.0) - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT` ("SDL.texture.opengl.tex_h"): + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT`: * the texture coordinate height of the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER` - * ("SDL.texture.opengles2.texture"): the GLuint texture associated with the + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the * texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER` - * ("SDL.texture.opengles2.texture_uv"): the GLuint texture associated with + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture associated with * the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER` - * ("SDL.texture.opengles2.texture_u"): the GLuint texture associated with + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture associated with * the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER` - * ("SDL.texture.opengles2.texture_v"): the GLuint texture associated with + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture associated with * the V plane of a YUV texture * * \param texture the texture to query diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index f11514c3e72de..99eeff5c341fe 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -809,79 +809,77 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * These are the supported properties: * - * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN` ("always-on-top"): + * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: * true if the window should be always on top - * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN` ("borderless"): true if + * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if * the window has no window decoration - * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN` ("focusable"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the * window should accept keyboard input (defaults true) - * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN` ("fullscreen"): true if + * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN`: true if * the window should start in fullscreen mode at desktop resolution - * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER` ("height"): the height of the + * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER`: the height of the * window - * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN` ("hidden"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN`: true if the * window should start hidden - * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` - * ("high-pixel-density"): true if the window uses a high pixel density + * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN`: true if the window uses a high pixel density * buffer if possible - * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN` ("maximized"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN`: true if the * window should start maximized - * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN` ("menu"): true if the window is + * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN`: true if the window is * a popup menu - * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN` ("metal"): true if the window + * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN`: true if the window * will be used with Metal rendering - * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN` ("minimized"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the * window should start minimized - * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN` ("mouse-grabbed"): + * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN`: * true if the window starts with grabbed mouse focus - * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN` ("opengl"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN`: true if the * window will be used with OpenGL rendering - * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER` ("parent"): an SDL_Window + * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER`: an SDL_Window * that will be the parent of this window, required for windows with the * "toolip" and "menu" properties - * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN` ("resizable"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN`: true if the * window should be resizable - * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING` ("title"): the title of the + * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING`: the title of the * window, in UTF-8 encoding - * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN` ("transparent"): true if + * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN`: true if * the window show transparent in the areas with alpha of 0 - * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN` ("tooltip"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN`: true if the * window is a tooltip - * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN` ("utility"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN`: true if the * window is a utility window, not showing in the task bar and window list - * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN` ("vulkan"): true if the + * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN`: true if the * window will be used with Vulkan rendering - * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER` ("width"): the width of the + * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER`: the width of the * window - * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER` ("x"): the x position of the + * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER`: the x position of the * window, or `SDL_WINDOWPOS_CENTERED`, defaults to * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows * with the "parent" property set. - * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER` ("y"): the y position of the + * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER`: the y position of the * window, or `SDL_WINDOWPOS_CENTERED`, defaults to * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows * with the "parent" property set. * * These are additional supported properties on macOS: * - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER` ("cocoa.window"): the + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER`: the * `(__unsafe_unretained)` NSWindow associated with the window, if you want * to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER` ("cocoa.view"): the + * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER`: the * `(__unsafe_unretained)` NSView associated with the window, defaults to * `[window contentView]` * * These are additional supported properties on Windows: * - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER` ("win32.hwnd"): the HWND + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND * associated with the window, if you want to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER` - * ("win32.pixel_format_hwnd"): optional, another window to share pixel + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER`: optional, another window to share pixel * format with, useful for OpenGL windows * * These are additional supported properties with X11: * - * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER` ("x11.window"): the X11 + * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER`: the X11 * Window associated with the window, if you want to wrap an existing * window. * @@ -983,62 +981,52 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * On Android: * - * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER` - * ("SDL.window.android.window"): the ANativeWindow associated with the + * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER`: the ANativeWindow associated with the * window - * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER` - * ("SDL.window.android.surface"): the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER`: the EGLSurface associated with the window * * On iOS: * - * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER` ("SDL.window.uikit.window"): + * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER`: * the `(__unsafe_unretained)` UIWindow associated with the window - * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER` - * ("SDL.window.uikit.metal_view_tag"): the NSInteger tag assocated with + * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag assocated with * metal views on the window * * On KMS/DRM: * - * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER` - * ("SDL.window.kmsdrm.dev_index"): the device index associated with the + * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER`: the device index associated with the * window (e.g. the X in /dev/dri/cardX) - * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER` ("SDL.window.kmsdrm.drm_fd"): + * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER`: * the DRM FD associated with the window - * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER` - * ("SDL.window.kmsdrm.gbm_dev"): the GBM device associated with the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER`: the GBM device associated with the window * * On macOS: * - * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER` ("SDL.window.cocoa.window"): + * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER`: * the `(__unsafe_unretained)` NSWindow associated with the window - * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER` - * ("SDL.window.cocoa.metal_view_tag"): the NSInteger tag assocated with + * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag assocated with * metal views on the window * * On Vivante: * - * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER` - * ("SDL.window.vivante.display"): the EGLNativeDisplayType associated with + * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType associated with * the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER` - * ("SDL.window.vivante.window"): the EGLNativeWindowType associated with + * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER`: the EGLNativeWindowType associated with * the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER` - * ("SDL.window.vivante.surface"): the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated with the window * * On UWP: * - * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER` ("SDL.window.winrt.window"): + * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER`: * the IInspectable CoreWindow associated with the window * * On Windows: * - * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER` ("SDL.window.win32.hwnd"): the + * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER`: the * HWND associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER` ("SDL.window.win32.hdc"): the HDC + * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER`: the HDC * associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER` - * ("SDL.window.win32.instance"): the HINSTANCE associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER`: the HINSTANCE associated with the window * * On Wayland: * @@ -1046,36 +1034,28 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * - * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER` - * ("SDL.window.wayland.registry"): the wl_registry associated with the + * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER`: the wl_registry associated with the * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` - * ("SDL.window.wayland.display"): the wl_display associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` - * ("SDL.window.wayland.surface"): the wl_surface associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER` - * ("SDL.window.wayland.egl_window"): the wl_egl_window associated with the + * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER`: the wl_egl_window associated with the * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER` - * ("SDL.window.wayland.xdg_surface"): the xdg_surface associated with the + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER`: the xdg_surface associated with the * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER` - * ("SDL.window.wayland.xdg_toplevel"): the xdg_toplevel role associated + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role associated * with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER` - * ("SDL.window.wayland.xdg_popup"): the xdg_popup role associated with the + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role associated with the * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER` - * ("SDL.window.wayland.xdg_positioner"): the xdg_positioner associated with + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner associated with * the window, in popup mode * * On X11: * - * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER` ("SDL.window.x11.display"): the + * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER`: the * X11 Display associated with the window - * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER` ("SDL.window.x11.screen"): the + * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER`: the * screen number associated with the window - * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER` ("SDL.window.x11.window"): the + * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER`: the * X11 Window associated with the window * * \param window the window to query From 4942027117763c6e67818827c3f1b477fc2cf7e3 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 17:34:23 +0000 Subject: [PATCH 688/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 179 ++++++++++++++++---------------- include/SDL3/SDL_video.h | 211 +++++++++++++++++++------------------- 2 files changed, 198 insertions(+), 192 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 12ac17e27b65d..6d46d44158e06 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -240,15 +240,14 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * * These are the supported properties: * - * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER`: the window - * where rendering is displayed - * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER`: the surface - * where rendering is displayed, if you want a software renderer without a - * window - * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING`: the name of the - * rendering driver to use, if a specific one is desired - * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: - * true if you want present synchronized with the refresh rate + * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER`: the window where rendering + * is displayed + * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER`: the surface where + * rendering is displayed, if you want a software renderer without a window + * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING`: the name of the rendering + * driver to use, if a specific one is desired + * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want + * present synchronized with the refresh rate * * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call @@ -335,10 +334,10 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 * associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device - * associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device - * associated with the renderer + * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated + * with the renderer + * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated + * with the renderer * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the * ID3D12CommandQueue associated with the renderer * @@ -454,62 +453,68 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * These are the supported properties: * - * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER`: one of the - * enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA - * format for the renderer - * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER`: one of the - * enumerated values in SDL_TextureAccess, defaults to - * SDL_TEXTUREACCESS_STATIC - * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER`: the width of the - * texture in pixels, required - * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture - * in pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER`: one of the enumerated values + * in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer + * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER`: one of the enumerated values + * in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC + * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER`: the width of the texture in + * pixels, required + * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in + * pixels, required * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER`: - * the ID3D11Texture2D associated with the texture, if you want to wrap an - * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D associated with the U plane of a - * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D associated with the V plane of a - * YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER`: the + * ID3D11Texture2D associated with the U plane of a YUV texture, if you want + * to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER`: the + * ID3D11Texture2D associated with the V plane of a YUV texture, if you want + * to wrap an existing texture. * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER`: - * the ID3D12Resource associated with the texture, if you want to wrap an + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER`: the ID3D12Resource + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource + * associated with the U plane of a YUV texture, if you want to wrap an + * existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource + * associated with the V plane of a YUV texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER`: the - * ID3D12Resource associated with the U plane of a - * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource associated with the V plane of a - * YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER`: - * the GLuint texture associated with the texture, if you want to wrap an + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint + * texture associated with the UV plane of an NV12 texture, if you want to + * wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture + * associated with the U plane of a YUV texture, if you want to wrap an + * existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture + * associated with the V plane of a YUV texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture associated with the UV plane of - * an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture associated with the U plane of a - * YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture associated with the V plane of a - * YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the texture, if - * you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the texture, if - * you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture associated with the UV plane - * of an NV12 texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture associated with the U plane - * of a YUV texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture associated with the V plane - * of a YUV texture, if you want to wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint + * texture associated with the texture, if you want to wrap an existing + * texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint + * texture associated with the texture, if you want to wrap an existing + * texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint + * texture associated with the UV plane of an NV12 texture, if you want to + * wrap an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint + * texture associated with the U plane of a YUV texture, if you want to wrap + * an existing texture. + * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint + * texture associated with the V plane of a YUV texture, if you want to wrap + * an existing texture. * * \param renderer the rendering context * \param props the properties to use @@ -555,47 +560,47 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D associated with the - * texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D associated with the - * U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D associated with the - * V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D + * associated with the texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D + * associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D + * associated with the V plane of a YUV texture * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER`: the ID3D12Resource associated with the - * texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource associated with the U - * plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource associated with the V - * plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER`: the ID3D12Resource + * associated with the texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource + * associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource + * associated with the V plane of a YUV texture * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER`: the GLuint texture associated with the - * texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture associated with the - * UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture associated with the - * U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture associated with the - * V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT`: - * the texture coordinate width of the texture (0.0 - 1.0) - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT`: - * the texture coordinate height of the texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture + * associated with the UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture + * associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture + * associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT`: the texture coordinate width + * of the texture (0.0 - 1.0) + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT`: the texture coordinate height + * of the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture associated with the - * texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture associated with - * the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture associated with - * the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture associated with - * the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture + * associated with the UV plane of an NV12 texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture + * associated with the U plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture + * associated with the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 99eeff5c341fe..6c40bc13b372d 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -809,57 +809,53 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * These are the supported properties: * - * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: - * true if the window should be always on top - * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if - * the window has no window decoration - * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the - * window should accept keyboard input (defaults true) - * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN`: true if - * the window should start in fullscreen mode at desktop resolution - * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER`: the height of the - * window - * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN`: true if the - * window should start hidden - * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN`: true if the window uses a high pixel density - * buffer if possible - * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN`: true if the - * window should start maximized - * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN`: true if the window is - * a popup menu - * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN`: true if the window - * will be used with Metal rendering - * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the - * window should start minimized - * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN`: - * true if the window starts with grabbed mouse focus - * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN`: true if the - * window will be used with OpenGL rendering - * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER`: an SDL_Window - * that will be the parent of this window, required for windows with the - * "toolip" and "menu" properties - * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN`: true if the - * window should be resizable - * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING`: the title of the - * window, in UTF-8 encoding - * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN`: true if - * the window show transparent in the areas with alpha of 0 - * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN`: true if the - * window is a tooltip - * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN`: true if the - * window is a utility window, not showing in the task bar and window list - * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN`: true if the - * window will be used with Vulkan rendering - * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER`: the width of the - * window - * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER`: the x position of the - * window, or `SDL_WINDOWPOS_CENTERED`, defaults to - * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows - * with the "parent" property set. - * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER`: the y position of the - * window, or `SDL_WINDOWPOS_CENTERED`, defaults to - * `SDL_WINDOWPOS_UNDEFINED`. This is relative to the parent for windows - * with the "parent" property set. + * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window + * should be always on top + * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has + * no window decoration + * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should + * accept keyboard input (defaults true) + * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN`: true if the window + * should start in fullscreen mode at desktop resolution + * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER`: the height of the window + * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN`: true if the window should + * start hidden + * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN`: true if the + * window uses a high pixel density buffer if possible + * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN`: true if the window should + * start maximized + * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN`: true if the window is a popup + * menu + * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN`: true if the window will be + * used with Metal rendering + * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the window should + * start minimized + * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN`: true if the window + * starts with grabbed mouse focus + * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN`: true if the window will be + * used with OpenGL rendering + * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER`: an SDL_Window that will be + * the parent of this window, required for windows with the "toolip" and + * "menu" properties + * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN`: true if the window should + * be resizable + * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING`: the title of the window, in + * UTF-8 encoding + * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN`: true if the window show + * transparent in the areas with alpha of 0 + * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN`: true if the window is a + * tooltip + * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN`: true if the window is a + * utility window, not showing in the task bar and window list + * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN`: true if the window will be + * used with Vulkan rendering + * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER`: the width of the window + * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER`: the x position of the window, or + * `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is + * relative to the parent for windows with the "parent" property set. + * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER`: the y position of the window, or + * `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is + * relative to the parent for windows with the "parent" property set. * * These are additional supported properties on macOS: * @@ -872,16 +868,15 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * These are additional supported properties on Windows: * - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND - * associated with the window, if you want to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER`: optional, another window to share pixel - * format with, useful for OpenGL windows + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND associated with + * the window, if you want to wrap an existing window. + * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER`: optional, + * another window to share pixel format with, useful for OpenGL windows * * These are additional supported properties with X11: * - * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER`: the X11 - * Window associated with the window, if you want to wrap an existing - * window. + * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER`: the X11 Window associated + * with the window, if you want to wrap an existing window. * * The window is implicitly shown if the "hidden" property is not set. * @@ -981,52 +976,56 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * On Android: * - * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER`: the ANativeWindow associated with the - * window - * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER`: the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER`: the ANativeWindow + * associated with the window + * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER`: the EGLSurface associated + * with the window * * On iOS: * - * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER`: - * the `(__unsafe_unretained)` UIWindow associated with the window - * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag assocated with - * metal views on the window + * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER`: the `(__unsafe_unretained)` + * UIWindow associated with the window + * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag + * assocated with metal views on the window * * On KMS/DRM: * - * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER`: the device index associated with the - * window (e.g. the X in /dev/dri/cardX) - * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER`: - * the DRM FD associated with the window - * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER`: the GBM device associated with the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER`: the device index + * associated with the window (e.g. the X in /dev/dri/cardX) + * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER`: the DRM FD associated with + * the window + * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER`: the GBM device + * associated with the window * * On macOS: * - * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER`: - * the `(__unsafe_unretained)` NSWindow associated with the window - * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag assocated with - * metal views on the window + * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)` + * NSWindow associated with the window + * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag + * assocated with metal views on the window * * On Vivante: * - * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType associated with - * the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER`: the EGLNativeWindowType associated with - * the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType + * associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER`: the EGLNativeWindowType + * associated with the window + * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated + * with the window * * On UWP: * - * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER`: - * the IInspectable CoreWindow associated with the window + * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER`: the IInspectable CoreWindow + * associated with the window * * On Windows: * - * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER`: the - * HWND associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER`: the HDC - * associated with the window - * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER`: the HINSTANCE associated with the window + * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER`: the HWND associated with the + * window + * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER`: the HDC associated with the + * window + * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER`: the HINSTANCE associated + * with the window * * On Wayland: * @@ -1034,29 +1033,31 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * - * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER`: the wl_registry associated with the - * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER`: the wl_egl_window associated with the - * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER`: the xdg_surface associated with the - * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role associated + * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER`: the wl_registry + * associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated * with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role associated with the - * window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner associated with - * the window, in popup mode + * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated + * with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER`: the wl_egl_window + * associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER`: the xdg_surface + * associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role + * associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role + * associated with the window + * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner + * associated with the window, in popup mode * * On X11: * - * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER`: the - * X11 Display associated with the window - * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER`: the - * screen number associated with the window - * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER`: the - * X11 Window associated with the window + * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER`: the X11 Display associated + * with the window + * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER`: the screen number associated + * with the window + * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER`: the X11 Window associated with + * the window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call From 059fb560ba98df5668e1cf1c88560b3156e0fb66 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 8 Jan 2024 15:53:51 +0000 Subject: [PATCH 689/725] gamepad: Clarify range and direction of axes It would be easy to assume that all APIs that reference SDL_JOYSTICK_AXIS_MAX work the same way, but they do not: triggers generally use the full signed 16-bit range in the lower-level joystick API, but are normalized to be non-negative by the higher-level gamepad API. We also never said explicitly which direction is positive here. Experimentally, it's right (X), down (Y), and pressed (triggers). Resolves: https://github.com/libsdl-org/SDL/issues/8793 Signed-off-by: Simon McVittie --- include/SDL3/SDL_gamepad.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index be970e640b8fe..0e66b3b891c79 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -149,7 +149,9 @@ typedef enum * and are centered within ~8000 of zero, though advanced UI will allow users to set * or autodetect the dead zone, which varies between gamepads. * - * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX. + * Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX + * (fully pressed) when reported by SDL_GetGamepadAxis(). Note that this is not the + * same range that will be reported by the lower-level SDL_GetJoystickAxis(). */ typedef enum { @@ -961,8 +963,13 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_Ga * * The axis indices start at index 0. * - * The state is a value ranging from -32768 to 32767. Triggers, however, range - * from 0 to 32767 (they never return a negative value). + * For thumbsticks, the state is a value ranging from -32768 (up/left) + * to 32767 (down/right). + * + * Triggers range from 0 when released to 32767 when fully pressed, and + * never return a negative value. Note that this differs from the value + * reported by the lower-level SDL_GetJoystickAxis(), which normally uses + * the full range. * * \param gamepad a gamepad * \param axis an axis index (one of the SDL_GamepadAxis values) From 44adab7dfda2f16d5cea143da06c57e87f926d28 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 17:36:24 +0000 Subject: [PATCH 690/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_gamepad.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 0e66b3b891c79..98af9a17fef62 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -963,13 +963,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_Ga * * The axis indices start at index 0. * - * For thumbsticks, the state is a value ranging from -32768 (up/left) - * to 32767 (down/right). + * For thumbsticks, the state is a value ranging from -32768 (up/left) to + * 32767 (down/right). * - * Triggers range from 0 when released to 32767 when fully pressed, and - * never return a negative value. Note that this differs from the value - * reported by the lower-level SDL_GetJoystickAxis(), which normally uses - * the full range. + * Triggers range from 0 when released to 32767 when fully pressed, and never + * return a negative value. Note that this differs from the value reported by + * the lower-level SDL_GetJoystickAxis(), which normally uses the full range. * * \param gamepad a gamepad * \param axis an axis index (one of the SDL_GamepadAxis values) From 022ff075b9a0ae837f4489a5ed68a4e769b1ca98 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 8 Jan 2024 17:20:27 +0000 Subject: [PATCH 691/725] test: When listing test-cases, say which ones are disabled When a test has been disabled because it's known not to work reliably or it's a test for unimplemented functionality, we probably don't want to encourage developers and testers to run it and report its failures as a bug. Helps: #8798, #8800 Signed-off-by: Simon McVittie --- src/test/SDL_test_harness.c | 2 +- test/testautomation.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/SDL_test_harness.c b/src/test/SDL_test_harness.c index ed43b7a9870fa..73e23016ae627 100644 --- a/src/test/SDL_test_harness.c +++ b/src/test/SDL_test_harness.c @@ -504,7 +504,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user /* Within each suite, loop over all test cases to check if we have a filter match */ for (testCounter = 0; testSuite->testCases[testCounter]; ++testCounter) { testCase = testSuite->testCases[testCounter]; - SDLTest_Log(" test: %s", testCase->name); + SDLTest_Log(" test: %s%s", testCase->name, testCase->enabled ? "" : " (disabled)"); } } SDLTest_Log("Exit code: 2"); diff --git a/test/testautomation.c b/test/testautomation.c index bb691702b7853..7805bbc4a0f9a 100644 --- a/test/testautomation.c +++ b/test/testautomation.c @@ -133,7 +133,7 @@ int main(int argc, char *argv[]) SDL_Log("Test suite: %s", testSuite->name); for (testCounter = 0; testSuite->testCases[testCounter]; ++testCounter) { const SDLTest_TestCaseReference *testCase = testSuite->testCases[testCounter]; - SDL_Log(" test: %s", testCase->name); + SDL_Log(" test: %s%s", testCase->name, testCase->enabled ? "" : " (disabled)"); } } return 0; From 8e7c0b34d7961566929f50fededfbb7ce76fb926 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 8 Jan 2024 18:34:28 +0000 Subject: [PATCH 692/725] test: If SDL_CreateRenderer() fails, say why Helps: https://github.com/libsdl-org/SDL/issues/8799 Signed-off-by: Simon McVittie --- test/testautomation_render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testautomation_render.c b/test/testautomation_render.c index 9ab7ea4603937..67b1f4124cde9 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -64,7 +64,7 @@ static void InitCreateRenderer(void *arg) renderer = SDL_CreateRenderer(window, NULL, renderer_flags); SDLTest_AssertPass("SDL_CreateRenderer()"); - SDLTest_AssertCheck(renderer != NULL, "Check SDL_CreateRenderer result"); + SDLTest_AssertCheck(renderer != NULL, "Check SDL_CreateRenderer result: %s", renderer != NULL ? "success" : SDL_GetError()); if (renderer == NULL) { SDL_DestroyWindow(window); return; From df438a3170fcef32166e5b5e48ffeb6692b5913c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jan 2024 14:07:23 -0500 Subject: [PATCH 693/725] opengl: OpenGL renderers need to support texture target in properties. Otherwise this has to become an awkward heuristic in sdl2-compat. --- include/SDL3/SDL_render.h | 38 ++++++++++++++----------- src/render/opengl/SDL_render_gl.c | 1 + src/render/opengles2/SDL_render_gles2.c | 1 + 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 6d46d44158e06..0eae80b3e97bc 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -586,6 +586,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * associated with the U plane of a YUV texture * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture * associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET`: the GLenum for the texture + * target (`GL_TEXTURE_2D`, `GL_TEXTURE_RECTANGLE_ARB`, etc) * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT`: the texture coordinate width * of the texture (0.0 - 1.0) * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT`: the texture coordinate height @@ -601,6 +603,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * associated with the U plane of a YUV texture * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture * associated with the V plane of a YUV texture + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET`: the GLenum for the texture + * target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc) * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call @@ -613,22 +617,24 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" /* the ID3D11Texture2D associated with the texture */ -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" /* the ID3D11Texture2D associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" /* the ID3D11Texture2D associated with the V plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" /* the ID3D12Resource associated with the texture */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" /* the ID3D12Resource associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" /* the ID3D12Resource associated with the V plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" /* the GLuint texture associated with the texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" /* the texture coordinate width of the texture (0.0 - 1.0) */ -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" /* the texture coordinate height of the texture (0.0 - 1.0) */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" /* the GLuint texture associated with the texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" /* the GLuint texture associated with the UV plane of an NV12 texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" /* the GLuint texture associated with the U plane of a YUV texture */ -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" /* the GLuint texture associated with the V plane of a YUV texture */ +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" +#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" +#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET "SDL.texture.opengl.target" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" +#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" +#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET "SDL.texture.opengles2.target" /** * Get the renderer that created an SDL_Texture. diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 5baa897255365..9e57f550ac15d 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -532,6 +532,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr } SDL_PropertiesID props = SDL_GetTextureProperties(texture); SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER, data->texture); + SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET, (Sint64) textype); SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT, data->texw); SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT, data->texh); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 49e0139c634bb..5e63a4214e7b0 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1594,6 +1594,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL } } SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, data->texture); + SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET, data->texture_type); if (texture->access == SDL_TEXTUREACCESS_TARGET) { data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); From 95066ce2a0b37f0c703b9b63dfe6e8e407d10221 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 19:10:31 +0000 Subject: [PATCH 694/725] Sync SDL3 wiki -> header --- include/SDL3/SDL_render.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 0eae80b3e97bc..94eee2a9cf486 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -603,8 +603,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * associated with the U plane of a YUV texture * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture * associated with the V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET`: the GLenum for the texture - * target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc) + * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET`: the GLenum for the + * texture target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc) * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call From 82f2c4d58140be61e5508765dd734368bb31e152 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jan 2024 14:15:56 -0500 Subject: [PATCH 695/725] render: Renamed SDL_GetTextureRenderer to SDL_GetRendererFromTexture. --- include/SDL3/SDL_render.h | 2 +- src/dynapi/SDL_dynapi.sym | 2 +- src/dynapi/SDL_dynapi_overrides.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 2 +- src/render/SDL_render.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 94eee2a9cf486..2a5958dfe756d 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -651,7 +651,7 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t * \sa SDL_CreateTextureFromSurface * \sa SDL_CreateTextureWithProperties */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetTextureRenderer(SDL_Texture *texture); +extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRendererFromTexture(SDL_Texture *texture); /** * Query the attributes of a texture. diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 51f3629b81514..f8900f6811bf0 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -961,7 +961,7 @@ SDL3_0.0.0 { SDL_wcsnstr; SDL_SyncWindow; SDL_GetGamepadSteamHandle; - SDL_GetTextureRenderer; + SDL_GetRendererFromTexture; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index ddd57de6a69ac..b092b19e1d8f4 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -986,4 +986,4 @@ #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_SyncWindow SDL_SyncWindow_REAL #define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL -#define SDL_GetTextureRenderer SDL_GetTextureRenderer_REAL +#define SDL_GetRendererFromTexture SDL_GetRendererFromTexture_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 7d92febecd76f..4224568647975 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1011,4 +1011,4 @@ SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b, SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetTextureRenderer,(SDL_Texture *a),(a),return) +SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetRendererFromTexture,(SDL_Texture *a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 66453024b5261..7cd43c9b77457 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1396,7 +1396,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s return texture; } -SDL_Renderer *SDL_GetTextureRenderer(SDL_Texture *texture) +SDL_Renderer *SDL_GetRendererFromTexture(SDL_Texture *texture) { CHECK_TEXTURE_MAGIC(texture, NULL); return texture->renderer; From 392796e49c40bff0ad08ac899ffcd2834ad87aca Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 5 Jan 2024 12:21:42 -0500 Subject: [PATCH 696/725] wayland: Eliminate redundant protocol checks If the xdg_wm_base protocol isn't present, the window won't be assigned a valid surface type at creation time, which makes these checks redundant. The libdecor path was already cleaned up in this manner some time ago. --- src/video/wayland/SDL_waylandwindow.c | 28 ++++++++++++--------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 249cbcb34b13d..b14701c91a792 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -179,7 +179,6 @@ static void UnsetDrawSurfaceViewport(SDL_Window *window) static void SetMinMaxDimensions(SDL_Window *window) { SDL_WindowData *wind = window->driverdata; - SDL_VideoData *viddata = wind->waylandData; int min_width, min_height, max_width, max_height; if ((window->flags & SDL_WINDOW_FULLSCREEN) || wind->fullscreen_deadline_count) { @@ -217,7 +216,7 @@ static void SetMinMaxDimensions(SDL_Window *window) } } else #endif - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && viddata->shell.xdg) { + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { return; /* Can't do anything yet, wait for ShowWindow */ } @@ -418,8 +417,7 @@ static void ConfigureWindowGeometry(SDL_Window *window) struct wl_region *region; /* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */ - if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR && - viddata->shell.xdg && data->shell_surface.xdg.surface) { + if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR && data->shell_surface.xdg.surface) { xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height); } @@ -528,7 +526,7 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output) } } else #endif - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && viddata->shell.xdg) { + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { return; /* Can't do anything yet, wait for ShowWindow */ } @@ -1476,7 +1474,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } else #endif - if ((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) && c->shell.xdg) { + if (data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface); xdg_surface_set_user_data(data->shell_surface.xdg.surface, data); xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data); @@ -1559,7 +1557,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } } else #endif - if (c->shell.xdg) { + if (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP || data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { /* Unlike libdecor we need to call this explicitly to prevent a deadlock. * libdecor will call this as part of their configure event! * -flibit @@ -1716,7 +1714,6 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) } } else #endif - if (data->shell.xdg) { if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { Wayland_ReleasePopup(_this, window); } else if (wind->shell_surface.xdg.roleobj.toplevel) { @@ -1887,7 +1884,6 @@ int Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; #ifdef HAVE_LIBDECOR_H @@ -1899,7 +1895,7 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) } else #endif /* Note that xdg-shell does NOT provide a way to unset minimize! */ - if (viddata->shell.xdg) { + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { return; /* Can't do anything yet, wait for ShowWindow */ } @@ -1919,9 +1915,11 @@ void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_b } } else #endif + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if ((viddata->decoration_manager) && (wind->server_decoration)) { - const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; - zxdg_toplevel_decoration_v1_set_mode(wind->server_decoration, mode); + const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + zxdg_toplevel_decoration_v1_set_mode(wind->server_decoration, mode); + } } } @@ -1953,7 +1951,6 @@ void Wayland_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; if (wind->show_hide_sync_required) { @@ -1968,7 +1965,7 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) libdecor_frame_set_maximized(wind->shell_surface.libdecor.frame); } else #endif - if (viddata->shell.xdg) { + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { return; /* Can't do anything yet, wait for ShowWindow */ } @@ -1978,7 +1975,6 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_VideoData *viddata = _this->driverdata; SDL_WindowData *wind = window->driverdata; /* TODO: Check compositor capabilities to see if minimizing is supported */ @@ -1991,7 +1987,7 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); } else #endif - if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && viddata->shell.xdg) { + if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) { if (wind->shell_surface.xdg.roleobj.toplevel == NULL) { return; /* Can't do anything yet, wait for ShowWindow */ } From 4417250d0dd02f25302c61e87aebf8d9d45e55be Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 6 Jan 2024 14:40:08 -0500 Subject: [PATCH 697/725] wayland: Remove the registry from the window properties A Wayland registry object can only have one listener attached at a time, so an application attempting to use the backend SDL registry object for its own purposes will just result in an error. Remove this property, as it is of no use to applications and will only result in errors. If an application needs the registry, it needs to get the wl_display object via `SDL.window.wayland.display` and use wl_display_get_registry() to create a new registry object that it can attach its own listeners to. --- include/SDL3/SDL_video.h | 3 --- src/video/wayland/SDL_waylandwindow.c | 1 - 2 files changed, 4 deletions(-) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 6c40bc13b372d..0eefdec6d9530 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -1033,8 +1033,6 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * - * - `SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER`: the wl_registry - * associated with the window * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated * with the window * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated @@ -1086,7 +1084,6 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *win #define SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" #define SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" #define SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" -#define SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER "SDL.window.wayland.registry" #define SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" #define SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" #define SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index b14701c91a792..92ceb3ec1e830 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2154,7 +2154,6 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_REGISTRY_POINTER, c->registry); SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, data->waylandData->display); SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER, data->surface); SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER, data->egl_window); From f7dd0f9491ab52833801dce8b5ebc4694e8e7c39 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 6 Jan 2024 15:37:38 -0500 Subject: [PATCH 698/725] wayland: Allow the creation of roleless window surfaces for custom application use Allow for the creation of SDL windows with a roleless surface that applications can use for their own purposes, such as with a windowing protocol other than XDG toplevel. The property `wayland.surface_role_custom` will create a window with a surface that SDL can render to and handles input for, but is not associated with a toplevel window, so applications can use it for their own, custom purposes (e.g. wlr_layer_shell). A test/minimal example is included in tests/testwaylandcustom.c --- docs/README-wayland.md | 28 +++ include/SDL3/SDL_video.h | 65 ++--- src/video/wayland/SDL_waylandwindow.c | 87 ++++--- src/video/wayland/SDL_waylandwindow.h | 3 +- test/CMakeLists.txt | 9 + test/testwaylandcustom.c | 333 ++++++++++++++++++++++++++ 6 files changed, 466 insertions(+), 59 deletions(-) create mode 100644 test/testwaylandcustom.c diff --git a/docs/README-wayland.md b/docs/README-wayland.md index a376b48ad01c8..ffbadced1a246 100644 --- a/docs/README-wayland.md +++ b/docs/README-wayland.md @@ -43,3 +43,31 @@ encounter limitations or behavior that is different from other windowing systems on the format of this file. Note that if your application manually sets the application ID via the `SDL_APP_ID` hint string, the desktop entry file name should match the application ID. For example, if your application ID is set to `org.my_org.sdl_app`, the desktop entry file should be named `org.my_org.sdl_app.desktop`. + +## Using custom Wayland windowing protocols with SDL windows + +Under normal operation, an `SDL_Window` corresponds to an XDG toplevel window, which provides a standard desktop window. +If an application wishes to use a different windowing protocol with an SDL window (e.g. wlr_layer_shell) while still +having SDL handle input and rendering, it needs to create a custom, roleless surface and attach that surface to its own +toplevel window. + +This is done by using `SDL_CreateWindowWithProperties()` and setting the +`SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` property to `SDL_TRUE`. Once the window has been +successfully created, the `wl_display` and `wl_surface` objects can then be retrieved from the +`SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` and `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` properties respectively. + +Surfaces don't receive any size change notifications, so if an application changes the window size, it must inform SDL +that the surface size has changed by calling SDL_SetWindowSize() with the new dimensions. + +Custom surfaces will automatically handle scaling internally if the window was created with the `high-pixel-density` +property set to `SDL_TRUE`. In this case, applications should not manually attach viewports or change the surface scale +value, as SDL will handle this internally. Calls to `SDL_SetWindowSize()` should use the logical size of the window, and +`SDL_GetWindowSizeInPixels()` should be used to query the size of the backbuffer surface in pixels. If this property is +not set or is `SDL_FALSE`, applications can attach their own viewports or change the surface scale manually, and the SDL +backend will not interfere or change any values internally. In this case, calls to `SDL_SetWindowSize()` should pass the +requested surface size in pixels, not the logical window size, as no scaling calculations will be done internally. + +All window functions that control window state aside from `SDL_SetWindowSize()` are no-ops with custom surfaces. + +Please see the minimal example in tests/testwaylandcustom.c for an example of how to use a custom, roleless surface and +attach it to an application-managed toplevel window. \ No newline at end of file diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 0eefdec6d9530..7c223fe40d2a1 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -866,6 +866,13 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * `(__unsafe_unretained)` NSView associated with the window, defaults to * `[window contentView]` * + * These are additional supported properties on Wayland: + * + * - `SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true + * if the application wants to use the Wayland surface for a custom role and + * does not want it attached to an XDG toplevel window. See + * docs/README-wayland.md for more information on using custom surfaces. + * * These are additional supported properties on Windows: * * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND associated with @@ -894,35 +901,35 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); -#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" -#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" -#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" -#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" -#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" -#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" -#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" -#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" -#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" -#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" -#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" -#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" -#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" -#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" -#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" -#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" -#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" -#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" -#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" -#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" -#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" -#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" -#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" -#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" - +#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" +#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" +#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" +#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" +#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" +#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" +#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" +#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" +#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" +#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" +#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" +#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" +#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" +#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" +#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" +#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" +#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" +#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" +#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" +#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" +#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" +#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" +#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" +#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" +#define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "wayland.surface_role_custom" +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" +#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" +#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" /** * Get the numeric ID of a window. diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 92ceb3ec1e830..ddc585d2e409b 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -395,8 +395,10 @@ static void ConfigureWindowGeometry(SDL_Window *window) wl_surface_set_buffer_scale(data->surface, 1); SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height, window_width, window_height); - } else { + } else if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) { UnsetDrawSurfaceViewport(window); + + /* Don't change this if DPI awareness flag is unset, as an application may have set this manually. */ wl_surface_set_buffer_scale(data->surface, (int32_t)data->windowed_scale_factor); } @@ -1415,6 +1417,11 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_WindowData *data = window->driverdata; SDL_PropertiesID props = SDL_GetWindowProperties(window); + /* Custom surfaces don't get toplevels and are always considered 'shown'; nothing to do here. */ + if (data->shell_surface_type == WAYLAND_SURFACE_CUSTOM) { + return; + } + /* If this is a child window, the parent *must* be in the final shown state, * meaning that it has received a configure event, followed by a frame callback. * If not, a race condition can result, with effects ranging from the child @@ -1437,8 +1444,6 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) WAYLAND_wl_display_roundtrip(c->display); } - data->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE; - /* Detach any previous buffers before resetting everything, otherwise when * calling this a second time you'll get an annoying protocol error! * @@ -1683,6 +1688,11 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) SDL_WindowData *wind = window->driverdata; SDL_PropertiesID props = SDL_GetWindowProperties(window); + /* Custom surfaces have nothing to destroy and are always considered to be 'shown'; nothing to do here. */ + if (wind->shell_surface_type == WAYLAND_SURFACE_CUSTOM) { + return; + } + /* The window was shown, but the sync point hasn't yet been reached. * Pump events to avoid a possible protocol violation. */ @@ -1715,17 +1725,16 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) } else #endif if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) { - Wayland_ReleasePopup(_this, window); - } else if (wind->shell_surface.xdg.roleobj.toplevel) { - xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel); - wind->shell_surface.xdg.roleobj.toplevel = NULL; - SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL); - } - if (wind->shell_surface.xdg.surface) { - xdg_surface_destroy(wind->shell_surface.xdg.surface); - wind->shell_surface.xdg.surface = NULL; - SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL); - } + Wayland_ReleasePopup(_this, window); + } else if (wind->shell_surface.xdg.roleobj.toplevel) { + xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel); + wind->shell_surface.xdg.roleobj.toplevel = NULL; + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL); + } + if (wind->shell_surface.xdg.surface) { + xdg_surface_destroy(wind->shell_surface.xdg.surface); + wind->shell_surface.xdg.surface = NULL; + SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL); } wind->show_hide_sync_required = SDL_TRUE; @@ -1844,6 +1853,11 @@ int Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_WindowData *wind = window->driverdata; struct wl_output *output = display->driverdata->output; + /* Custom surfaces have no toplevel to make fullscreen. */ + if (wind->shell_surface_type == WAYLAND_SURFACE_CUSTOM) { + return -1; + } + if (wind->show_hide_sync_required) { WAYLAND_wl_display_roundtrip(_this->driverdata->display); } @@ -2041,6 +2055,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert { SDL_WindowData *data; SDL_VideoData *c; + const SDL_bool custom_surface_role = SDL_GetBooleanProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN, SDL_FALSE); data = SDL_calloc(1, sizeof(*data)); if (!data) { @@ -2140,18 +2155,24 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert /* We may need to create an idle inhibitor for this new window */ Wayland_SuspendScreenSaver(_this); + if (!custom_surface_role) { #ifdef HAVE_LIBDECOR_H - if (c->shell.libdecor && !SDL_WINDOW_IS_POPUP(window)) { - data->shell_surface_type = WAYLAND_SURFACE_LIBDECOR; - } else + if (c->shell.libdecor && !SDL_WINDOW_IS_POPUP(window)) { + data->shell_surface_type = WAYLAND_SURFACE_LIBDECOR; + } else #endif - if (c->shell.xdg) { - if (SDL_WINDOW_IS_POPUP(window)) { - data->shell_surface_type = WAYLAND_SURFACE_XDG_POPUP; - } else { - data->shell_surface_type = WAYLAND_SURFACE_XDG_TOPLEVEL; - } - } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ + if (c->shell.xdg) { + if (SDL_WINDOW_IS_POPUP(window)) { + data->shell_surface_type = WAYLAND_SURFACE_XDG_POPUP; + } else { + data->shell_surface_type = WAYLAND_SURFACE_XDG_TOPLEVEL; + } + } /* All other cases will be WAYLAND_SURFACE_UNKNOWN */ + } else { + /* Roleless surfaces are always considered to be in the shown state by the backend. */ + data->shell_surface_type = WAYLAND_SURFACE_CUSTOM; + data->surface_status = WAYLAND_SURFACE_STATUS_SHOWN; + } SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, data->waylandData->display); @@ -2259,12 +2280,20 @@ void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *wind = window->driverdata; - /* Queue an event to send the window size. */ - struct wl_callback *cb = wl_display_sync(_this->driverdata->display); + if (wind->shell_surface_type != WAYLAND_SURFACE_CUSTOM) { + /* Queue an event to send the window size. */ + struct wl_callback *cb = wl_display_sync(_this->driverdata->display); - wind->pending_size_event.width = window->floating.w; - wind->pending_size_event.height = window->floating.h; - wl_callback_add_listener(cb, &size_event_listener, (void*)((uintptr_t)window->id)); + wind->pending_size_event.width = window->floating.w; + wind->pending_size_event.height = window->floating.h; + wl_callback_add_listener(cb, &size_event_listener, (void *)((uintptr_t)window->id)); + } else { + /* We are being informed of a size change on a custom surface, just configure. */ + wind->requested_window_width = window->floating.w; + wind->requested_window_height = window->floating.h; + + ConfigureWindowGeometry(window); + } } void Wayland_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h) diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index f7f5037175b2b..96c7a0eab7395 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -70,7 +70,8 @@ struct SDL_WindowData WAYLAND_SURFACE_UNKNOWN = 0, WAYLAND_SURFACE_XDG_TOPLEVEL, WAYLAND_SURFACE_XDG_POPUP, - WAYLAND_SURFACE_LIBDECOR + WAYLAND_SURFACE_LIBDECOR, + WAYLAND_SURFACE_CUSTOM } shell_surface_type; enum { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 98fc28c95cd6d..7604e0e65eb75 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -398,6 +398,15 @@ add_sdl_test_executable(testvulkan NO_C90 SOURCES testvulkan.c) add_sdl_test_executable(testoffscreen SOURCES testoffscreen.c) add_sdl_test_executable(testpopup SOURCES testpopup.c) +if (HAVE_WAYLAND) + # Set the GENERATED property on the protocol file, since it is first created at build time + set_property(SOURCE ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c PROPERTY GENERATED 1) + add_sdl_test_executable(testwaylandcustom NO_C90 NEEDS_RESOURCES SOURCES testwaylandcustom.c ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c) + # Needed to silence the documentation warning in the generated header file + target_compile_options(testwaylandcustom PRIVATE -Wno-documentation-unknown-command) + target_link_libraries(testwaylandcustom PRIVATE wayland-client) +endif() + check_c_compiler_flag(-Wformat-overflow HAVE_WFORMAT_OVERFLOW) if(HAVE_WFORMAT_OVERFLOW) target_compile_definitions(testautomation PRIVATE HAVE_WFORMAT_OVERFLOW) diff --git a/test/testwaylandcustom.c b/test/testwaylandcustom.c new file mode 100644 index 0000000000000..3e1042bbbe7d8 --- /dev/null +++ b/test/testwaylandcustom.c @@ -0,0 +1,333 @@ +/* + Copyright (C) 1997-2024 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ + +#include +#include + +#include +#include +#include + +#include "icon.h" + +#define WINDOW_WIDTH 640 +#define WINDOW_HEIGHT 480 +#define NUM_SPRITES 100 +#define MAX_SPEED 1 + +static SDL_Window *window; +static SDL_Renderer *renderer; +static SDL_Texture *sprite; +static SDL_FRect positions[NUM_SPRITES]; +static SDL_FRect velocities[NUM_SPRITES]; +static int sprite_w, sprite_h; +static int done; + +static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) +{ + SDL_Texture *texture = NULL; + SDL_Surface *surface; + SDL_RWops *src = SDL_RWFromConstMem(data, len); + if (src) { + surface = SDL_LoadBMP_RW(src, SDL_TRUE); + if (surface) { + /* Treat white as transparent */ + SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255)); + + texture = SDL_CreateTextureFromSurface(r, surface); + *w = surface->w; + *h = surface->h; + SDL_DestroySurface(surface); + } + } + return texture; +} + +static void MoveSprites(void) +{ + int i; + int window_w; + int window_h; + SDL_FRect *position, *velocity; + + /* Get the window size */ + SDL_GetWindowSizeInPixels(window, &window_w, &window_h); + + /* Draw a gray background */ + SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); + SDL_RenderClear(renderer); + + /* Move the sprite, bounce at the wall, and draw */ + for (i = 0; i < NUM_SPRITES; ++i) { + position = &positions[i]; + velocity = &velocities[i]; + position->x += velocity->x; + if ((position->x < 0) || (position->x >= (window_w - sprite_w))) { + velocity->x = -velocity->x; + position->x += velocity->x; + } + position->y += velocity->y; + if ((position->y < 0) || (position->y >= (window_h - sprite_h))) { + velocity->y = -velocity->y; + position->y += velocity->y; + } + + /* Blit the sprite onto the screen */ + SDL_RenderTexture(renderer, sprite, NULL, position); + } + + /* Update the screen! */ + SDL_RenderPresent(renderer); +} + +static int InitSprites(void) +{ + /* Create the sprite texture and initialize the sprite positions */ + sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h); + + if (!sprite) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create sprite texture"); + return -1; + } + + srand((unsigned int)time(NULL)); + for (int i = 0; i < NUM_SPRITES; ++i) { + positions[i].x = (float)(rand() % (WINDOW_WIDTH - sprite_w)); + positions[i].y = (float)(rand() % (WINDOW_HEIGHT - sprite_h)); + positions[i].w = (float)sprite_w; + positions[i].h = (float)sprite_h; + velocities[i].x = 0.0f; + velocities[i].y = 0.0f; + while (!velocities[i].x && !velocities[i].y) { + velocities[i].x = (float)((rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED); + velocities[i].y = (float)((rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED); + } + } + + return 0; +} + +/* Encapsulated in a struct to silence shadow variable warnings */ +static struct _state +{ + /* These are owned by SDL and must not be destroyed! */ + struct wl_display *wl_display; + struct wl_surface *wl_surface; + + /* These are owned by the application and need to be cleaned up on exit. */ + struct wl_registry *wl_registry; + struct xdg_wm_base *xdg_wm_base; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; +} state; + +static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) +{ + xdg_surface_ack_configure(state.xdg_surface, serial); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = xdg_surface_configure, +}; + +static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) +{ + /* NOP */ +} + +static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) +{ + done = 1; +} + +static void xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) +{ + /* NOP */ +} + +static void xdg_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) +{ + /* NOP */ +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_configure, + .close = xdg_toplevel_close, + .configure_bounds = xdg_toplevel_configure_bounds, + .wm_capabilities = xdg_toplevel_wm_capabilities +}; + +static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + xdg_wm_base_pong(state.xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = xdg_wm_base_ping, +}; + +static void registry_global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version) +{ + if (SDL_strcmp(interface, xdg_wm_base_interface.name) == 0) { + state.xdg_wm_base = wl_registry_bind(state.wl_registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(state.xdg_wm_base, &xdg_wm_base_listener, NULL); + } +} + +static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) +{ + /* NOP */ +} + +static const struct wl_registry_listener wl_registry_listener = { + .global = registry_global, + .global_remove = registry_global_remove, +}; + +int main(int argc, char **argv) +{ + int ret = -1; + SDL_PropertiesID props; + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { + return -1; + } + + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") != 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Video driver must be 'wayland', not '%s'", SDL_GetCurrentVideoDriver()); + goto exit; + } + + /* Create a window with the custom surface role property set. */ + props = SDL_CreateProperties(); + SDL_SetBooleanProperty(props, SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN, SDL_TRUE); /* Roleless surface */ + SDL_SetBooleanProperty(props, SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN, SDL_TRUE); /* OpenGL enabled */ + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, WINDOW_WIDTH); /* Default width */ + SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, WINDOW_HEIGHT); /* Default height */ + SDL_SetBooleanProperty(props, SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, SDL_TRUE); /* Handle DPI scaling internally */ + SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, "Wayland custom surface role test"); /* Default title */ + + window = SDL_CreateWindowWithProperties(props); + if (!window) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation failed"); + goto exit; + } + + /* Create the renderer */ + renderer = SDL_CreateRenderer(window, NULL, 0); + if (!renderer) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Renderer creation failed"); + goto exit; + } + + /* Get the display object and use it to create a registry object, which will enumerate the xdg_wm_base protocol. */ + state.wl_display = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, NULL); + state.wl_registry = wl_display_get_registry(state.wl_display); + wl_registry_add_listener(state.wl_registry, &wl_registry_listener, NULL); + + /* Roundtrip to enumerate registry objects. */ + wl_display_roundtrip(state.wl_display); + + if (!state.xdg_wm_base) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "'xdg_wm_base' protocol not found!"); + goto exit; + } + + /* Get the wl_surface object from the SDL_Window, and create a toplevel window with it. */ + state.wl_surface = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER, NULL); + + /* Create the xdg_surface from the wl_surface. */ + state.xdg_surface = xdg_wm_base_get_xdg_surface(state.xdg_wm_base, state.wl_surface); + xdg_surface_add_listener(state.xdg_surface, &xdg_surface_listener, NULL); + + /* Create the xdg_toplevel from the xdg_surface. */ + state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface); + xdg_toplevel_add_listener(state.xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title(state.xdg_toplevel, SDL_GetWindowTitle(window)); + + /* Initialize the sprites. */ + if (InitSprites() < 0) { + goto exit; + } + + while (!done) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_KEY_DOWN) { + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + done = 1; + break; + case SDLK_EQUALS: + /* Ctrl+ enlarges the window */ + if (event.key.keysym.mod & SDL_KMOD_CTRL) { + int w, h; + SDL_GetWindowSize(window, &w, &h); + SDL_SetWindowSize(window, w * 2, h * 2); + } + break; + case SDLK_MINUS: + /* Ctrl- shrinks the window */ + if (event.key.keysym.mod & SDL_KMOD_CTRL) { + int w, h; + SDL_GetWindowSize(window, &w, &h); + SDL_SetWindowSize(window, w / 2, h / 2); + } + break; + default: + break; + } + } + } + + /* Draw the sprites */ + MoveSprites(); + } + + ret = 0; + +exit: + /* The display and surface handles obtained from SDL are owned by SDL and must *NOT* be destroyed here! */ + if (state.xdg_toplevel) { + xdg_toplevel_destroy(state.xdg_toplevel); + state.xdg_toplevel = NULL; + } + if (state.xdg_surface) { + xdg_surface_destroy(state.xdg_surface); + state.xdg_surface = NULL; + } + if (state.xdg_wm_base) { + xdg_wm_base_destroy(state.xdg_wm_base); + state.xdg_wm_base = NULL; + } + if (state.wl_registry) { + wl_registry_destroy(state.wl_registry); + state.wl_registry = NULL; + } + + /* Destroy the SDL resources */ + if (sprite) { + SDL_DestroyTexture(sprite); + sprite = NULL; + } + if (renderer) { + SDL_DestroyRenderer(renderer); + renderer = NULL; + } + if (window) { + SDL_DestroyWindow(window); + window = NULL; + } + + SDL_Quit(); + return ret; +} From 4b6df8923854a9e5661fa18775470397da956077 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 7 Jan 2024 12:25:49 -0500 Subject: [PATCH 699/725] wayland: Add a property to allow creation of a wl_egl_window object even if OpenGL is not enabled Useful if the application handles OpenGL outside of SDL and wants to use the window without having to pull in Wayland as a dependency. --- include/SDL3/SDL_video.h | 4 ++++ src/video/wayland/SDL_waylandwindow.c | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 7c223fe40d2a1..d64f015a5eb7f 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -872,6 +872,9 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * if the application wants to use the Wayland surface for a custom role and * does not want it attached to an XDG toplevel window. See * docs/README-wayland.md for more information on using custom surfaces. + * - `SDL_PROPERTY_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN - true if + * the application wants an associated `wl_egl_window` object to be created, + * even if the window does not have the OpenGL property or flag set. * * These are additional supported properties on Windows: * @@ -927,6 +930,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_Propertie #define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" #define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" #define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "wayland.surface_role_custom" +#define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "wayland.create_egl_window" #define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" #define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" #define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index ddc585d2e409b..7866b066715d0 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2056,6 +2056,8 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert SDL_WindowData *data; SDL_VideoData *c; const SDL_bool custom_surface_role = SDL_GetBooleanProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN, SDL_FALSE); + const SDL_bool create_egl_window = !!(window->flags & SDL_WINDOW_OPENGL) || + SDL_GetBooleanProperty(create_props, SDL_PROPERTY_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN, SDL_FALSE); data = SDL_calloc(1, sizeof(*data)); if (!data) { @@ -2129,18 +2131,20 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } } - if (window->flags & SDL_WINDOW_OPENGL) { + if (create_egl_window) { data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height); + } #ifdef SDL_VIDEO_OPENGL_EGL + if (window->flags & SDL_WINDOW_OPENGL) { /* Create the GLES window surface */ data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->egl_window); if (data->egl_surface == EGL_NO_SURFACE) { return -1; /* SDL_EGL_CreateSurface should have set error */ } -#endif } +#endif if (c->relative_mouse_mode) { Wayland_input_lock_pointer(c->input); From 05d18aab1ce16f0f94ee70dbc0e8c8680d1a7c64 Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 8 Jan 2024 19:55:19 +0000 Subject: [PATCH 700/725] Sync SDL3 wiki -> header --- docs/README-wayland.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-wayland.md b/docs/README-wayland.md index ffbadced1a246..c145230f8a722 100644 --- a/docs/README-wayland.md +++ b/docs/README-wayland.md @@ -67,7 +67,7 @@ not set or is `SDL_FALSE`, applications can attach their own viewports or change backend will not interfere or change any values internally. In this case, calls to `SDL_SetWindowSize()` should pass the requested surface size in pixels, not the logical window size, as no scaling calculations will be done internally. -All window functions that control window state aside from `SDL_SetWindowSize()` are no-ops with custom surfaces. +All window functions that control window state aside from `SDL_SetWindowSize()` are no-ops with custom surfaces. Please see the minimal example in tests/testwaylandcustom.c for an example of how to use a custom, roleless surface and -attach it to an application-managed toplevel window. \ No newline at end of file +attach it to an application-managed toplevel window. From 5948ea997ff32c800e66c0ba722d8e2712404e68 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 8 Jan 2024 13:54:18 -0800 Subject: [PATCH 701/725] Make sure new windows have mouse and keyboard focus if there's no windowing system --- src/video/SDL_video.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 8efd6f0dd7481..3813b30dd6d49 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2131,9 +2131,15 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) parent->first_child = window; } - if (_this->CreateSDLWindow && _this->CreateSDLWindow(_this, window, props) < 0) { - SDL_DestroyWindow(window); - return NULL; + if (_this->CreateSDLWindow) { + if (_this->CreateSDLWindow(_this, window, props) < 0) { + SDL_DestroyWindow(window); + return NULL; + } + } else { + /* No windowing system, make sure the new window has focus */ + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); } /* Clear minimized if not on windows, only windows handles it at create rather than FinishWindowCreation, From 590d0bec6f2feb4ff5d167c8bd83004e9420c9a7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 8 Jan 2024 14:32:28 -0800 Subject: [PATCH 702/725] Revert "Make sure new windows have mouse and keyboard focus if there's no windowing system" This reverts commit 5948ea997ff32c800e66c0ba722d8e2712404e68. This isn't needed, the proper focus logic is in SDL_ShowWindow() --- src/video/SDL_video.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 3813b30dd6d49..8efd6f0dd7481 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2131,15 +2131,9 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) parent->first_child = window; } - if (_this->CreateSDLWindow) { - if (_this->CreateSDLWindow(_this, window, props) < 0) { - SDL_DestroyWindow(window); - return NULL; - } - } else { - /* No windowing system, make sure the new window has focus */ - SDL_SetMouseFocus(window); - SDL_SetKeyboardFocus(window); + if (_this->CreateSDLWindow && _this->CreateSDLWindow(_this, window, props) < 0) { + SDL_DestroyWindow(window); + return NULL; } /* Clear minimized if not on windows, only windows handles it at create rather than FinishWindowCreation, From ccae9c1ef6b70f4d91eaf4e95f48ee806b8081bd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 8 Jan 2024 13:38:29 -0800 Subject: [PATCH 703/725] Only initialize audio drivers that have been requested If testautomation is running with only a specific audio driver enabled, we shouldn't try to open other ones, as they might fail. Fixes https://github.com/libsdl-org/SDL/issues/8797 (cherry picked from commit 4c11307a4e75fbfde0d8ace6b19d612d2973bf0b) --- test/testautomation_audio.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c index 71b20ff564c04..42d90fde6a137 100644 --- a/test/testautomation_audio.c +++ b/test/testautomation_audio.c @@ -87,6 +87,7 @@ static int audio_initQuitAudio(void *arg) int result; int i, iMax; const char *audioDriver; + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); @@ -102,6 +103,10 @@ static int audio_initQuitAudio(void *arg) SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ + if (hint && SDL_strcmp(audioDriver, hint) != 0) { + continue; + } + /* Call Init */ SDL_SetHint("SDL_AUDIO_DRIVER", audioDriver); result = SDL_InitSubSystem(SDL_INIT_AUDIO); @@ -146,6 +151,7 @@ static int audio_initOpenCloseQuitAudio(void *arg) int i, iMax, j, k; const char *audioDriver; SDL_AudioSpec desired; + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); @@ -161,6 +167,10 @@ static int audio_initOpenCloseQuitAudio(void *arg) SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ + if (hint && SDL_strcmp(audioDriver, hint) != 0) { + continue; + } + /* Change specs */ for (j = 0; j < 2; j++) { @@ -231,6 +241,7 @@ static int audio_pauseUnpauseAudio(void *arg) int result; const char *audioDriver; SDL_AudioSpec desired; + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); @@ -246,6 +257,10 @@ static int audio_pauseUnpauseAudio(void *arg) SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ + if (hint && SDL_strcmp(audioDriver, hint) != 0) { + continue; + } + /* Change specs */ for (j = 0; j < 2; j++) { From 3a219caf3da11df9feed819be6d2b08c10d44cfc Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 8 Jan 2024 18:00:28 -0500 Subject: [PATCH 704/725] wayland: Restore accidentally removed line of code --- src/video/wayland/SDL_waylandwindow.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 7866b066715d0..7c77f1e044662 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1444,6 +1444,8 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) WAYLAND_wl_display_roundtrip(c->display); } + data->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE; + /* Detach any previous buffers before resetting everything, otherwise when * calling this a second time you'll get an annoying protocol error! * From 6407e0cc37185997480ca66d90d4ec6d8b276481 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 9 Jan 2024 11:43:12 -0800 Subject: [PATCH 705/725] Added attribution for GIP protocol handling (thanks @medusalix!) --- src/joystick/hidapi/SDL_hidapi_xboxone.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index a7a6508fdc95b..4631f1fa8877e 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -1154,6 +1154,10 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateInitState(SDL_DriverXboxOne_Context * return SDL_TRUE; } +/* GIP protocol handling adapted under the Zlib license with permission from @medusalix: + * https://github.com/medusalix/xone/blob/master/bus/protocol.h + * https://github.com/medusalix/xone/blob/master/bus/protocol.c + */ #define GIP_HEADER_MIN_LENGTH 3 /* Internal commands */ From 9a77813df0404e518013724925aacd060b60b8dd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 10 Jan 2024 06:25:49 -0800 Subject: [PATCH 706/725] WinMain is specified by the Win32 API as having extern "C" linkage Fixes https://github.com/libsdl-org/SDL/issues/8814 --- include/SDL3/SDL_main_impl.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index 33a3d4347a20d..2ba34271fbc8a 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -100,6 +100,10 @@ int main(int argc, char *argv[]) #endif /* _MSC_VER && ! __GDK__ */ /* This is where execution begins [windowed apps and GDK] */ + +#ifdef __cplusplus +extern "C" { +#endif #if defined( UNICODE ) && UNICODE int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrev, PWSTR szCmdLine, int sw) #else /* ANSI */ @@ -112,6 +116,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) (void)sw; return SDL_RunApp(0, NULL, SDL_main, NULL); } +#ifdef __cplusplus +} /* extern "C" */ +#endif /* end of __WIN32__ and __GDK__ impls */ #elif defined(__WINRT__) @@ -163,10 +170,16 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) #pragma comment(lib, "runtimeobject.lib") #endif +#ifdef __cplusplus +extern "C" { +#endif int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { return SDL_RunApp(0, NULL, SDL_main, NULL); } +#ifdef __cplusplus +} /* extern "C" */ +#endif /* end of WinRT impl */ #elif defined(__NGAGE__) From ec2159d4920205b6a6bfb46286a2419257b75df7 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 10 Jan 2024 11:17:06 -0500 Subject: [PATCH 707/725] tests: Clean up the window creation properties in the Wayland custom surface example --- test/testwaylandcustom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testwaylandcustom.c b/test/testwaylandcustom.c index 3e1042bbbe7d8..19196f2187da0 100644 --- a/test/testwaylandcustom.c +++ b/test/testwaylandcustom.c @@ -217,6 +217,7 @@ int main(int argc, char **argv) SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, "Wayland custom surface role test"); /* Default title */ window = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation failed"); goto exit; From d766f68cb30b058277b8d574c9d5a230265cbe73 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 10 Jan 2024 14:41:15 -0600 Subject: [PATCH 708/725] Fix compile error with XInputOnGameInput.h --- src/core/windows/SDL_xinput.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/windows/SDL_xinput.h b/src/core/windows/SDL_xinput.h index 4790fec21dae8..d9c840db9f59c 100644 --- a/src/core/windows/SDL_xinput.h +++ b/src/core/windows/SDL_xinput.h @@ -28,6 +28,7 @@ #ifdef HAVE_XINPUT_H #if defined(__XBOXONE__) || defined(__XBOXSERIES__) /* Xbox supports an XInput wrapper which is a C++-only header... */ +#include /* Required to compile with recent MSVC... */ #include using namespace XInputOnGameInput; #else From b5bc64aa553fe12d09fe2821eace14ea5b948bd9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 10 Jan 2024 06:36:02 -0800 Subject: [PATCH 709/725] Fixed pause key on Windows (thanks Mikhail!) --- src/video/windows/SDL_windowsevents.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 63bc28a76e4ba..f9d1c0211fa3c 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -162,6 +162,9 @@ static SDL_Scancode WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam) if (scanCode != 0) { if ((keyFlags & KF_EXTENDED) == KF_EXTENDED) { scanCode = MAKEWORD(scanCode, 0xe0); + } else if (scanCode == 0x45) { + /* Pause */ + scanCode = 0xe046; } } else { Uint16 vkCode = LOWORD(wParam); From 0c6b07076149775ced022227cde118ef333993cf Mon Sep 17 00:00:00 2001 From: George Broughton Date: Thu, 11 Jan 2024 16:11:12 +0100 Subject: [PATCH 710/725] Capture debug macros off by default --- src/video/SDL_video_capture.c | 2 +- src/video/SDL_video_capture_v4l2.c | 4 +++- src/video/android/SDL_android_video_capture.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video/SDL_video_capture.c b/src/video/SDL_video_capture.c index 295fc248315c8..ea43ff9cdafb5 100644 --- a/src/video/SDL_video_capture.c +++ b/src/video/SDL_video_capture.c @@ -27,7 +27,7 @@ #include "SDL_pixels_c.h" #include "../thread/SDL_systhread.h" -#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 +#define DEBUG_VIDEO_CAPTURE_CAPTURE 0 #ifdef SDL_VIDEO_CAPTURE diff --git a/src/video/SDL_video_capture_v4l2.c b/src/video/SDL_video_capture_v4l2.c index b826704e4b7cf..3edc26322fd00 100644 --- a/src/video/SDL_video_capture_v4l2.c +++ b/src/video/SDL_video_capture_v4l2.c @@ -32,7 +32,7 @@ #include "../../core/linux/SDL_udev.h" #include /* INT_MAX */ -#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 +#define DEBUG_VIDEO_CAPTURE_CAPTURE 0 #if defined(__linux__) && !defined(__ANDROID__) @@ -692,6 +692,7 @@ GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width +#if DEBUG_VIDEO_CAPTURE_CAPTURE static void dbg_v4l2_pixelformat(const char *str, int f) { SDL_Log("%s V4L2_format=%d %c%c%c%c", str, f, @@ -700,6 +701,7 @@ dbg_v4l2_pixelformat(const char *str, int f) { (f >> 16) & 0xff, (f >> 24) & 0xff); } +#endif int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) diff --git a/src/video/android/SDL_android_video_capture.c b/src/video/android/SDL_android_video_capture.c index 3deec8140335a..55393b08b2d76 100644 --- a/src/video/android/SDL_android_video_capture.c +++ b/src/video/android/SDL_android_video_capture.c @@ -27,7 +27,7 @@ #include "../SDL_pixels_c.h" #include "../../thread/SDL_systhread.h" -#define DEBUG_VIDEO_CAPTURE_CAPTURE 1 +#define DEBUG_VIDEO_CAPTURE_CAPTURE 0 #if defined(__ANDROID__) && __ANDROID_API__ >= 24 From cf0d1d7234e4ce1cc05d4e0ff1517c33363dfe7b Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 11 Jan 2024 09:26:55 +0100 Subject: [PATCH 711/725] Fixed ASAN warning, runtime error: left shift of 160 by 24 places cannot be represented in type 'int' --- test/testautomation_guid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testautomation_guid.c b/test/testautomation_guid.c index ff3718a844b8c..7bd1d90e0dca2 100644 --- a/test/testautomation_guid.c +++ b/test/testautomation_guid.c @@ -126,7 +126,7 @@ TestGuidToString(void *arg) SDL_GUIDToString(guid, guid_str, size); /* Check bytes before guid_str_buf */ - expected_prefix = fill_char | (fill_char << 8) | (fill_char << 16) | (fill_char << 24); + expected_prefix = fill_char | (fill_char << 8) | (fill_char << 16) | (((Uint32)fill_char) << 24); SDL_memcpy(&actual_prefix, guid_str_buf, 4); SDLTest_AssertCheck(expected_prefix == actual_prefix, "String buffer memory before output untouched, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32 ", at size=%d", expected_prefix, actual_prefix, size); From 483155bbf94b661b9054d1dba75b23ec9ed5626a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 11 Jan 2024 13:49:28 -0800 Subject: [PATCH 712/725] Fixed borderless window client area calculation --- src/video/windows/SDL_windowsevents.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index f9d1c0211fa3c..af5fbfbf204a0 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1424,8 +1424,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (!(window_flags & SDL_WINDOW_RESIZABLE)) { int w, h; NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS *)lParam; - w = data->window->windowed.w; - h = data->window->windowed.h; + w = data->window->floating.w; + h = data->window->floating.h; params->rgrc[0].right = params->rgrc[0].left + w; params->rgrc[0].bottom = params->rgrc[0].top + h; } From 312160935d3ff9da1cd6d307cd82b17dc06f47f4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 06:51:44 -0800 Subject: [PATCH 713/725] Removed deprecated use of __IPHONEOS__ (thanks @Dragon-Baroque!) --- src/video/SDL_video_capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_video_capture.c b/src/video/SDL_video_capture.c index ea43ff9cdafb5..01fbb49d5a298 100644 --- a/src/video/SDL_video_capture.c +++ b/src/video/SDL_video_capture.c @@ -861,7 +861,7 @@ SDL_QuitVideoCapture(void) /* See SDL_android_video_capture.c */ -#elif defined(__IPHONEOS__) || defined(__MACOS__) +#elif defined(__IOS__) || defined(__MACOS__) /* See SDL_video_capture_apple.m */ #else From 277fded7bac77417c94c1f58a33a0005ad02f5f1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 07:07:27 -0800 Subject: [PATCH 714/725] Refactor AdjustWindowRectEx() into WIN_AdjustWindowRectForHWND() Also include the window EXSTYLE to calls to AdjustWindowRectEx() --- src/video/windows/SDL_windowsevents.c | 32 +++------------ src/video/windows/SDL_windowswindow.c | 59 +++++++++++++++++++++------ src/video/windows/SDL_windowswindow.h | 3 +- 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index af5fbfbf204a0..8a963cb85ca51 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1041,27 +1041,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } if (!(SDL_GetWindowFlags(data->window) & SDL_WINDOW_BORDERLESS)) { - LONG style = GetWindowLong(hwnd, GWL_STYLE); - /* DJM - according to the docs for GetMenu(), the - return value is undefined if hwnd is a child window. - Apparently it's too difficult for MS to check - inside their function, so I have to do it here. - */ - BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); - UINT dpi; - - dpi = USER_DEFAULT_SCREEN_DPI; size.top = 0; size.left = 0; size.bottom = h; size.right = w; - - if (WIN_IsPerMonitorV2DPIAware(SDL_GetVideoDevice())) { - dpi = data->videodata->GetDpiForWindow(hwnd); - data->videodata->AdjustWindowRectExForDpi(&size, style, menu, 0, dpi); - } else { - AdjustWindowRectEx(&size, style, menu, 0); - } + WIN_AdjustWindowRectForHWND(hwnd, &size); w = size.right - size.left; h = size.bottom - size.top; #ifdef HIGHDPI_DEBUG @@ -1510,6 +1494,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) int query_client_w_win, query_client_h_win; const DWORD style = GetWindowLong(hwnd, GWL_STYLE); + const DWORD styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); const BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); #ifdef HIGHDPI_DEBUG @@ -1522,7 +1507,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) RECT rect = { 0 }; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, prevDPI); + data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, styleEx, prevDPI); } frame_w = -rect.left + rect.right; @@ -1539,7 +1524,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) rect.bottom = query_client_h_win; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, nextDPI); + data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, styleEx, nextDPI); } /* This is supposed to control the suggested rect param of WM_DPICHANGED */ @@ -1580,19 +1565,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { /* Calculate the new frame w/h such that the client area size is maintained. */ - const DWORD style = GetWindowLong(hwnd, GWL_STYLE); - const BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); - RECT rect = { 0 }; rect.right = data->window->w; rect.bottom = data->window->h; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - if (data->videodata->GetDpiForWindow && data->videodata->AdjustWindowRectExForDpi) { - data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, newDPI); - } else { - AdjustWindowRectEx(&rect, style, menu, 0); - } + WIN_AdjustWindowRectForHWND(hwnd, &rect); } w = rect.right - rect.left; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 38a9055a3f4f4..2a452d01b90e5 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -154,7 +154,7 @@ static DWORD GetWindowStyleEx(SDL_Window *window) * Returns arguments to pass to SetWindowPos - the window rect, including frame, in Windows coordinates. * Can be called before we have a HWND. */ -static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) +static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, DWORD styleEx, BOOL menu, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) { SDL_VideoData *videodata = SDL_GetVideoDevice() ? SDL_GetVideoDevice()->driverdata : NULL; RECT rect; @@ -162,17 +162,17 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m /* Client rect, in points */ switch (rect_type) { case SDL_WINDOWRECT_CURRENT: - SDL_RelativeToGlobalForWindow(window,window->x, window->y, x, y); + SDL_RelativeToGlobalForWindow(window, window->x, window->y, x, y); *width = window->w; *height = window->h; break; case SDL_WINDOWRECT_WINDOWED: - SDL_RelativeToGlobalForWindow(window,window->windowed.x, window->windowed.y, x, y); + SDL_RelativeToGlobalForWindow(window, window->windowed.x, window->windowed.y, x, y); *width = window->windowed.w; *height = window->windowed.h; break; case SDL_WINDOWRECT_FLOATING: - SDL_RelativeToGlobalForWindow(window,window->floating.x, window->floating.y, x, y); + SDL_RelativeToGlobalForWindow(window, window->floating.x, window->floating.y, x, y); *width = window->floating.w; *height = window->floating.h; break; @@ -202,12 +202,12 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m UINT frame_dpi; SDL_WindowData *data = window->driverdata; frame_dpi = (data && videodata->GetDpiForWindow) ? videodata->GetDpiForWindow(data->hwnd) : USER_DEFAULT_SCREEN_DPI; - if (videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, frame_dpi) == 0) { + if (videodata->AdjustWindowRectExForDpi(&rect, style, menu, styleEx, frame_dpi) == 0) { return WIN_SetError("AdjustWindowRectExForDpi()"); } } } else { - if (AdjustWindowRectEx(&rect, style, menu, 0) == 0) { + if (AdjustWindowRectEx(&rect, style, menu, styleEx) == 0) { return WIN_SetError("AdjustWindowRectEx()"); } } @@ -231,20 +231,54 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL m return 0; } -void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) +int WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type) { SDL_WindowData *data = window->driverdata; HWND hwnd = data->hwnd; - DWORD style; + DWORD style, styleEx; + BOOL menu; + + style = GetWindowLong(hwnd, GWL_STYLE); + styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); +#if defined(__XBOXONE__) || defined(__XBOXSERIES__) + menu = FALSE; +#else + menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); +#endif + return WIN_AdjustWindowRectWithStyle(window, style, styleEx, menu, x, y, width, height, rect_type); +} + +int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect) +{ + SDL_VideoDevice *videodevice = SDL_GetVideoDevice(); + SDL_VideoData *videodata = videodevice ? videodevice->driverdata : NULL; + DWORD style, styleEx; BOOL menu; style = GetWindowLong(hwnd, GWL_STYLE); + styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); #if defined(__XBOXONE__) || defined(__XBOXSERIES__) menu = FALSE; #else menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); #endif - WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, rect_type); + +#if defined(__XBOXONE__) || defined(__XBOXSERIES__) + AdjustWindowRectEx(&rect, style, menu, styleEx); +#else + if (WIN_IsPerMonitorV2DPIAware(videodevice)) { + /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of AdjustWindowRectEx. */ + UINT frame_dpi = videodata->GetDpiForWindow ? videodata->GetDpiForWindow(hwnd) : USER_DEFAULT_SCREEN_DPI; + if (!videodata->AdjustWindowRectExForDpi(lpRect, style, menu, styleEx, frame_dpi)) { + return WIN_SetError("AdjustWindowRectExForDpi()"); + } + } else { + if (!AdjustWindowRectEx(lpRect, style, menu, styleEx)) { + return WIN_SetError("AdjustWindowRectEx()"); + } + } +#endif + return 0; } int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type) @@ -603,7 +637,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI /* Figure out what the window area will be */ WIN_ConstrainPopup(window); - WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_WINDOWRECT_FLOATING); + WIN_AdjustWindowRectWithStyle(window, style, styleEx, FALSE, &x, &y, &w, &h, SDL_WINDOWRECT_FLOATING); hwnd = CreateWindowEx(styleEx, SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL, SDL_Instance, NULL); @@ -1073,7 +1107,7 @@ int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vide SDL_WindowData *data = window->driverdata; HWND hwnd = data->hwnd; MONITORINFO minfo; - DWORD style; + DWORD style, styleEx; HWND top; int x, y; int w, h; @@ -1108,6 +1142,7 @@ int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vide style = GetWindowLong(hwnd, GWL_STYLE); style &= ~STYLE_MASK; style |= GetWindowStyle(window); + styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); if (fullscreen) { x = minfo.rcMonitor.left; @@ -1136,7 +1171,7 @@ int WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vide } menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); - WIN_AdjustWindowRectWithStyle(window, style, menu, + WIN_AdjustWindowRectWithStyle(window, style, styleEx, menu, &x, &y, &w, &h, data->windowed_mode_was_maximized ? SDL_WINDOWRECT_WINDOWED : SDL_WINDOWRECT_FLOATING); diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 835ba622db60d..8f6476c862e62 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -119,7 +119,8 @@ extern void WIN_UpdateDarkModeForHWND(HWND hwnd); extern int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type); extern void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y); extern int WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); -extern void WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type); +extern int WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type); +extern int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect); /* Ends C function definitions when using C++ */ #ifdef __cplusplus From f8cce4ead45bb4cd1aad00292ba60873ad5d09bf Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Fri, 12 Jan 2024 18:56:10 +0300 Subject: [PATCH 715/725] SDL_windowsevents.c: fixed -Werror=unused-variable --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 8a963cb85ca51..bc67d39f3eea2 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1542,11 +1542,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_DPICHANGED: /* Windows 8.1+ */ { - const int newDPI = HIWORD(wParam); RECT *const suggestedRect = (RECT *)lParam; int w, h; #ifdef HIGHDPI_DEBUG + const int newDPI = HIWORD(wParam); SDL_Log("WM_DPICHANGED: to %d\tsuggested rect: (%d, %d), (%dx%d)\n", newDPI, suggestedRect->left, suggestedRect->top, suggestedRect->right - suggestedRect->left, suggestedRect->bottom - suggestedRect->top); #endif From e4ee1cade7d66439e363e156c517660b565cb228 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 09:32:49 -0800 Subject: [PATCH 716/725] Revert "SDL_windowsevents.c: fixed -Werror=unused-variable" This reverts commit f8cce4ead45bb4cd1aad00292ba60873ad5d09bf. --- src/video/windows/SDL_windowsevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index bc67d39f3eea2..8a963cb85ca51 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1542,11 +1542,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_DPICHANGED: /* Windows 8.1+ */ { + const int newDPI = HIWORD(wParam); RECT *const suggestedRect = (RECT *)lParam; int w, h; #ifdef HIGHDPI_DEBUG - const int newDPI = HIWORD(wParam); SDL_Log("WM_DPICHANGED: to %d\tsuggested rect: (%d, %d), (%dx%d)\n", newDPI, suggestedRect->left, suggestedRect->top, suggestedRect->right - suggestedRect->left, suggestedRect->bottom - suggestedRect->top); #endif From 7efeb3613150b8347cbec52e877313ce65589439 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 09:31:58 -0800 Subject: [PATCH 717/725] Pass the frame DPI to WIN_AdjustWindowRectForHWND() --- src/video/windows/SDL_windowsevents.c | 12 ++++-------- src/video/windows/SDL_windowswindow.c | 6 ++++-- src/video/windows/SDL_windowswindow.h | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 8a963cb85ca51..08b9e9dd6091f 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1045,7 +1045,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) size.left = 0; size.bottom = h; size.right = w; - WIN_AdjustWindowRectForHWND(hwnd, &size); + WIN_AdjustWindowRectForHWND(hwnd, &size, 0); w = size.right - size.left; h = size.bottom - size.top; #ifdef HIGHDPI_DEBUG @@ -1493,10 +1493,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) int frame_w, frame_h; int query_client_w_win, query_client_h_win; - const DWORD style = GetWindowLong(hwnd, GWL_STYLE); - const DWORD styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); - const BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); - #ifdef HIGHDPI_DEBUG SDL_Log("WM_GETDPISCALEDSIZE: current DPI: %d potential DPI: %d input size: (%dx%d)", prevDPI, nextDPI, sizeInOut->cx, sizeInOut->cy); @@ -1507,7 +1503,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) RECT rect = { 0 }; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, styleEx, prevDPI); + WIN_AdjustWindowRectForHWND(hwnd, &rect, prevDPI); } frame_w = -rect.left + rect.right; @@ -1524,7 +1520,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) rect.bottom = query_client_h_win; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, styleEx, nextDPI); + WIN_AdjustWindowRectForHWND(hwnd, &rect, nextDPI); } /* This is supposed to control the suggested rect param of WM_DPICHANGED */ @@ -1570,7 +1566,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) rect.bottom = data->window->h; if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - WIN_AdjustWindowRectForHWND(hwnd, &rect); + WIN_AdjustWindowRectForHWND(hwnd, &rect, newDPI); } w = rect.right - rect.left; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 2a452d01b90e5..fbb816e531c5c 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -248,7 +248,7 @@ int WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *he return WIN_AdjustWindowRectWithStyle(window, style, styleEx, menu, x, y, width, height, rect_type); } -int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect) +int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect, UINT frame_dpi) { SDL_VideoDevice *videodevice = SDL_GetVideoDevice(); SDL_VideoData *videodata = videodevice ? videodevice->driverdata : NULL; @@ -268,7 +268,9 @@ int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect) #else if (WIN_IsPerMonitorV2DPIAware(videodevice)) { /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of AdjustWindowRectEx. */ - UINT frame_dpi = videodata->GetDpiForWindow ? videodata->GetDpiForWindow(hwnd) : USER_DEFAULT_SCREEN_DPI; + if (!frame_dpi) { + frame_dpi = videodata->GetDpiForWindow ? videodata->GetDpiForWindow(hwnd) : USER_DEFAULT_SCREEN_DPI; + } if (!videodata->AdjustWindowRectExForDpi(lpRect, style, menu, styleEx, frame_dpi)) { return WIN_SetError("AdjustWindowRectExForDpi()"); } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 8f6476c862e62..2e826230809fd 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -120,7 +120,7 @@ extern int WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_Win extern void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y); extern int WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable); extern int WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_WindowRect rect_type); -extern int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect); +extern int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect, UINT frame_dpi); /* Ends C function definitions when using C++ */ #ifdef __cplusplus From 98be55894eb0db46f9cef689365719ed5f35ab3b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 09:38:28 -0800 Subject: [PATCH 718/725] Moved window state change handling from WM_WINDOWPOSCHANGING to WM_WINDOWPOSCHANGED Applications might override WM_WINDOWPOSCHANGING which would prevent us from getting the correct window state. This also fixes cases where the window doesn't get WM_SHOWWINDOW, as described in Raymond Chen's blog post: https://devblogs.microsoft.com/oldnewthing/20080115-00/?p=23813 --- src/video/windows/SDL_windowsevents.c | 119 ++++++++++++++------------ 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 08b9e9dd6091f..bfbf93dc0579c 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1088,91 +1088,96 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_WINDOWPOSCHANGING: { WINDOWPOS *windowpos = (WINDOWPOS*)lParam; + if (!IsIconic(hwnd) && + !IsZoomed(hwnd) && + (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) && + !(data->window->flags & SDL_WINDOW_FULLSCREEN)) { + /* Use the stored floating size if moving from a fixed-size to floating state. */ + int fx, fy, fw, fh; + + WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING); + windowpos->x = fx; + windowpos->y = fy; + windowpos->cx = fw; + windowpos->cy = fh; + windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE); + } + } break; - if (data->expected_resize) { - returnCode = 0; + case WM_WINDOWPOSCHANGED: + { + SDL_Window *win; + const SDL_DisplayID original_displayID = data->last_displayID; + const WINDOWPOS *windowpos = (WINDOWPOS *)lParam; + const SDL_bool moved = !(windowpos->flags & SWP_NOMOVE); + const SDL_bool resized = !(windowpos->flags & SWP_NOSIZE); + const SDL_bool iconic = IsIconic(hwnd); + const SDL_bool zoomed = IsZoomed(hwnd); + + if (windowpos->flags & SWP_SHOWWINDOW) { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_SHOWN, 0, 0); } - if (IsIconic(hwnd)) { + if (iconic) { SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - } else if (IsZoomed(hwnd)) { + } else if (zoomed) { if (data->window->flags & SDL_WINDOW_MINIMIZED) { /* If going from minimized to maximized, send the restored event first. */ SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); } SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } else { - SDL_bool was_fixed_size = !!(data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)); + } else if (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) { SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - - /* Send the stored floating size if moving from a fixed-size to floating state. */ - if (was_fixed_size && !(data->window->flags & SDL_WINDOW_FULLSCREEN)) { - int fx, fy, fw, fh; - - WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING); - windowpos->x = fx; - windowpos->y = fy; - windowpos->cx = fw; - windowpos->cy = fh; - windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE); - } } - } break; - case WM_WINDOWPOSCHANGED: - { - SDL_Window *win; - RECT rect; - int x, y; - int w, h; - const SDL_DisplayID original_displayID = data->last_displayID; + if (windowpos->flags & SWP_HIDEWINDOW) { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0); + } - if (data->initializing || data->in_border_change) { + if (!moved && !resized) { + /* Nothing left to handle */ break; } /* When the window is minimized it's resized to the dock icon size, ignore this */ - if (IsIconic(hwnd)) { + if (iconic) { break; } - if (!GetClientRect(hwnd, &rect) || WIN_IsRectEmpty(&rect)) { + if (data->initializing) { break; } - ClientToScreen(hwnd, (LPPOINT)&rect); - ClientToScreen(hwnd, (LPPOINT)&rect + 1); - - WIN_UpdateClipCursor(data->window); - - x = rect.left; - y = rect.top; - SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); + if (moved) { + RECT rect; + int x, y; - // 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)) { - ClientToScreen(hwnd, (LPPOINT)&rect); - ClientToScreen(hwnd, (LPPOINT)&rect + 1); + if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) { + ClientToScreen(hwnd, (LPPOINT)&rect); + ClientToScreen(hwnd, (LPPOINT)&rect + 1); - WIN_UpdateClipCursor(data->window); + x = rect.left; + y = rect.top; - x = rect.left; - y = rect.top; + SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); + } } - w = rect.right - rect.left; - h = rect.bottom - rect.top; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h); + if (resized) { + RECT rect; + int w, h; -#ifdef HIGHDPI_DEBUG - SDL_Log("WM_WINDOWPOSCHANGED: Windows client rect (pixels): (%d, %d) (%d x %d)\tSDL client rect (points): (%d, %d) (%d x %d) windows reported dpi %d", - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, - x, y, w, h, data->videodata->GetDpiForWindow ? data->videodata->GetDpiForWindow(data->hwnd) : 0); -#endif + /* 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)) { + w = rect.right; + h = rect.bottom; - /* Forces a WM_PAINT event */ - InvalidateRect(hwnd, NULL, FALSE); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h); + } + } + + WIN_UpdateClipCursor(data->window); /* Update the window display position */ data->last_displayID = SDL_GetDisplayForWindow(data->window); @@ -1189,6 +1194,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT); } } + + /* Forces a WM_PAINT event */ + InvalidateRect(hwnd, NULL, FALSE); + } break; case WM_ENTERSIZEMOVE: From f0b9c7f0f0122d8a8275b68da8d817708c9d4d7a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 Jan 2024 10:03:13 -0800 Subject: [PATCH 719/725] Let Windows track floating window state This fixes restoring window size and position after moving it to a tiled location (which isn't maximized) and then back. --- src/video/windows/SDL_windowsevents.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index bfbf93dc0579c..60453ba8fb7b9 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1087,21 +1087,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_WINDOWPOSCHANGING: { - WINDOWPOS *windowpos = (WINDOWPOS*)lParam; - if (!IsIconic(hwnd) && - !IsZoomed(hwnd) && - (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) && - !(data->window->flags & SDL_WINDOW_FULLSCREEN)) { - /* Use the stored floating size if moving from a fixed-size to floating state. */ - int fx, fy, fw, fh; - - WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING); - windowpos->x = fx; - windowpos->y = fy; - windowpos->cx = fw; - windowpos->cy = fh; - windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE); - } } break; case WM_WINDOWPOSCHANGED: From 4033a0a83b3a675c6b7803e36fb13114579d0b5b Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 12 Jan 2024 15:43:49 +0100 Subject: [PATCH 720/725] Prevent ASAN warning: like SDL_triangle.c:305:30: runtime error: left shift of negative value -672 (even if the value was correctly computed) --- src/render/software/SDL_triangle.c | 48 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index e62ff22e45b8b..602dc85bdce51 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -112,10 +112,23 @@ static int is_top_left(const SDL_Point *a, const SDL_Point *b, int is_clockwise) return 0; } +/* x = (y << FP_BITS) */ +/* prevent runtime error: left shift of negative value */ +#define PRECOMP(x, y) \ + val = y; \ + if (val >= 0) { \ + x = val << FP_BITS; \ + } else { \ + val *= -1; \ + x = val << FP_BITS; \ + x *= -1; \ + } + void trianglepoint_2_fixedpoint(SDL_Point *a) { - a->x <<= FP_BITS; - a->y <<= FP_BITS; + int val; + PRECOMP(a->x, a->x); + PRECOMP(a->y, a->y); } /* bounding rect of three points (in fixed point) */ @@ -297,12 +310,15 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin is_clockwise = area > 0; area = SDL_abs(area); - d2d1_y = (d1->y - d2->y) << FP_BITS; - d0d2_y = (d2->y - d0->y) << FP_BITS; - d1d0_y = (d0->y - d1->y) << FP_BITS; - d1d2_x = (d2->x - d1->x) << FP_BITS; - d2d0_x = (d0->x - d2->x) << FP_BITS; - d0d1_x = (d1->x - d0->x) << FP_BITS; + { + int val; + PRECOMP(d2d1_y, d1->y - d2->y) + PRECOMP(d0d2_y, d2->y - d0->y) + PRECOMP(d1d0_y, d0->y - d1->y) + PRECOMP(d1d2_x, d2->x - d1->x) + PRECOMP(d2d0_x, d0->x - d2->x) + PRECOMP(d0d1_x, d1->x - d0->x) + } /* Starting point for rendering, at the middle of a pixel */ { @@ -564,13 +580,15 @@ int SDL_SW_BlitTriangle( is_clockwise = area > 0; area = SDL_abs(area); - d2d1_y = (d1->y - d2->y) << FP_BITS; - d0d2_y = (d2->y - d0->y) << FP_BITS; - d1d0_y = (d0->y - d1->y) << FP_BITS; - - d1d2_x = (d2->x - d1->x) << FP_BITS; - d2d0_x = (d0->x - d2->x) << FP_BITS; - d0d1_x = (d1->x - d0->x) << FP_BITS; + { + int val; + PRECOMP(d2d1_y, d1->y - d2->y) + PRECOMP(d0d2_y, d2->y - d0->y) + PRECOMP(d1d0_y, d0->y - d1->y) + PRECOMP(d1d2_x, d2->x - d1->x) + PRECOMP(d2d0_x, d0->x - d2->x) + PRECOMP(d0d1_x, d1->x - d0->x) + } s2s0_x = s0->x - s2->x; s2s1_x = s1->x - s2->x; From 101f903bb1b6c0163d1ccf5b02b9ebfc3757b140 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Fri, 12 Jan 2024 16:09:11 +0100 Subject: [PATCH 721/725] testgeometry: allow to use arrows to move the triangle --- test/testgeometry.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/testgeometry.c b/test/testgeometry.c index 16d44ca576fad..9abefab431878 100644 --- a/test/testgeometry.c +++ b/test/testgeometry.c @@ -29,6 +29,8 @@ static SDL_Texture **sprites; static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; static float angle = 0.0f; static int sprite_w, sprite_h; +static int translate_cx = 0; +static int translate_cy = 0; static int done; @@ -92,6 +94,18 @@ static void loop(void) angle += yrel; } } + } else if (event.type == SDL_EVENT_KEY_DOWN) { + if (event.key.keysym.sym == SDLK_LEFT) { + translate_cx -= 1; + } else if (event.key.keysym.sym == SDLK_RIGHT) { + translate_cx += 1; + } else if (event.key.keysym.sym == SDLK_UP) { + translate_cy -= 1; + } else if (event.key.keysym.sym == SDLK_DOWN) { + translate_cy += 1; + } else { + SDLTest_CommonEvent(state, &event, &done); + } } else { SDLTest_CommonEvent(state, &event, &done); } @@ -119,6 +133,9 @@ static void loop(void) cy = viewport.y + viewport.h / 2; d = (viewport.w + viewport.h) / 5.f; + cx += translate_cx; + cy += translate_cy; + a = (angle * 3.1415f) / 180.0f; verts[0].position.x = cx + d * SDL_cosf(a); verts[0].position.y = cy + d * SDL_sinf(a); From d4a97487407a456bf39325ab6b6c4b0b6e041099 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 13 Jan 2024 14:41:02 -0500 Subject: [PATCH 722/725] win32: Fix test failures WM_WINDOWPOSCHANGING needs to return 0 when a resize was initiated programmatically Checking the SWP_NOMOVE and SWP_NOSIZE flags in the WINDOWPOS struct when handling WM_WINDOWPOSCHANGED to avoid sending redundant resize and move events is unreliable, as they can be set even when the window has moved or changed size, such as when leaving fullscreen, or programmatically resizing a window without STYLE_RESIZABLE set. Fixes the video_getSetWindowSize and video_setWindowCenteredOnDisplay tests. --- src/video/windows/SDL_windowsevents.c | 47 ++++++++++----------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 60453ba8fb7b9..98298afda17b5 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1087,6 +1087,9 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_WINDOWPOSCHANGING: { + if (data->expected_resize) { + returnCode = 0; + } } break; case WM_WINDOWPOSCHANGED: @@ -1094,10 +1097,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_Window *win; const SDL_DisplayID original_displayID = data->last_displayID; const WINDOWPOS *windowpos = (WINDOWPOS *)lParam; - const SDL_bool moved = !(windowpos->flags & SWP_NOMOVE); - const SDL_bool resized = !(windowpos->flags & SWP_NOSIZE); const SDL_bool iconic = IsIconic(hwnd); const SDL_bool zoomed = IsZoomed(hwnd); + RECT rect; + int x, y; + int w, h; if (windowpos->flags & SWP_SHOWWINDOW) { SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_SHOWN, 0, 0); @@ -1119,11 +1123,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0); } - if (!moved && !resized) { - /* Nothing left to handle */ - break; - } - /* When the window is minimized it's resized to the dock icon size, ignore this */ if (iconic) { break; @@ -1133,33 +1132,23 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; } - if (moved) { - RECT rect; - int x, y; - - if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) { - ClientToScreen(hwnd, (LPPOINT)&rect); - ClientToScreen(hwnd, (LPPOINT)&rect + 1); + if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) { + ClientToScreen(hwnd, (LPPOINT) &rect); + ClientToScreen(hwnd, (LPPOINT) &rect + 1); - x = rect.left; - y = rect.top; + x = rect.left; + y = rect.top; - SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); - } + SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); } - if (resized) { - RECT rect; - int w, h; - - /* 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)) { - w = rect.right; - h = rect.bottom; + /* 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)) { + w = rect.right; + h = rect.bottom; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h); - } + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h); } WIN_UpdateClipCursor(data->window); From 649556befa156201116a4f25089597463d0efd44 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 13 Jan 2024 15:02:28 -0500 Subject: [PATCH 723/725] win32: Let windows manage the floating state unless explicitly overridden Windows doesn't inform applications if the window is in the docked/tiled state, so let windows manage the window size when restoring from a fixed-size state, unless the application explicitly requested a new size/position. Fixes the video_getSetWindowState test. --- src/video/windows/SDL_windowsevents.c | 19 +++++++++++++++++++ src/video/windows/SDL_windowswindow.c | 4 ++++ src/video/windows/SDL_windowswindow.h | 1 + 3 files changed, 24 insertions(+) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 98298afda17b5..777291cdd1273 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1090,6 +1090,25 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if (data->expected_resize) { returnCode = 0; } + + if (data->floating_rect_pending && + !IsIconic(hwnd) && + !IsZoomed(hwnd) && + (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) && + !(data->window->flags & SDL_WINDOW_FULLSCREEN)) { + /* If a new floating size is pending, apply it if moving from a fixed-size to floating state. */ + WINDOWPOS *windowpos = (WINDOWPOS*)lParam; + int fx, fy, fw, fh; + + WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING); + windowpos->x = fx; + windowpos->y = fy; + windowpos->cx = fw; + windowpos->cy = fh; + windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE); + + data->floating_rect_pending = SDL_FALSE; + } } break; case WM_WINDOWPOSCHANGED: diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index fbb816e531c5c..896eb81266fd6 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -829,6 +829,8 @@ int WIN_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) return WIN_SetWindowPositionInternal(window, window->driverdata->copybits_flag | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE, SDL_WINDOWRECT_FLOATING); + } else { + window->driverdata->floating_rect_pending = SDL_TRUE; } } else { return SDL_UpdateFullscreenMode(window, SDL_TRUE, SDL_TRUE); @@ -841,6 +843,8 @@ void WIN_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) { if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) { WIN_SetWindowPositionInternal(window, window->driverdata->copybits_flag | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE, SDL_WINDOWRECT_FLOATING); + } else { + window->driverdata->floating_rect_pending = SDL_TRUE; } } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 2e826230809fd..9de65c3cc073f 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -59,6 +59,7 @@ struct SDL_WindowData SDL_bool expected_resize; SDL_bool in_border_change; SDL_bool in_title_click; + SDL_bool floating_rect_pending; Uint8 focus_click_pending; SDL_bool skip_update_clipcursor; Uint64 last_updated_clipcursor; From 3a4ac15a27cff632c7e46be6cfd05ee6fdbd85ff Mon Sep 17 00:00:00 2001 From: chalonverse Date: Sun, 14 Jan 2024 20:31:41 -0800 Subject: [PATCH 724/725] Make Xbox GDK code public (and fix some GDK code rot) (#8844) --- .gitignore | 1 + VisualC-GDK/SDL.sln | 3 + VisualC-GDK/SDL/SDL.vcxproj | 44 +- VisualC-GDK/SDL/SDL.vcxproj.filters | 1840 ++++------------- VisualC-GDK/clean.sh | 1 + .../shaders/D3D12_PixelShader_Colors.hlsl | 19 + .../shaders/D3D12_PixelShader_NV12_BT601.hlsl | 43 + .../shaders/D3D12_PixelShader_NV12_BT709.hlsl | 43 + .../shaders/D3D12_PixelShader_NV12_JPEG.hlsl | 43 + .../shaders/D3D12_PixelShader_NV21_BT601.hlsl | 43 + .../shaders/D3D12_PixelShader_NV21_BT709.hlsl | 43 + .../shaders/D3D12_PixelShader_NV21_JPEG.hlsl | 43 + .../shaders/D3D12_PixelShader_Textures.hlsl | 24 + .../shaders/D3D12_PixelShader_YUV_BT601.hlsl | 46 + .../shaders/D3D12_PixelShader_YUV_BT709.hlsl | 46 + .../shaders/D3D12_PixelShader_YUV_JPEG.hlsl | 46 + VisualC-GDK/shaders/D3D12_VertexShader.hlsl | 95 + VisualC-GDK/shaders/buildshaders.bat | 35 + .../testcontroller/testcontroller.vcxproj | 14 +- .../testcontroller.vcxproj.filters | 8 +- VisualC-GDK/tests/testgdk/src/testgdk.cpp | 71 +- VisualC-GDK/tests/testgdk/testgdk.vcxproj | 6 +- .../tests/testgdk/testgdk.vcxproj.filters | 6 +- .../tests/testsprite/testsprite.vcxproj | 6 +- .../testsprite/testsprite.vcxproj.filters | 6 +- docs/README-gdk.md | 29 +- src/core/SDL_core_unsupported.c | 9 + src/filesystem/gdk/SDL_sysfilesystem.cpp | 8 +- src/render/direct3d12/SDL_render_d3d12.c | 2 +- .../direct3d12/SDL_render_d3d12_xbox.cpp | 153 +- src/render/direct3d12/SDL_render_d3d12_xbox.h | 29 +- .../direct3d12/SDL_shaders_d3d12_xboxone.cpp | 123 +- .../SDL_shaders_d3d12_xboxseries.cpp | 123 +- src/video/SDL_video_unsupported.c | 10 +- src/video/windows/SDL_windowsevents.c | 5 +- src/video/windows/SDL_windowswindow.c | 8 +- src/video/windows/SDL_windowswindow.h | 2 + 37 files changed, 1550 insertions(+), 1526 deletions(-) create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl create mode 100644 VisualC-GDK/shaders/D3D12_VertexShader.hlsl create mode 100644 VisualC-GDK/shaders/buildshaders.bat diff --git a/.gitignore b/.gitignore index e0d5ef3a8a272..9e577f4984231 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ VisualC/tests/testscale/sample.bmp VisualC/tests/testsprite/icon.bmp VisualC/tests/testyuv/testyuv.bmp VisualC-GDK/**/Layout +VisualC-GDK/shaders/*.h # for Android android-project/local.properties diff --git a/VisualC-GDK/SDL.sln b/VisualC-GDK/SDL.sln index 2cdfa0bd84765..14289c2878d35 100644 --- a/VisualC-GDK/SDL.sln +++ b/VisualC-GDK/SDL.sln @@ -11,6 +11,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3_test", "SDL_test\SDL_test.vcxproj", "{DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcontroller", "tests\testcontroller\testcontroller.vcxproj", "{55812185-D13C-4022-9C81-32E0F4A08305}" + ProjectSection(ProjectDependencies) = postProject + {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A} = {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgdk", "tests\testgdk\testgdk.vcxproj", "{1C9A3F71-35A5-4C56-B292-F4375B3C3649}" EndProject diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index b7b5a72c02ff8..c7fa0a28db57a 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -130,7 +130,7 @@ OldStyle OnlyExplicitInline true - Use + NotUsing SDL_internal.h @@ -170,6 +170,12 @@ Windows true + + $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) + + + Building shader blobs (Xbox Series) + @@ -198,6 +204,12 @@ Windows true + + $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one + + + Building shader blobs (Xbox One) + @@ -215,7 +227,7 @@ ProgramDatabase OnlyExplicitInline true - Use + NotUsing SDL_internal.h @@ -258,6 +270,12 @@ true true + + $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) + + + Building shader blobs (Xbox Series) + @@ -287,6 +305,12 @@ true true + + $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one + + + Building shader blobs (Xbox One) + @@ -457,6 +481,12 @@ Create $(IntDir)$(TargetName)_cpp.pch + + true + true + true + true + $(IntDir)$(TargetName)_cpp.pch $(IntDir)$(TargetName)_cpp.pch @@ -589,7 +619,10 @@ - + + true + true + @@ -733,7 +766,7 @@ - + NotUsing @@ -776,6 +809,7 @@ + @@ -800,4 +834,4 @@ - + \ No newline at end of file diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index e9f4d52c5064b..4692d46846edc 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -1,1434 +1,436 @@  - - {395b3af0-33d0-411b-b153-de1676bf1ef8} - - - {5a3e3167-75be-414f-8947-a5306df372b2} - - - {546d9ed1-988e-49d3-b1a5-e5b3d19de6c1} - - - {a56247ff-5108-4960-ba6a-6814fd1554ec} - - - {8880dfad-2a06-4e84-ab6e-6583641ad2d1} - - - {2b996a7f-f3e9-4300-a97f-2c907bcd89a9} - - - {5713d682-2bc7-4da4-bcf0-262a98f142eb} - - - {5e27e19f-b3f8-4e2d-b323-b00b2040ec86} - - - {a3ab9cff-8495-4a5c-8af6-27e43199a712} - - - {377061e4-3856-4f05-b916-0d3b360df0f6} - - - {226a6643-1c65-4c7f-92aa-861313d974bb} - - - {ef859522-a7fe-4a00-a511-d6a9896adf5b} - - - {01fd2642-4493-4316-b548-fb829f4c9125} - - - {cce7558f-590a-4f0a-ac0d-e579f76e588e} - - - {7a53c9e4-d4bd-40ed-9265-1625df685121} - - - {4c7a051c-ce7c-426c-bf8c-9187827f9052} - - - {97e2f79f-311b-42ea-81b2-e801649fdd93} - - - {baf97c8c-7e90-41e5-bff8-14051b8d3956} - - - {45e50d3a-56c9-4352-b811-0c60c49a2431} - - - {9d86e0ef-d6f6-4db2-bfc5-b3529406fa8d} - - - {b35fa13c-6ed2-4680-8c56-c7d71b76ceab} - - - {61b61b31-9e26-4171-a3bb-b969f1889726} - - - {f63aa216-6ee7-4143-90d3-32be3787f276} - - - {90bee923-89df-417f-a6c3-3e260a7dd54d} - - - {4c8ad943-c2fb-4014-9ca3-041e0ad08426} - - - {3d68ae70-a9ff-46cf-be69-069f0b02aca0} - - - {ebc2fca3-3c26-45e3-815e-3e0581d5e226} - - - {47c445a2-7014-4e15-9660-7c89a27dddcf} - - - {d008487d-6ed0-4251-848b-79a68e3c1459} - - - {c9e8273e-13ae-47dc-bef8-8ad8e64c9a3d} - - - {0b8e136d-56ae-47e7-9981-e863a57ac616} - - - {bf3febd3-9328-43e8-b196-0fd3be8177dd} - - - {1a62dc68-52d2-4c07-9d81-d94dfe1d0d12} - - - {e9f01b22-34b3-4380-ade6-0e96c74e9c90} - - - {f674f22f-7841-4f3a-974e-c36b2d4823fc} - - - {d7ad92de-4e55-4202-9b2b-1bd9a35fe4dc} - - - {8311d79d-9ad5-4369-99fe-b2fb2659d402} - - - {6c4dfb80-fdf9-497c-a6ff-3cd8f22efde9} - - - {4810e35c-33cb-4da2-bfaf-452da20d3c9a} - - - {2cf93f1d-81fd-4bdc-998c-5e2fa43988bc} - - - {5752b7ab-2344-4f38-95ab-b5d3bc150315} - - - {7a0eae3d-f113-4914-b926-6816d1929250} - - - {ee602cbf-96a2-4b0b-92a9-51d38a727411} - - - {a812185b-9060-4a1c-8431-be4f66894626} - - - {31c16cdf-adc4-4950-8293-28ba530f3882} - - - {add61b53-8144-47d6-bd67-3420a87c4905} - - - {e7cdcf36-b462-49c7-98b7-07ea7b3687f4} - - - {82588eef-dcaa-4f69-b2a9-e675940ce54c} - - - {560239c3-8fa1-4d23-a81a-b8408b2f7d3f} - - - {81711059-7575-4ece-9e68-333b63e992c4} - - - {1e44970f-7535-4bfb-b8a5-ea0cea0349e0} - - - {1dd91224-1176-492b-a2cb-e26153394db0} - - - {e3ecfe50-cf22-41d3-8983-2fead5164b47} - - - {5521d22f-1e52-47a6-8c52-06a3b6bdefd7} - - - {4755f3a6-49ac-46d6-86be-21f5c21f2197} - - - {f48c2b17-1bee-4fec-a7c8-24cf619abe08} - - - {3ab60a46-e18e-450a-a916-328fb8547e59} - - - {3ad16a8a-0ed8-439c-a771-383af2e2867f} - - - {00002ddb6c5ea921181bf32d50e40000} - - - {00000a808f8ba6b489985f82a4e80000} - - - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - API Headers - - - main - - - - - - API Headers - - - API Headers - - - API Headers - - - audio - - - audio - - - audio - - - audio - - - audio - - - audio - - - core\windows - - - core\windows - - - core\windows - - - core\windows - - - core\windows - - - dynapi - - - dynapi - - - dynapi - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - haptic - - - haptic - - - joystick - - - joystick - - - joystick - - - joystick - - - joystick - - - joystick - - - joystick - - - libm - - - libm - - - hidapi\hidapi - - - locale - - - misc - - - audio\directsound - - - audio\disk - - - audio\dummy - - - audio\wasapi - - - haptic\windows - - - haptic\windows - - - haptic\windows - - - joystick\hidapi - - - joystick\hidapi - - - joystick\windows - - - joystick\windows - - - joystick\windows - - - joystick\windows - - - joystick\virtual - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video\dummy - - - video\dummy - - - video\dummy - - - video\yuv2rgb - - - video\yuv2rgb - - - video\yuv2rgb - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - timer - - - thread - - - thread - - - thread\windows - - - thread\windows - - - thread\generic - - - sensor - - - sensor - - - sensor\dummy - - - sensor\windows - - - render - - - render - - - render - - - render\direct3d - - - render\direct3d11 - - - render\opengl - - - render\opengl - - - render\opengles2 - - - render\opengles2 - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - power - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - video\khronos\vulkan - - - - - - - - render\direct3d12 - - - - core\gdk - - - render\direct3d12 - - - video\gdk - - - thread\generic - - - + + + + + + + + + + + + + + + + + + + + + + - - main\generic - - - main - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - audio - - - audio - - - audio - - - audio - - - audio - - - audio - - - audio - - - audio - - - atomic - - - atomic - - - core - - - core - - - core\windows - - - core\windows - - - core\windows - - - core\windows - - - cpuinfo - - - dynapi - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - events - - - file - - - filesystem\gdk - - - haptic - - - hidapi - - - joystick - - - joystick - - - joystick - - - joystick - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - libm - - - loadso\windows - - - misc - - - misc\windows - - - locale\windows - - - locale - - - audio\directsound - - - audio\disk - - - audio\dummy - - - audio\wasapi - - - audio\wasapi - - - haptic\windows - - - haptic\windows - - - haptic\windows - - - haptic\dummy - - - joystick\dummy - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\hidapi - - - joystick\windows - - - joystick\windows - - - joystick\windows - - - joystick\windows - - - joystick\windows - - - joystick\virtual - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video - - - video\dummy - - - video\dummy - - - video\dummy - - - video\yuv2rgb - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - video\windows - - - timer - - - timer\windows - - - thread - - - thread\windows - - - thread\windows - - - thread\windows - - - thread\windows - - - thread\windows - - - thread\generic - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - stdlib - - - sensor - - - sensor\dummy - - - sensor\windows - - - render - - - render - - - render - - - render - - - render\direct3d - - - render\direct3d - - - render\direct3d11 - - - render\direct3d11 - - - render\opengl - - - render\opengl - - - render\opengles2 - - - render\opengles2 - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - render\software - - - power - - - - power\windows - - - render\direct3d12 - - - render\direct3d12 - - - stdlib - - - stdlib - - - core\gdk - - - render\direct3d12 - - - render\direct3d12 - - - render\direct3d12 - - - core\windows - - - core\windows - - - video\gdk - - - thread\windows - - - thread\generic - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/VisualC-GDK/clean.sh b/VisualC-GDK/clean.sh index a026b71a30ef3..235b79c49431c 100755 --- a/VisualC-GDK/clean.sh +++ b/VisualC-GDK/clean.sh @@ -4,3 +4,4 @@ find . -type f \( -name '*.bmp' -o -name '*.wav' -o -name '*.dat' \) -print -del find . -depth -type d \( -name Gaming.Desktop.x64 \) -exec rm -rv {} \; find . -depth -type d \( -name Gaming.Xbox.Scarlett.x64 \) -exec rm -rv {} \; find . -depth -type d \( -name Gaming.Xbox.XboxOne.x64 \) -exec rm -rv {} \; +rm shaders/*.h diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl new file mode 100644 index 0000000000000..47eff4cc2444e --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl @@ -0,0 +1,19 @@ +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define ColorRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + "DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0)" + +[RootSignature(ColorRS)] +float4 main(PixelShaderInput input) : SV_TARGET0 +{ + return input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl new file mode 100644 index 0000000000000..cffbc2261822c --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; + const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; + const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl new file mode 100644 index 0000000000000..81d409c94eb2c --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; + const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; + const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl new file mode 100644 index 0000000000000..494bce5192d3b --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {0.0, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; + const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; + const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl new file mode 100644 index 0000000000000..794c763728af1 --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; + const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; + const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl new file mode 100644 index 0000000000000..f5b9522c0f8c5 --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; + const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; + const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl new file mode 100644 index 0000000000000..1b467b480369e --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl @@ -0,0 +1,43 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureUV : register(t1); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(NVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {0.0, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; + const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; + const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl new file mode 100644 index 0000000000000..0dcdf89c69bab --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl @@ -0,0 +1,24 @@ +Texture2D theTexture : register(t0); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define TextureRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(TextureRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + return theTexture.Sample(theSampler, input.tex) * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl new file mode 100644 index 0000000000000..09e58943a7f8e --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl @@ -0,0 +1,46 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureU : register(t1); +Texture2D theTextureV : register(t2); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define YUVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(YUVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; + const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; + const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.y = theTextureU.Sample(theSampler, input.tex).r; + yuv.z = theTextureV.Sample(theSampler, input.tex).r; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl new file mode 100644 index 0000000000000..f5aa0cd7e4abb --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl @@ -0,0 +1,46 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureU : register(t1); +Texture2D theTextureV : register(t2); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define YUVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(YUVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; + const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; + const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.y = theTextureU.Sample(theSampler, input.tex).r; + yuv.z = theTextureV.Sample(theSampler, input.tex).r; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl new file mode 100644 index 0000000000000..84d09b8bff031 --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl @@ -0,0 +1,46 @@ +Texture2D theTextureY : register(t0); +Texture2D theTextureU : register(t1); +Texture2D theTextureV : register(t2); +SamplerState theSampler : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define YUVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(YUVRS)] +float4 main(PixelShaderInput input) : SV_TARGET +{ + const float3 offset = {0.0, -0.501960814, -0.501960814}; + const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; + const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; + const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; + + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.y = theTextureU.Sample(theSampler, input.tex).r; + yuv.z = theTextureV.Sample(theSampler, input.tex).r; + + yuv += offset; + Output.r = dot(yuv, Rcoeff); + Output.g = dot(yuv, Gcoeff); + Output.b = dot(yuv, Bcoeff); + Output.a = 1.0f; + + return Output * input.color; +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_VertexShader.hlsl b/VisualC-GDK/shaders/D3D12_VertexShader.hlsl new file mode 100644 index 0000000000000..e10b488925ef2 --- /dev/null +++ b/VisualC-GDK/shaders/D3D12_VertexShader.hlsl @@ -0,0 +1,95 @@ +#pragma pack_matrix( row_major ) + +struct VertexShaderConstants +{ + matrix model; + matrix projectionAndView; +}; +ConstantBuffer Constants : register(b0); + +struct VertexShaderInput +{ + float3 pos : POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +struct VertexShaderOutput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +#define ColorRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + "DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0)" + +#define TextureRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +#define YUVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +#define NVRS \ + "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "RootConstants(num32BitConstants=32, b0),"\ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" + +[RootSignature(ColorRS)] +VertexShaderOutput mainColor(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Transform the vertex position into projected space. + pos = mul(pos, Constants.model); + pos = mul(pos, Constants.projectionAndView); + output.pos = pos; + + // Pass through texture coordinates and color values without transformation + output.tex = input.tex; + output.color = input.color; + + return output; +} + +[RootSignature(TextureRS)] +VertexShaderOutput mainTexture(VertexShaderInput input) +{ + return mainColor(input); +} + +[RootSignature(YUVRS)] +VertexShaderOutput mainYUV(VertexShaderInput input) +{ + return mainColor(input); +} + +[RootSignature(NVRS)] +VertexShaderOutput mainNV(VertexShaderInput input) +{ + return mainColor(input); +} \ No newline at end of file diff --git a/VisualC-GDK/shaders/buildshaders.bat b/VisualC-GDK/shaders/buildshaders.bat new file mode 100644 index 0000000000000..4447b5e2f8267 --- /dev/null +++ b/VisualC-GDK/shaders/buildshaders.bat @@ -0,0 +1,35 @@ +if %2.==one. goto setxboxone +rem Xbox Series compile +set XBOXDXC="%GameDKLatest%\GXDK\bin\Scarlett\DXC.exe" +set SUFFIX=_Series.h +goto startbuild + +:setxboxone +set XBOXDXC="%GameDKLatest%\GXDK\bin\XboxOne\DXC.exe" +set SUFFIX=_One.h + +:startbuild +echo Building with %XBOXDXC% +cd "%1\shaders" +rem Root Signatures +%XBOXDXC% -E ColorRS -T rootsig_1_1 -rootsig-define ColorRS -Fh D3D12_RootSig_Color%SUFFIX% -Vn D3D12_RootSig_Color D3D12_VertexShader.hlsl +%XBOXDXC% -E TextureRS -T rootsig_1_1 -rootsig-define TextureRS -Fh D3D12_RootSig_Texture%SUFFIX% -Vn D3D12_RootSig_Texture D3D12_VertexShader.hlsl +%XBOXDXC% -E YUVRS -T rootsig_1_1 -rootsig-define YUVRS -Fh D3D12_RootSig_YUV%SUFFIX% -Vn D3D12_RootSig_YUV D3D12_VertexShader.hlsl +%XBOXDXC% -E NVRS -T rootsig_1_1 -rootsig-define NVRS -Fh D3D12_RootSig_NV%SUFFIX% -Vn D3D12_RootSig_NV D3D12_VertexShader.hlsl +rem Vertex Shaders +%XBOXDXC% -E mainColor -T vs_6_0 -Fh D3D12_VertexShader_Color%SUFFIX% -Vn D3D12_VertexShader_Color D3D12_VertexShader.hlsl +%XBOXDXC% -E mainTexture -T vs_6_0 -Fh D3D12_VertexShader_Texture%SUFFIX% -Vn D3D12_VertexShader_Texture D3D12_VertexShader.hlsl +%XBOXDXC% -E mainNV -T vs_6_0 -Fh D3D12_VertexShader_NV%SUFFIX% -Vn D3D12_VertexShader_NV D3D12_VertexShader.hlsl +%XBOXDXC% -E mainYUV -T vs_6_0 -Fh D3D12_VertexShader_YUV%SUFFIX% -Vn D3D12_VertexShader_YUV D3D12_VertexShader.hlsl +rem Pixel Shaders +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Colors%SUFFIX% -Vn D3D12_PixelShader_Colors D3D12_PixelShader_Colors.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT601%SUFFIX% -Vn D3D12_PixelShader_NV12_BT601 D3D12_PixelShader_NV12_BT601.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT709%SUFFIX% -Vn D3D12_PixelShader_NV12_BT709 D3D12_PixelShader_NV12_BT709.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV12_JPEG D3D12_PixelShader_NV12_JPEG.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT601%SUFFIX% -Vn D3D12_PixelShader_NV21_BT601 D3D12_PixelShader_NV21_BT601.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT709%SUFFIX% -Vn D3D12_PixelShader_NV21_BT709 D3D12_PixelShader_NV21_BT709.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV21_JPEG D3D12_PixelShader_NV21_JPEG.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Textures%SUFFIX% -Vn D3D12_PixelShader_Textures D3D12_PixelShader_Textures.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT601%SUFFIX% -Vn D3D12_PixelShader_YUV_BT601 D3D12_PixelShader_YUV_BT601.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT709%SUFFIX% -Vn D3D12_PixelShader_YUV_BT709 D3D12_PixelShader_YUV_BT709.hlsl +%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_JPEG%SUFFIX% -Vn D3D12_PixelShader_YUV_JPEG D3D12_PixelShader_YUV_JPEG.hlsl \ No newline at end of file diff --git a/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj b/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj index 3f0156166eff6..5680fe311add4 100644 --- a/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj +++ b/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj @@ -139,7 +139,7 @@ Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -211,7 +211,7 @@ true Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -273,6 +273,12 @@ false true + + {da956fd3-e143-46f2-9fe5-c77bebc56b1a} + false + false + true + @@ -298,7 +304,7 @@ - + Document true true @@ -330,4 +336,4 @@ - + \ No newline at end of file diff --git a/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj.filters b/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj.filters index e4e2413ef87d0..90aec1b6a1940 100644 --- a/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj.filters +++ b/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj.filters @@ -18,9 +18,6 @@ logos - - wingdk - wingdk @@ -34,6 +31,9 @@ logos + + wingdk + @@ -49,4 +49,4 @@ {e704dcb9-c83c-4c94-a139-b0f3e3f428f2} - + \ No newline at end of file diff --git a/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/VisualC-GDK/tests/testgdk/src/testgdk.cpp index f65fd4b964557..bc4895bdce441 100644 --- a/VisualC-GDK/tests/testgdk/src/testgdk.cpp +++ b/VisualC-GDK/tests/testgdk/src/testgdk.cpp @@ -53,23 +53,14 @@ static struct int soundpos; /* Current play position */ } wave; -static SDL_AudioDeviceID device; - -static void -close_audio() -{ - if (device != 0) { - SDL_CloseAudioDevice(device); - device = 0; - } -} +static SDL_AudioStream *stream; /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ static void quit(int rc) { SDL_free(sprites); - close_audio(); + SDL_DestroyAudioStream(stream); SDL_free(wave.sound); SDLTest_CommonQuit(state); /* If rc is 0, just let main return normally rather than calling exit. @@ -80,49 +71,13 @@ quit(int rc) } } -static void -open_audio() +static int fillerup(void) { - /* Initialize fillerup() variables */ - device = SDL_OpenAudioDevice(NULL, SDL_FALSE, &wave.spec, NULL, 0); - if (!device) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError()); - SDL_free(wave.sound); - quit(2); + const int minimum = (wave.soundlen / SDL_AUDIO_FRAMESIZE(wave.spec)) / 2; + if (SDL_GetAudioStreamQueued(stream) < minimum) { + SDL_PutAudioStreamData(stream, wave.sound, wave.soundlen); } - - /* Let the audio run */ - SDL_PlayAudioDevice(device); -} - -static void -reopen_audio() -{ - close_audio(); - open_audio(); -} - -void SDLCALL -fillerup(void *unused, Uint8 *stream, int len) -{ - Uint8 *waveptr; - int waveleft; - - /* Set up the pointers */ - waveptr = wave.sound + wave.soundpos; - waveleft = wave.soundlen - wave.soundpos; - - /* Go! */ - while (waveleft <= len) { - SDL_memcpy(stream, waveptr, waveleft); - stream += waveleft; - len -= waveleft; - waveptr = wave.sound; - waveleft = wave.soundlen; - wave.soundpos = 0; - } - SDL_memcpy(stream, waveptr, len); - wave.soundpos += len; + return 0; } void @@ -371,6 +326,7 @@ loop() } DrawSprites(state->renderers[i], sprites[i]); } + fillerup(); } int @@ -469,13 +425,11 @@ main(int argc, char *argv[]) } /* Load the wave file into memory */ - if (SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen) == NULL) { + if (SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen) == -1) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", soundname, SDL_GetError()); quit(1); } - wave.spec.callback = fillerup; - /* Show the list of available drivers */ SDL_Log("Available audio drivers:"); for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { @@ -484,7 +438,12 @@ main(int argc, char *argv[]) SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); - open_audio(); + stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); + if (!stream) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); + return -1; + } + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); /* Main render loop */ done = 0; diff --git a/VisualC-GDK/tests/testgdk/testgdk.vcxproj b/VisualC-GDK/tests/testgdk/testgdk.vcxproj index c0e74e22e3eca..c43e5f4d9cb53 100644 --- a/VisualC-GDK/tests/testgdk/testgdk.vcxproj +++ b/VisualC-GDK/tests/testgdk/testgdk.vcxproj @@ -139,7 +139,7 @@ Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -223,7 +223,7 @@ true Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -346,7 +346,7 @@ copy "%(FullPath)" "$(OutDir)\" - + Document true true diff --git a/VisualC-GDK/tests/testgdk/testgdk.vcxproj.filters b/VisualC-GDK/tests/testgdk/testgdk.vcxproj.filters index b82a989857379..1cbae864107b1 100644 --- a/VisualC-GDK/tests/testgdk/testgdk.vcxproj.filters +++ b/VisualC-GDK/tests/testgdk/testgdk.vcxproj.filters @@ -18,9 +18,6 @@ logos - - wingdk - wingdk @@ -35,6 +32,9 @@ logos + + wingdk + diff --git a/VisualC-GDK/tests/testsprite/testsprite.vcxproj b/VisualC-GDK/tests/testsprite/testsprite.vcxproj index 211f14cb96e32..9534f5b0b9e8d 100644 --- a/VisualC-GDK/tests/testsprite/testsprite.vcxproj +++ b/VisualC-GDK/tests/testsprite/testsprite.vcxproj @@ -139,7 +139,7 @@ Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -223,7 +223,7 @@ true Windows - xgameruntime.lib;../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib;%(AdditionalDependencies) + xgameruntime.lib;../Microsoft.Xbox.Services.GDK.C.Thunks.lib;%(AdditionalDependencies) @@ -346,7 +346,7 @@ copy "%(FullPath)" "$(OutDir)\" - + Document true true diff --git a/VisualC-GDK/tests/testsprite/testsprite.vcxproj.filters b/VisualC-GDK/tests/testsprite/testsprite.vcxproj.filters index 3e0399e1f931b..ac1cda63980db 100644 --- a/VisualC-GDK/tests/testsprite/testsprite.vcxproj.filters +++ b/VisualC-GDK/tests/testsprite/testsprite.vcxproj.filters @@ -18,9 +18,6 @@ logos - - wingdk - xboxseries @@ -34,6 +31,9 @@ logos + + wingdk + diff --git a/docs/README-gdk.md b/docs/README-gdk.md index 6c242b5a0c863..f68908c39a5c6 100644 --- a/docs/README-gdk.md +++ b/docs/README-gdk.md @@ -3,15 +3,16 @@ GDK This port allows SDL applications to run via Microsoft's Game Development Kit (GDK). -Windows (GDK) and Xbox One/Xbox Series (GDKX) are supported. Although most of the Xbox code is included in the public SDL source code, NDA access is required for a small number of source files. If you have access to GDKX, these required Xbox files are posted on the GDK forums [here](https://forums.xboxlive.com/questions/130003/). +Windows (GDK) and Xbox One/Xbox Series (GDKX) are both supported and all the required code is included in this public SDL release. However, only licensed Xbox developers have access to the GDKX libraries which will allow you to build the Xbox targets. Requirements ------------ * Microsoft Visual Studio 2022 (in theory, it should also work in 2017 or 2019, but this has not been tested) -* Microsoft GDK June 2022 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/June_2022)) -* To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the identifiers used by the GDK test programs in the included solution will work. +* Microsoft GDK October 2023 Update 1 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/October_2023_Update_1)) +* For Xbox, you will need the corresponding GDKX version (licensed developers only) +* To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the test identifiers used by the GDK test programs in the included solution work. Windows GDK Status @@ -32,8 +33,8 @@ The Windows GDK port supports the full set of Win32 APIs, renderers, controllers * Single-player games have some additional features available: * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer. * `SDL_GetPrefPath` still works, but only for single-player titles. - -These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! + + These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! * What doesn't work: * Compilation with anything other than through the included Visual C++ solution file @@ -74,7 +75,7 @@ While the Gaming.Desktop.x64 configuration sets most of the required settings, t * Under Linker > Input > Additional Dependencies, you need the following: * `SDL3.lib` * `xgameruntime.lib` - * `../Microsoft.Xbox.Services.141.GDK.C.Thunks.lib` + * `../Microsoft.Xbox.Services.GDK.C.Thunks.lib` * Note that in general, the GDK libraries depend on the MSVC C/C++ runtime, so there is no way to remove this dependency from a GDK program that links against GDK. ### 4. Setting up SDL_main ### @@ -86,7 +87,7 @@ Rather than using your own implementation of `WinMain`, it's recommended that yo The game will not launch in the debugger unless required DLLs are included in the directory that contains the game's .exe file. You need to make sure that the following files are copied into the directory: * Your SDL3.dll -* "$(Console_GRDKExtLibRoot)Xbox.Services.API.C\DesignTime\CommonConfiguration\Neutral\Lib\Release\Microsoft.Xbox.Services.141.GDK.C.Thunks.dll" +* "$(Console_GRDKExtLibRoot)Xbox.Services.API.C\DesignTime\CommonConfiguration\Neutral\Lib\Release\Microsoft.Xbox.Services.GDK.C.Thunks.dll" * XCurl.dll You can either copy these in a post-build step, or you can add the dlls into the project and set its Configuration Properties > General > Item type to "Copy file," which will also copy them into the output directory. @@ -143,6 +144,20 @@ To create the package: 6. Once the package is installed, you can run it from the start menu. 7. As with when running from Visual Studio, if you need to test any Xbox Live functionality you must switch to the correct sandbox. +Xbox GDKX Setup +--------------------- +In general, the same process in the Windows GDK instructions work. There are just a few additional notes: +* For Xbox One consoles, use the Gaming.Xbox.XboxOne.x64 target +* For Xbox Series consoles, use the Gaming.Xbox.Scarlett.x64 target +* The Xbox One target sets the `__XBOXONE__` define and the Xbox Series target sets the `__XBOXSERIES__` define +* You don't need to link against the Xbox.Services Thunks lib nor include that dll in your package (it doesn't exist for Xbox) +* The shader blobs for Xbox are created in a pre-build step for the Xbox targets, rather than included in the source (due to NDA and version compatability reasons) +* To create a package, use: + `makepkg pack /f PackageLayout.xml /lt /d . /pd Package` +* To install the package, use: + `xbapp install [PACKAGE].xvc` +* For some reason, if you make changes that require SDL3.dll to build, and you are running through the debugger (instead of a package), you have to rebuild your .exe target for the debugger to recognize the dll has changed and needs to be transferred to the console again +* While there are successful releases of Xbox titles using this port, it is not as extensively tested as other targets Troubleshooting --------------- diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c index d67dab04dceb6..b9e33974297b3 100644 --- a/src/core/SDL_core_unsupported.c +++ b/src/core/SDL_core_unsupported.c @@ -224,3 +224,12 @@ Sint32 JNI_OnLoad(void *vm, void *reserved) return -1; /* JNI_ERR */ } #endif + +#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +char *SDL_GetUserFolder(SDL_Folder folder) +{ + (void)folder; + SDL_Unsupported(); + return NULL; +} +#endif diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp index 1fb0ff9a5c4e6..26f515746d414 100644 --- a/src/filesystem/gdk/SDL_sysfilesystem.cpp +++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp @@ -18,7 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "../../SDL_internal.h" +#include "SDL_internal.h" #ifdef SDL_FILESYSTEM_XBOX @@ -26,9 +26,9 @@ /* System dependent filesystem routines */ #include "../../core/windows/SDL_windows.h" -#include "SDL_hints.h" -#include "SDL_system.h" -#include "SDL_filesystem.h" +#include +#include +#include #include char * diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 1f5dafd38667b..f87fcb917fa56 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1435,7 +1435,7 @@ static void D3D12_FreeSRVIndex(SDL_Renderer *renderer, SIZE_T index) static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D12Resource **texture) { - IUnknown *unknown = SDL_GetProperty(props, name, NULL); + IUnknown *unknown = (IUnknown*)SDL_GetProperty(props, name, NULL); if (unknown) { HRESULT result = D3D_CALL(unknown, QueryInterface, D3D_GUID(SDL_IID_ID3D12Resource), (void **)texture); if (FAILED(result)) { diff --git a/src/render/direct3d12/SDL_render_d3d12_xbox.cpp b/src/render/direct3d12/SDL_render_d3d12_xbox.cpp index a7fbef19212e9..0c4605561c9eb 100644 --- a/src/render/direct3d12/SDL_render_d3d12_xbox.cpp +++ b/src/render/direct3d12/SDL_render_d3d12_xbox.cpp @@ -19,9 +19,156 @@ 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && (defined(__XBOXONE__) || defined(__XBOXSERIES__)) +#include "../../SDL_internal.h" +#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && (defined(__XBOXONE__) || defined(__XBOXSERIES__)) #include "SDL_render_d3d12_xbox.h" +#include "../../core/windows/SDL_windows.h" +#include + +#if defined(_MSC_VER) && !defined(__clang__) +#define SDL_COMPOSE_ERROR(str) __FUNCTION__ ", " str +#else +#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str +#endif + +static const GUID SDL_IID_ID3D12Device1 = { 0x77acce80, 0x638e, 0x4e65, { 0x88, 0x95, 0xc1, 0xf2, 0x33, 0x86, 0x86, 0x3e } }; +static const GUID SDL_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } }; +static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } }; + +extern "C" HRESULT +D3D12_XBOX_CreateDevice(ID3D12Device **device, SDL_bool createDebug) +{ + HRESULT result; + D3D12XBOX_CREATE_DEVICE_PARAMETERS params; + IDXGIDevice1 *dxgiDevice; + IDXGIAdapter *dxgiAdapter; + IDXGIOutput *dxgiOutput; + SDL_zero(params); + + params.Version = D3D12_SDK_VERSION; + params.ProcessDebugFlags = createDebug ? D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED : D3D12XBOX_PROCESS_DEBUG_FLAG_NONE; + params.GraphicsCommandQueueRingSizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES; + params.GraphicsScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES; + params.ComputeScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES; + + result = D3D12XboxCreateDevice(NULL, ¶ms, SDL_IID_ID3D12Device1, (void **) device); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] D3D12XboxCreateDevice"), result); + goto done; + } + + result = (*device)->QueryInterface(SDL_IID_IDXGIDevice1, (void **) &dxgiDevice); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] ID3D12Device to IDXGIDevice1"), result); + goto done; + } + + result = dxgiDevice->GetAdapter(&dxgiAdapter); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] dxgiDevice->GetAdapter"), result); + goto done; + } + + result = dxgiAdapter->EnumOutputs(0, &dxgiOutput); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] dxgiAdapter->EnumOutputs"), result); + goto done; + } + + /* Set frame interval */ + result = (*device)->SetFrameIntervalX(dxgiOutput, D3D12XBOX_FRAME_INTERVAL_60_HZ, 1, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] SetFrameIntervalX"), result); + goto done; + } + + result = (*device)->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0, NULL, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] ScheduleFrameEventX"), result); + goto done; + } + +done: + return result; +} + +extern "C" HRESULT +D3D12_XBOX_CreateBackBufferTarget(ID3D12Device1 *device, int width, int height, void **resource) +{ + + D3D12_HEAP_PROPERTIES heapProps; + D3D12_RESOURCE_DESC resourceDesc; + + SDL_zero(heapProps); + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + SDL_zero(resourceDesc); + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resourceDesc.Alignment = 0; + resourceDesc.Width = width; + resourceDesc.Height = height; + resourceDesc.DepthOrArraySize = 1; + resourceDesc.MipLevels = 1; + resourceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + resourceDesc.SampleDesc.Count = 1; + resourceDesc.SampleDesc.Quality = 0; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + + return device->CreateCommittedResource(&heapProps, + D3D12_HEAP_FLAG_ALLOW_DISPLAY, + &resourceDesc, + D3D12_RESOURCE_STATE_PRESENT, + NULL, + SDL_IID_ID3D12Resource, + resource + ); +} + +extern "C" HRESULT +D3D12_XBOX_StartFrame(ID3D12Device1 *device, UINT64 *outToken) +{ + *outToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + return device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, NULL, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, outToken); +} + +extern "C" HRESULT +D3D12_XBOX_PresentFrame(ID3D12CommandQueue *commandQueue, UINT64 token, ID3D12Resource *renderTarget) +{ + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters; + SDL_zero(planeParameters); + planeParameters.Token = token; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = &renderTarget; + return commandQueue->PresentX(1, &planeParameters, NULL); +} + +extern "C" void +D3D12_XBOX_GetResolution(Uint32 *width, Uint32 *height) +{ + switch (XSystemGetDeviceType()) { + case XSystemDeviceType::XboxScarlettLockhart: + *width = 2560; + *height = 1440; + break; + + case XSystemDeviceType::XboxOneX: + case XSystemDeviceType::XboxScarlettAnaconda: + case XSystemDeviceType::XboxOneXDevkit: + case XSystemDeviceType::XboxScarlettDevkit: + *width = 3840; + *height = 2160; + break; + + default: + *width = 1920; + *height = 1080; + break; + } +} -#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info." #endif diff --git a/src/render/direct3d12/SDL_render_d3d12_xbox.h b/src/render/direct3d12/SDL_render_d3d12_xbox.h index 4f5ee1fc0dfec..6db955a4229d3 100644 --- a/src/render/direct3d12/SDL_render_d3d12_xbox.h +++ b/src/render/direct3d12/SDL_render_d3d12_xbox.h @@ -19,4 +19,31 @@ 3. This notice may not be removed or altered from any source distribution. */ -#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info." +#ifndef SDL_render_d3d12_xbox_h_ +#define SDL_render_d3d12_xbox_h_ + +#include "../../SDL_internal.h" + +#if defined(__XBOXONE__) +#include +#else /* __XBOXSERIES__ */ +#include +#endif + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +extern HRESULT D3D12_XBOX_CreateDevice(ID3D12Device **device, SDL_bool createDebug); +extern HRESULT D3D12_XBOX_CreateBackBufferTarget(ID3D12Device1 *device, int width, int height, void **resource); +extern HRESULT D3D12_XBOX_StartFrame(ID3D12Device1 *device, UINT64 *outToken); +extern HRESULT D3D12_XBOX_PresentFrame(ID3D12CommandQueue *commandQueue, UINT64 token, ID3D12Resource *renderTarget); +extern void D3D12_XBOX_GetResolution(Uint32 *width, Uint32 *height); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp b/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp index 90339bf234f5e..e224ffc2b7906 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp +++ b/src/render/direct3d12/SDL_shaders_d3d12_xboxone.cpp @@ -18,10 +18,127 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_internal.h" +#include "../../SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && defined(__XBOXONE__) +#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXONE__) -#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info." +#include + +#include "../../core/windows/SDL_windows.h" +#include + +#include "SDL_shaders_d3d12.h" + +#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str + +/* Shader blob headers are generated with a pre-build step using buildshaders.bat */ +#include "../VisualC-GDK/shaders/D3D12_PixelShader_Colors_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_Textures_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709_One.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG_One.h" + +#include "../VisualC-GDK/shaders/D3D12_VertexShader_Color_One.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_NV_One.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_Texture_One.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_YUV_One.h" + +#include "../VisualC-GDK/shaders/D3D12_RootSig_Color_One.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_NV_One.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_Texture_One.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_YUV_One.h" + +static struct +{ + const void *ps_shader_data; + SIZE_T ps_shader_size; + const void *vs_shader_data; + SIZE_T vs_shader_size; + D3D12_RootSignature root_sig; +} D3D12_shaders[NUM_SHADERS] = { + { D3D12_PixelShader_Colors, sizeof(D3D12_PixelShader_Colors), + D3D12_VertexShader_Color, sizeof(D3D12_VertexShader_Color), + ROOTSIG_COLOR }, + { D3D12_PixelShader_Textures, sizeof(D3D12_PixelShader_Textures), + D3D12_VertexShader_Texture, sizeof(D3D12_VertexShader_Texture), + ROOTSIG_TEXTURE }, +#if SDL_HAVE_YUV + { D3D12_PixelShader_YUV_JPEG, sizeof(D3D12_PixelShader_YUV_JPEG), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_YUV_BT601, sizeof(D3D12_PixelShader_YUV_BT601), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_YUV_BT709, sizeof(D3D12_PixelShader_YUV_BT709), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_NV12_JPEG, sizeof(D3D12_PixelShader_NV12_JPEG), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV12_BT601, sizeof(D3D12_PixelShader_NV12_BT601), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV12_BT709, sizeof(D3D12_PixelShader_NV12_BT709), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_JPEG, sizeof(D3D12_PixelShader_NV21_JPEG), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_BT601, sizeof(D3D12_PixelShader_NV21_BT601), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_BT709, sizeof(D3D12_PixelShader_NV21_BT709), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, +#endif +}; + +static struct +{ + const void *rs_shader_data; + SIZE_T rs_shader_size; +} D3D12_rootsigs[NUM_ROOTSIGS] = { + { D3D12_RootSig_Color, sizeof(D3D12_RootSig_Color) }, + { D3D12_RootSig_Texture, sizeof(D3D12_RootSig_Texture) }, +#if SDL_HAVE_YUV + { D3D12_RootSig_YUV, sizeof(D3D12_RootSig_YUV) }, + { D3D12_RootSig_NV, sizeof(D3D12_RootSig_NV) }, +#endif +}; + +extern "C" void +D3D12_GetVertexShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_shaders[shader].vs_shader_data; + outBytecode->BytecodeLength = D3D12_shaders[shader].vs_shader_size; +} + +extern "C" void +D3D12_GetPixelShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_shaders[shader].ps_shader_data; + outBytecode->BytecodeLength = D3D12_shaders[shader].ps_shader_size; +} + +extern "C" D3D12_RootSignature +D3D12_GetRootSignatureType(D3D12_Shader shader) +{ + return D3D12_shaders[shader].root_sig; +} + +extern "C" void +D3D12_GetRootSignatureData(D3D12_RootSignature rootSig, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_rootsigs[rootSig].rs_shader_data; + outBytecode->BytecodeLength = D3D12_rootsigs[rootSig].rs_shader_size; +} #endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXONE__) */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp b/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp index beeefabbd6e62..29c20cd692c32 100644 --- a/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp +++ b/src/render/direct3d12/SDL_shaders_d3d12_xboxseries.cpp @@ -18,10 +18,127 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_internal.h" +#include "../../SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && defined(__XBOXSERIES__) +#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXSERIES__) -#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info." +#include + +#include "../../core/windows/SDL_windows.h" +#include + +#include "SDL_shaders_d3d12.h" + +#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str + +/* Shader blob headers are generated with a pre-build step using buildshaders.bat */ +#include "../VisualC-GDK/shaders/D3D12_PixelShader_Colors_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_Textures_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709_Series.h" +#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG_Series.h" + +#include "../VisualC-GDK/shaders/D3D12_VertexShader_Color_Series.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_Texture_Series.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_NV_Series.h" +#include "../VisualC-GDK/shaders/D3D12_VertexShader_YUV_Series.h" + +#include "../VisualC-GDK/shaders/D3D12_RootSig_Color_Series.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_Texture_Series.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_YUV_Series.h" +#include "../VisualC-GDK/shaders/D3D12_RootSig_NV_Series.h" + +static struct +{ + const void *ps_shader_data; + SIZE_T ps_shader_size; + const void *vs_shader_data; + SIZE_T vs_shader_size; + D3D12_RootSignature root_sig; +} D3D12_shaders[NUM_SHADERS] = { + { D3D12_PixelShader_Colors, sizeof(D3D12_PixelShader_Colors), + D3D12_VertexShader_Color, sizeof(D3D12_VertexShader_Color), + ROOTSIG_COLOR }, + { D3D12_PixelShader_Textures, sizeof(D3D12_PixelShader_Textures), + D3D12_VertexShader_Texture, sizeof(D3D12_VertexShader_Texture), + ROOTSIG_TEXTURE }, +#if SDL_HAVE_YUV + { D3D12_PixelShader_YUV_JPEG, sizeof(D3D12_PixelShader_YUV_JPEG), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_YUV_BT601, sizeof(D3D12_PixelShader_YUV_BT601), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_YUV_BT709, sizeof(D3D12_PixelShader_YUV_BT709), + D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV), + ROOTSIG_YUV }, + { D3D12_PixelShader_NV12_JPEG, sizeof(D3D12_PixelShader_NV12_JPEG), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV12_BT601, sizeof(D3D12_PixelShader_NV12_BT601), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV12_BT709, sizeof(D3D12_PixelShader_NV12_BT709), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_JPEG, sizeof(D3D12_PixelShader_NV21_JPEG), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_BT601, sizeof(D3D12_PixelShader_NV21_BT601), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, + { D3D12_PixelShader_NV21_BT709, sizeof(D3D12_PixelShader_NV21_BT709), + D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV), + ROOTSIG_NV }, +#endif +}; + +static struct +{ + const void *rs_shader_data; + SIZE_T rs_shader_size; +} D3D12_rootsigs[NUM_ROOTSIGS] = { + { D3D12_RootSig_Color, sizeof(D3D12_RootSig_Color) }, + { D3D12_RootSig_Texture, sizeof(D3D12_RootSig_Texture) }, +#if SDL_HAVE_YUV + { D3D12_RootSig_YUV, sizeof(D3D12_RootSig_YUV) }, + { D3D12_RootSig_NV, sizeof(D3D12_RootSig_NV) }, +#endif +}; + +extern "C" void +D3D12_GetVertexShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_shaders[shader].vs_shader_data; + outBytecode->BytecodeLength = D3D12_shaders[shader].vs_shader_size; +} + +extern "C" void +D3D12_GetPixelShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_shaders[shader].ps_shader_data; + outBytecode->BytecodeLength = D3D12_shaders[shader].ps_shader_size; +} + +extern "C" D3D12_RootSignature +D3D12_GetRootSignatureType(D3D12_Shader shader) +{ + return D3D12_shaders[shader].root_sig; +} + +extern "C" void +D3D12_GetRootSignatureData(D3D12_RootSignature rootSig, D3D12_SHADER_BYTECODE *outBytecode) +{ + outBytecode->pShaderBytecode = D3D12_rootsigs[rootSig].rs_shader_data; + outBytecode->BytecodeLength = D3D12_rootsigs[rootSig].rs_shader_size; +} #endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXSERIES__) */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video_unsupported.c b/src/video/SDL_video_unsupported.c index 633e717e13d48..0731f038038bd 100644 --- a/src/video/SDL_video_unsupported.c +++ b/src/video/SDL_video_unsupported.c @@ -41,7 +41,7 @@ int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID) #endif -#ifndef SDL_GDK_TEXTINPUT +#ifndef __GDK__ DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(void *outTaskQueue); int SDL_GDKGetTaskQueue(void *outTaskQueue) @@ -81,3 +81,11 @@ void SDL_iPhoneSetEventPump(SDL_bool enabled) SDL_Unsupported(); } #endif + +#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID) +{ + (void)displayID; + return SDL_Unsupported(); +} +#endif diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 777291cdd1273..250ef84133bc2 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -169,9 +169,11 @@ static SDL_Scancode WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam) } else { Uint16 vkCode = LOWORD(wParam); +#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) /* Windows may not report scan codes for some buttons (multimedia buttons etc). * Get scan code from the VK code.*/ scanCode = LOWORD(MapVirtualKey(vkCode, MAPVK_VK_TO_VSC_EX)); +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ /* Pause/Break key have a special scan code with 0xe1 prefix. * Use Pause scan code that is used in Win32. */ @@ -515,8 +517,6 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) return 1; } -#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ - static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, RAWMOUSE *rawmouse) { SDL_MouseID mouseID; @@ -692,6 +692,7 @@ void WIN_PollRawMouseInput(void) data->last_rawinput_poll = now; } +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 896eb81266fd6..2cab61dce7152 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -264,7 +264,7 @@ int WIN_AdjustWindowRectForHWND(HWND hwnd, LPRECT lpRect, UINT frame_dpi) #endif #if defined(__XBOXONE__) || defined(__XBOXSERIES__) - AdjustWindowRectEx(&rect, style, menu, styleEx); + AdjustWindowRectEx(lpRect, style, menu, styleEx); #else if (WIN_IsPerMonitorV2DPIAware(videodevice)) { /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of AdjustWindowRectEx. */ @@ -490,6 +490,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd data->initializing = SDL_FALSE; +#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) if (window->flags & SDL_WINDOW_EXTERNAL) { /* Query the title from the existing window */ LPTSTR title; @@ -510,6 +511,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwnd SDL_small_free(title, isstack); } } +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ SDL_PropertiesID props = SDL_GetWindowProperties(window); SDL_SetProperty(props, SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, data->hwnd); @@ -554,7 +556,9 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window) #endif } } +#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) SDL_free(data->rawinput); +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ SDL_free(data); } window->driverdata = NULL; @@ -672,6 +676,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI } } +#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) /* FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs) */ if (window->flags & SDL_WINDOW_TRANSPARENT) { void *handle = SDL_LoadObject("dwmapi.dll"); @@ -739,6 +744,7 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI return SDL_SetError("Could not create GL window (WGL support not configured)"); #endif } +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ return 0; } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 9de65c3cc073f..49659a1066c3b 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -67,11 +67,13 @@ struct SDL_WindowData SDL_bool windowed_mode_was_maximized; SDL_bool in_window_deactivation; RECT cursor_clipped_rect; +#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) RAWINPUT *rawinput; UINT rawinput_offset; UINT rawinput_size; UINT rawinput_count; Uint64 last_rawinput_poll; +#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ SDL_Point last_raw_mouse_position; SDL_bool mouse_tracked; SDL_bool destroy_parent_with_window; From 99f6bcf5049ba7d536f8e5b94de818618a47814e Mon Sep 17 00:00:00 2001 From: SDL Wiki Bot Date: Mon, 15 Jan 2024 04:32:24 +0000 Subject: [PATCH 725/725] Sync SDL3 wiki -> header --- docs/README-gdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-gdk.md b/docs/README-gdk.md index f68908c39a5c6..9a948583f2751 100644 --- a/docs/README-gdk.md +++ b/docs/README-gdk.md @@ -33,7 +33,7 @@ The Windows GDK port supports the full set of Win32 APIs, renderers, controllers * Single-player games have some additional features available: * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer. * `SDL_GetPrefPath` still works, but only for single-player titles. - + These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! * What doesn't work: