mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-08-17 00:47:34 +08:00
Add SDL3 support
This commit is contained in:
+12
-7
@@ -436,9 +436,9 @@ if(wxUSE_GUI)
|
||||
wx_option_force_value(wxUSE_GRAPHICS_DIRECT2D OFF)
|
||||
endif()
|
||||
endif()
|
||||
if(MSVC) # match setup.h
|
||||
if(MSVC) # match setup.h
|
||||
wx_option_force_value(wxUSE_GRAPHICS_DIRECT2D ${wxUSE_GRAPHICS_CONTEXT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# WXQT checks
|
||||
if(WXQT)
|
||||
@@ -691,12 +691,17 @@ if(wxUSE_GUI)
|
||||
endif()
|
||||
|
||||
if(wxUSE_SOUND AND wxUSE_LIBSDL AND UNIX AND NOT APPLE)
|
||||
find_package(SDL2)
|
||||
if(NOT SDL2_FOUND)
|
||||
find_package(SDL)
|
||||
mark_as_advanced(SDL_INCLUDE_DIR SDLMAIN_LIBRARY)
|
||||
find_package(SDL3)
|
||||
if(SDL3_FOUND)
|
||||
set(wxUSE_LIBSDL3 ON)
|
||||
else()
|
||||
find_package(SDL2)
|
||||
if(NOT SDL2_FOUND)
|
||||
find_package(SDL)
|
||||
mark_as_advanced(SDL_INCLUDE_DIR SDLMAIN_LIBRARY)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT SDL2_FOUND AND NOT SDL_FOUND)
|
||||
if(NOT SDL3_FOUND AND NOT SDL2_FOUND AND NOT SDL_FOUND)
|
||||
message(WARNING "SDL not found, SDL Audio back-end won't be available")
|
||||
wx_option_force_value(wxUSE_LIBSDL OFF)
|
||||
endif()
|
||||
|
||||
@@ -99,7 +99,17 @@ if(WXGTK AND wxUSE_PRIVATE_FONTS)
|
||||
wx_lib_link_libraries(wxcore PUBLIC ${FONTCONFIG_LIBRARIES} ${PANGOFT2_LIBRARIES})
|
||||
endif()
|
||||
if(wxUSE_LIBSDL)
|
||||
if(SDL2_FOUND)
|
||||
if(SDL3_FOUND)
|
||||
# Upstream SDL3 ships an imported target; prefer it over raw vars.
|
||||
if(TARGET SDL3::SDL3)
|
||||
wx_lib_link_libraries(wxcore PUBLIC SDL3::SDL3)
|
||||
elseif(TARGET SDL3::SDL3-shared)
|
||||
wx_lib_link_libraries(wxcore PUBLIC SDL3::SDL3-shared)
|
||||
else()
|
||||
wx_lib_include_directories(wxcore ${SDL3_INCLUDE_DIRS})
|
||||
wx_lib_link_libraries(wxcore PUBLIC ${SDL3_LIBRARIES})
|
||||
endif()
|
||||
elseif(SDL2_FOUND)
|
||||
wx_lib_include_directories(wxcore ${SDL2_INCLUDE_DIR})
|
||||
wx_lib_link_libraries(wxcore PUBLIC ${SDL2_LIBRARY})
|
||||
elseif(SDL_FOUND)
|
||||
|
||||
@@ -735,6 +735,11 @@
|
||||
*/
|
||||
#cmakedefine01 wxUSE_LIBSDL
|
||||
|
||||
/*
|
||||
* Use SDL 3.x (rather than SDL 2.x or 1.x) for the SDL audio backend
|
||||
*/
|
||||
#cmakedefine01 wxUSE_LIBSDL3
|
||||
|
||||
/*
|
||||
* Compile sound backends as plugins
|
||||
*/
|
||||
|
||||
+15
-4
@@ -5320,23 +5320,34 @@ WITH_PLUGIN_SDL=0
|
||||
if test "$wxUSE_SOUND" = "yes"; then
|
||||
if test "$USE_UNIX" = 1 -a "$USE_MAC" != 1 ; then
|
||||
if test "$wxUSE_LIBSDL" != "no"; then
|
||||
PKG_CHECK_MODULES([SDL], [sdl2 >= 2.0.0],
|
||||
PKG_CHECK_MODULES([SDL], [sdl3 >= 3.0.0],
|
||||
[
|
||||
EXTRALIBS_SDL="$SDL_LIBS"
|
||||
CFLAGS="$SDL_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$SDL_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(wxUSE_LIBSDL)
|
||||
AC_DEFINE(wxUSE_LIBSDL3)
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([SDL 2.0 not available. Falling back to 1.2.])
|
||||
AM_PATH_SDL([1.2.0],
|
||||
AC_MSG_NOTICE([SDL 3.0 not available. Falling back to SDL 2.0.])
|
||||
PKG_CHECK_MODULES([SDL], [sdl2 >= 2.0.0],
|
||||
[
|
||||
EXTRALIBS_SDL="$SDL_LIBS"
|
||||
CFLAGS="$SDL_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$SDL_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(wxUSE_LIBSDL)
|
||||
],
|
||||
[wxUSE_LIBSDL="no"])
|
||||
[
|
||||
AC_MSG_NOTICE([SDL 2.0 not available. Falling back to 1.2.])
|
||||
AM_PATH_SDL([1.2.0],
|
||||
[
|
||||
EXTRALIBS_SDL="$SDL_LIBS"
|
||||
CFLAGS="$SDL_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$SDL_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(wxUSE_LIBSDL)
|
||||
],
|
||||
[wxUSE_LIBSDL="no"])
|
||||
])
|
||||
])
|
||||
if test "$wxUSE_LIBSDL" = "yes" -a "$wxUSE_PLUGINS" = "yes" ; then
|
||||
WITH_PLUGIN_SDL=1
|
||||
|
||||
@@ -734,6 +734,11 @@
|
||||
*/
|
||||
#define wxUSE_LIBSDL 0
|
||||
|
||||
/*
|
||||
* Use SDL 3.x (rather than SDL 2.x or 1.x) for the SDL audio backend
|
||||
*/
|
||||
#define wxUSE_LIBSDL3 0
|
||||
|
||||
/*
|
||||
* Compile sound backends as plugins
|
||||
*/
|
||||
|
||||
+7
-1
@@ -88,7 +88,7 @@ typedef pid_t GPid;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined( VMS_GTK2 ) || defined( __WXX11__ )
|
||||
#if defined( VMS_GTK2 ) || defined( __WXX11__ )
|
||||
#define wxUSE_CAIRO 1
|
||||
#else
|
||||
#define wxUSE_CAIRO 0
|
||||
@@ -764,6 +764,12 @@ typedef pid_t GPid;
|
||||
* Use SDL for audio (Unix)
|
||||
*/
|
||||
#define wxUSE_LIBSDL 0
|
||||
|
||||
/*
|
||||
* Use SDL 3.x (rather than SDL 2.x or 1.x) for the SDL audio backend
|
||||
*/
|
||||
#define wxUSE_LIBSDL3 0
|
||||
|
||||
/*
|
||||
* Use GTK print for printing under GTK+ 2.10+
|
||||
*/
|
||||
|
||||
+120
-8
@@ -13,7 +13,24 @@
|
||||
|
||||
#if wxUSE_SOUND && wxUSE_LIBSDL
|
||||
|
||||
#include <SDL.h>
|
||||
#if wxUSE_LIBSDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
// Compatibility helpers so the rest of this file can be written once.
|
||||
#if SDL_MAJOR_VERSION >= 3
|
||||
typedef SDL_AudioFormat wxSDL_AudioFormat;
|
||||
#define wxSDL_AUDIO_U8 SDL_AUDIO_U8
|
||||
#define wxSDL_AUDIO_S16LSB SDL_AUDIO_S16LE
|
||||
#define WX_SDL_USE_STREAM_API 1
|
||||
#else
|
||||
typedef int wxSDL_AudioFormat;
|
||||
#define wxSDL_AUDIO_U8 AUDIO_U8
|
||||
#define wxSDL_AUDIO_S16LSB AUDIO_S16LSB
|
||||
#define WX_SDL_USE_STREAM_API 0
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/event.h"
|
||||
@@ -65,7 +82,11 @@ class wxSoundBackendSDL : public wxSoundBackend
|
||||
public:
|
||||
wxSoundBackendSDL()
|
||||
: m_initialized(false), m_playing(false), m_audioOpen(false),
|
||||
m_data(nullptr), m_evtHandler(nullptr) {}
|
||||
m_data(nullptr),
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
m_stream(nullptr), m_silence(0),
|
||||
#endif
|
||||
m_evtHandler(nullptr) {}
|
||||
virtual ~wxSoundBackendSDL();
|
||||
|
||||
wxString GetName() const override { return wxT("Simple DirectMedia Layer"); }
|
||||
@@ -93,6 +114,13 @@ private:
|
||||
SDL_AudioSpec m_spec;
|
||||
bool m_loop;
|
||||
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
// SDL3 owns the device through the audio stream; silence sample is no
|
||||
// longer part of SDL_AudioSpec, so we keep our own copy.
|
||||
SDL_AudioStream *m_stream;
|
||||
Uint8 m_silence;
|
||||
#endif
|
||||
|
||||
wxSoundBackendSDLEvtHandler *m_evtHandler;
|
||||
};
|
||||
|
||||
@@ -128,22 +156,45 @@ bool wxSoundBackendSDL::IsAvailable() const
|
||||
{
|
||||
if (m_initialized)
|
||||
return true;
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) != SDL_INIT_AUDIO)
|
||||
if ((SDL_WasInit(SDL_INIT_AUDIO) & SDL_INIT_AUDIO) != SDL_INIT_AUDIO)
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
|
||||
#if SDL_MAJOR_VERSION >= 3
|
||||
// SDL3: SDL_Init returns bool, and SDL_INIT_NOPARACHUTE is gone.
|
||||
if (!SDL_Init(SDL_INIT_AUDIO))
|
||||
return false;
|
||||
#else
|
||||
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE) == -1)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
wxConstCast(this, wxSoundBackendSDL)->m_initialized = true;
|
||||
wxLogTrace(wxT("sound"), wxT("initialized SDL audio subsystem"));
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
extern "C" void SDLCALL
|
||||
wx_sdl_audio_callback(void *userdata, SDL_AudioStream *stream,
|
||||
int additional_amount, int /*total_amount*/)
|
||||
{
|
||||
if (additional_amount <= 0)
|
||||
return;
|
||||
wxSoundBackendSDL *bk = static_cast<wxSoundBackendSDL*>(userdata);
|
||||
Uint8 *buf = static_cast<Uint8*>(SDL_malloc(additional_amount));
|
||||
if (!buf)
|
||||
return;
|
||||
bk->FillAudioBuffer(buf, additional_amount);
|
||||
SDL_PutAudioStreamData(stream, buf, additional_amount);
|
||||
SDL_free(buf);
|
||||
}
|
||||
#else
|
||||
extern "C" void wx_sdl_audio_callback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
wxSoundBackendSDL *bk = (wxSoundBackendSDL*)userdata;
|
||||
bk->FillAudioBuffer(stream, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
void wxSoundBackendSDL::FillAudioBuffer(Uint8 *stream, int len)
|
||||
{
|
||||
@@ -180,7 +231,11 @@ void wxSoundBackendSDL::FillAudioBuffer(Uint8 *stream, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
memset(stream, m_silence, len);
|
||||
#else
|
||||
memset(stream, m_spec.silence, len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,6 +253,33 @@ bool wxSoundBackendSDL::OpenAudio()
|
||||
if (!m_evtHandler)
|
||||
m_evtHandler = new wxSoundBackendSDLEvtHandler(this);
|
||||
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
// SDL3: silence and buffering are handled by the stream itself, and
|
||||
// SDL_AudioSpec only carries format/channels/freq.
|
||||
m_silence = (m_spec.format == wxSDL_AUDIO_U8) ? 128 : 0;
|
||||
|
||||
wxLogTrace(wxT("sound"), wxT("opening SDL audio..."));
|
||||
m_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
|
||||
&m_spec,
|
||||
wx_sdl_audio_callback,
|
||||
this);
|
||||
if (m_stream)
|
||||
{
|
||||
#if wxUSE_LOG_DEBUG
|
||||
const char *drv = SDL_GetCurrentAudioDriver();
|
||||
wxLogTrace(wxT("sound"), wxT("opened audio, driver '%s'"),
|
||||
wxString(drv ? drv : "", wxConvLocal));
|
||||
#endif
|
||||
m_audioOpen = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString err(SDL_GetError(), wxConvLocal);
|
||||
wxLogError(_("Couldn't open audio: %s"), err);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
m_spec.silence = 0;
|
||||
m_spec.samples = 4096;
|
||||
m_spec.size = 0;
|
||||
@@ -226,6 +308,7 @@ bool wxSoundBackendSDL::OpenAudio()
|
||||
wxLogError(_("Couldn't open audio: %s"), err);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -234,7 +317,12 @@ void wxSoundBackendSDL::CloseAudio()
|
||||
{
|
||||
if (m_audioOpen)
|
||||
{
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
SDL_DestroyAudioStream(m_stream);
|
||||
m_stream = nullptr;
|
||||
#else
|
||||
SDL_CloseAudio();
|
||||
#endif
|
||||
wxLogTrace(wxT("sound"), wxT("closed audio"));
|
||||
m_audioOpen = false;
|
||||
}
|
||||
@@ -245,11 +333,11 @@ bool wxSoundBackendSDL::Play(wxSoundData *data, unsigned flags,
|
||||
{
|
||||
Stop();
|
||||
|
||||
int format;
|
||||
wxSDL_AudioFormat format;
|
||||
if (data->m_bitsPerSample == 8)
|
||||
format = AUDIO_U8;
|
||||
format = wxSDL_AUDIO_U8;
|
||||
else if (data->m_bitsPerSample == 16)
|
||||
format = AUDIO_S16LSB;
|
||||
format = wxSDL_AUDIO_S16LSB;
|
||||
else
|
||||
return false;
|
||||
|
||||
@@ -258,7 +346,7 @@ bool wxSoundBackendSDL::Play(wxSoundData *data, unsigned flags,
|
||||
{
|
||||
if (format == m_spec.format &&
|
||||
m_spec.freq == (int)data->m_samplingRate &&
|
||||
m_spec.channels == data->m_channels)
|
||||
(unsigned)m_spec.channels == data->m_channels)
|
||||
{
|
||||
needsOpen = false;
|
||||
}
|
||||
@@ -277,16 +365,24 @@ bool wxSoundBackendSDL::Play(wxSoundData *data, unsigned flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
SDL_LockAudioStream(m_stream);
|
||||
#else
|
||||
SDL_LockAudio();
|
||||
#endif
|
||||
wxLogTrace(wxT("sound"), wxT("playing new sound"));
|
||||
m_playing = true;
|
||||
m_pos = 0;
|
||||
m_loop = (flags & wxSOUND_LOOP);
|
||||
m_data = data;
|
||||
data->IncRef();
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
SDL_UnlockAudioStream(m_stream);
|
||||
SDL_ResumeAudioStreamDevice(m_stream);
|
||||
#else
|
||||
SDL_UnlockAudio();
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
#endif
|
||||
|
||||
// wait until playback finishes if called in sync mode:
|
||||
if (!(flags & wxSOUND_ASYNC))
|
||||
@@ -314,6 +410,21 @@ bool wxSoundBackendSDL::Play(wxSoundData *data, unsigned flags,
|
||||
|
||||
void wxSoundBackendSDL::Stop()
|
||||
{
|
||||
#if WX_SDL_USE_STREAM_API
|
||||
if (m_stream)
|
||||
{
|
||||
SDL_LockAudioStream(m_stream);
|
||||
SDL_PauseAudioStreamDevice(m_stream);
|
||||
}
|
||||
m_playing = false;
|
||||
if (m_data)
|
||||
{
|
||||
m_data->DecRef();
|
||||
m_data = nullptr;
|
||||
}
|
||||
if (m_stream)
|
||||
SDL_UnlockAudioStream(m_stream);
|
||||
#else
|
||||
SDL_LockAudio();
|
||||
SDL_PauseAudio(1);
|
||||
m_playing = false;
|
||||
@@ -323,6 +434,7 @@ void wxSoundBackendSDL::Stop()
|
||||
m_data = nullptr;
|
||||
}
|
||||
SDL_UnlockAudio();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" wxSoundBackend *wxCreateSoundBackendSDL()
|
||||
|
||||
Reference in New Issue
Block a user