Skip to content

Commit

Permalink
Add SDL3 support
Browse files Browse the repository at this point in the history
Fix #2865
  • Loading branch information
Ghabry committed Jan 22, 2025
1 parent fa09f89 commit 13e106e
Show file tree
Hide file tree
Showing 15 changed files with 1,802 additions and 78 deletions.
40 changes: 30 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,8 @@ elseif(NINTENDO_WIIU)
elseif(AMIGA)
set(PLAYER_TARGET_PLATFORM "SDL1" CACHE STRING "Platform to compile for.")
else()
set(PLAYER_TARGET_PLATFORM "SDL2" CACHE STRING "Platform to compile for. Options: SDL2 SDL1 libretro")
set_property(CACHE PLAYER_TARGET_PLATFORM PROPERTY STRINGS SDL2 SDL1 libretro)
set(PLAYER_TARGET_PLATFORM "SDL3" CACHE STRING "Platform to compile for. Options: SDL3 SDL2 SDL1 libretro")
set_property(CACHE PLAYER_TARGET_PLATFORM PROPERTY STRINGS SDL3 SDL2 SDL1 libretro)
endif()
set(PLAYER_BUILD_EXECUTABLE ON)
set(PLAYER_TEST_LIBRARIES ${PROJECT_NAME})
Expand All @@ -579,7 +579,20 @@ if(ANDROID AND PLAYER_GRADLE_BUILD)
endforeach(f)
endif()

if(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2")
if(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL3")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/sdl/sdl3_ui.cpp
src/platform/sdl/sdl3_ui.h)
target_compile_definitions(${PROJECT_NAME} PUBLIC USE_SDL=3)

player_find_package(NAME SDL3
TARGET SDL3::SDL3
REQUIRED)

if(ANDROID)
set(PLAYER_BUILD_EXECUTABLE OFF)
endif()
elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/sdl/sdl2_ui.cpp
src/platform/sdl/sdl2_ui.h)
Expand Down Expand Up @@ -703,6 +716,9 @@ endif()
# Sound system to use
if(PLAYER_AUDIO_BACKEND)
# already set earlier in the platform config
elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL3")
set(PLAYER_AUDIO_BACKEND "SDL3" CACHE STRING "Audio system to use. Options: SDL3 OFF")
set_property(CACHE PLAYER_AUDIO_BACKEND PROPERTY STRINGS SDL3 OFF)
elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2")
set(PLAYER_AUDIO_BACKEND "SDL2" CACHE STRING "Audio system to use. Options: SDL2 OFF")
set_property(CACHE PLAYER_AUDIO_BACKEND PROPERTY STRINGS SDL2 OFF)
Expand All @@ -720,22 +736,26 @@ else()
endif()

set(PLAYER_HAS_AUDIO ON)
if(${PLAYER_AUDIO_BACKEND} STREQUAL "SDL1")
if(${PLAYER_AUDIO_BACKEND} STREQUAL "SDL3")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/sdl/sdl_audio.cpp
src/platform/sdl/sdl_audio.h)
src/platform/sdl/sdl3_audio.cpp
src/platform/sdl/sdl3_audio.h)
elseif(${PLAYER_AUDIO_BACKEND} STREQUAL "SDL2")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/sdl/sdl_audio.cpp
src/platform/sdl/sdl_audio.h)
src/platform/sdl/sdl2_audio.cpp
src/platform/sdl/sdl2_audio.h)
elseif(${PLAYER_AUDIO_BACKEND} STREQUAL "SDL1")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/sdl/sdl1_audio.cpp
src/platform/sdl/sdl1_audio.h)
elseif(${PLAYER_AUDIO_BACKEND} STREQUAL "AESND")
target_sources(${PROJECT_NAME} PRIVATE
src/platform/wii/audio.cpp
src/platform/wii/audio.h)
target_compile_definitions(${PROJECT_NAME} PUBLIC AUDIO_AESND=1)
elseif(${PLAYER_AUDIO_BACKEND} STREQUAL ${PLAYER_TARGET_PLATFORM})

elseif(${PLAYER_AUDIO_BACKED} STREQUAL "OFF")
elseif(${PLAYER_AUDIO_BACKEND} STREQUAL "OFF")
set(PLAYER_HAS_AUDIO OFF)
else()
message(FATAL_ERROR "Invalid Audio Backend ${PLAYER_AUDIO_BACKEND}")
Expand Down Expand Up @@ -1366,7 +1386,7 @@ else() # library
if(WIN32)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT easyrpg_libretro)
endif()
elseif(ANDROID AND ${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2")
elseif(ANDROID AND ${PLAYER_TARGET_PLATFORM} MATCHES "^SDL.*$")
add_library(easyrpg_android
src/platform/android/android.cpp
src/platform/android/android.h
Expand Down
15 changes: 13 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -452,11 +452,22 @@ libeasyrpg_player_a_SOURCES = \
src/window_varlist.cpp \
src/window_varlist.h

SOURCEFILES_SDL3 += \
src/platform/sdl/sdl3_ui.cpp \
src/platform/sdl/sdl3_ui.h \
src/platform/sdl/sdl3_audio.cpp \
src/platform/sdl/sdl3_audio.h
if HAVE_SDL3
libeasyrpg_player_a_SOURCES += $(SOURCEFILES_SDL3)
else
EXTRA_DIST += $(SOURCEFILES_SDL3)
endif

SOURCEFILES_SDL2 = \
src/platform/sdl/sdl2_ui.cpp \
src/platform/sdl/sdl2_ui.h \
src/platform/sdl/sdl_audio.cpp \
src/platform/sdl/sdl_audio.h
src/platform/sdl/sdl2_audio.cpp \
src/platform/sdl/sdl2_audio.h
if HAVE_SDL2
libeasyrpg_player_a_SOURCES += $(SOURCEFILES_SDL2)
else
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Documentation is available at the documentation wiki: https://wiki.easyrpg.org
### minimal / required

- [liblcf] for RPG Maker data reading.
- SDL2 >= 2.0.5 for screen backend support.
- SDL3 or SDL2 >= 2.0.5 for screen backend support.
- Pixman for low level pixel manipulation.
- libpng for PNG image support.
- zlib for XYZ image and ZIP archive support.
Expand Down
13 changes: 9 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ PKG_CHECK_MODULES([FMT],[fmt],,[
AC_MSG_ERROR([Could not find libfmt! Consider installing version 5.3 or newer.])
],[AC_MSG_RESULT([yes])])
])
PKG_CHECK_MODULES([SDL],[sdl2 >= 2.0.5],[sdl_version=2],[
PKG_CHECK_MODULES([SDL],[sdl],[sdl_version=1],[
AC_MSG_ERROR([Could not find SDL! Consider installing version 2.0.5 or newer.])
PKG_CHECK_MODULES([SDL],[sdl3],[sdl_version=3],[
PKG_CHECK_MODULES([SDL],[sdl2 >= 2.0.5],[sdl_version=2],[
PKG_CHECK_MODULES([SDL],[sdl],[sdl_version=1],[
AC_MSG_ERROR([Could not find SDL! Consider installing version 2.0.5 or newer.])
])
])
])
AC_DEFINE_UNQUOTED([USE_SDL],[$sdl_version],[Enable SDL, version 2 or 1.2])
AC_DEFINE_UNQUOTED([USE_SDL],[$sdl_version],[Enable SDL, version 3, 2 or 1.2])
AM_CONDITIONAL([HAVE_SDL3], [test "x$sdl_version" = "x3"])
AM_CONDITIONAL([HAVE_SDL2], [test "x$sdl_version" = "x2"])
AM_CONDITIONAL([HAVE_SDL1], [test "x$sdl_version" = "x1"])
EP_PKG_CHECK([FREETYPE],[freetype2],[Custom Font rendering.])
Expand Down Expand Up @@ -219,6 +222,8 @@ if test "yes" != "$silent"; then
echo " prefix: $prefix"
echo " bash completion: $BASHCOMPLETION_DIR"
test "$sdl_version" = "3" && \
echo "Backend: SDL3"
test "$sdl_version" = "2" && \
echo "Backend: SDL2"
test "$sdl_version" = "1" && \
Expand Down
8 changes: 6 additions & 2 deletions src/baseui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#include "bitmap.h"
#include "player.h"

#if USE_SDL==2
#if USE_SDL==3
# include "platform/sdl/sdl3_ui.h"
#elif USE_SDL==2
# include "platform/sdl/sdl2_ui.h"
#elif USE_SDL==1
# include "platform/sdl/sdl_ui.h"
Expand All @@ -37,7 +39,9 @@
std::shared_ptr<BaseUi> DisplayUi;

std::shared_ptr<BaseUi> BaseUi::CreateUi(long width, long height, const Game_Config& cfg) {
#if USE_SDL==2
#if USE_SDL==3
return std::make_shared<Sdl3Ui>(width, height, cfg);
#elif USE_SDL==2
return std::make_shared<Sdl2Ui>(width, height, cfg);
#elif USE_SDL==1
return std::make_shared<SdlUi>(width, height, cfg);
Expand Down
4 changes: 3 additions & 1 deletion src/platform/sdl/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include "utils.h"
#include "output.h"

#ifdef USE_SDL // This is needed on Windows, SDL wraps main()
#if USE_SDL == 3 // This is needed on Windows, SDL wraps main()
# include <SDL3/SDL.h>
#elif USE_SDL <= 2
# include <SDL.h>
#endif
#ifdef _WIN32
Expand Down
128 changes: 128 additions & 0 deletions src/platform/sdl/sdl2_audio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* This file is part of EasyRPG Player.
*
* EasyRPG Player is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EasyRPG Player is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
*/

#include "system.h"

#ifdef SUPPORT_AUDIO

#include <cassert>
#include <cstdint>
#include <chrono>
#include <SDL.h>
#include <SDL_audio.h>
#include <SDL_version.h>

#ifdef EMSCRIPTEN
# include <emscripten.h>
#endif

#include "sdl2_audio.h"
#include "output.h"

using namespace std::chrono_literals;

namespace {
SDL_AudioDeviceID audio_dev_id = 0;
}

void sdl_audio_callback(void* userdata, uint8_t* stream, int length) {
// no mutex locking required, SDL does this before calling

static_cast<GenericAudio*>(userdata)->Decode(stream, length);
}

AudioDecoder::Format sdl_format_to_format(Uint16 format) {
switch (format) {
case AUDIO_U8:
return AudioDecoder::Format::U8;
case AUDIO_S8:
return AudioDecoder::Format::S8;
case AUDIO_U16SYS:
return AudioDecoder::Format::U16;
case AUDIO_S16SYS:
return AudioDecoder::Format::S16;
case AUDIO_S32:
return AudioDecoder::Format::S32;
case AUDIO_F32:
return AudioDecoder::Format::F32;
default:
Output::Warning("Couldn't find GenericAudio format for {:#x}", format);
assert(false);
}

return (AudioDecoder::Format)-1;
}

Sdl2Audio::Sdl2Audio(const Game_ConfigAudio& cfg) :
GenericAudio(cfg)
{
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
Output::Warning("Couldn't init audio: {}", SDL_GetError());
return;
}

#ifdef EMSCRIPTEN
// Get preferred sample rate from Browser (-> OS)
const int frequency = EM_ASM_INT_V({
var context;
try {
context = new AudioContext();
} catch (e) {
context = new webkitAudioContext();
}
return context.sampleRate;
});
#else
const int frequency = 44100;
#endif

SDL_AudioSpec want = {};
SDL_AudioSpec have = {};
want.freq = frequency;
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = 2048;
want.callback = sdl_audio_callback;
want.userdata = this;

audio_dev_id = SDL_OpenAudioDevice(nullptr, 0, &want, &have, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
bool init_success = audio_dev_id > 0;

if (!init_success) {
Output::Warning("Couldn't open audio: {}", SDL_GetError());
return;
}

SetFormat(have.freq, sdl_format_to_format(have.format), have.channels);

// Start Audio
SDL_PauseAudioDevice(audio_dev_id, 0);
}

Sdl2Audio::~Sdl2Audio() {
SDL_CloseAudioDevice(audio_dev_id);
}

void Sdl2Audio::LockMutex() const {
SDL_LockAudioDevice(audio_dev_id);
}

void Sdl2Audio::UnlockMutex() const {
SDL_UnlockAudioDevice(audio_dev_id);
}

#endif
32 changes: 32 additions & 0 deletions src/platform/sdl/sdl2_audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* This file is part of EasyRPG Player.
*
* EasyRPG Player is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EasyRPG Player is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef EP_AUDIO_SDL2_H
#define EP_AUDIO_SDL2_H

#include "audio_generic.h"

class Sdl2Audio : public GenericAudio {
public:
Sdl2Audio(const Game_ConfigAudio& cfg);
~Sdl2Audio();

void LockMutex() const override;
void UnlockMutex() const override;
};

#endif
8 changes: 4 additions & 4 deletions src/platform/sdl/sdl2_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
# if AUDIO_AESND
# include "platform/wii/audio.h"
# else
# include "sdl_audio.h"
# include "sdl2_audio.h"
# endif

AudioInterface& Sdl2Ui::GetAudio() {
Expand Down Expand Up @@ -205,7 +205,7 @@ Sdl2Ui::Sdl2Ui(long width, long height, const Game_Config& cfg) : BaseUi(cfg)
# ifdef AUDIO_AESND
audio_ = std::make_unique<WiiAudio>(cfg.audio);
# else
audio_ = std::make_unique<SdlAudio>(cfg.audio);
audio_ = std::make_unique<Sdl2Audio>(cfg.audio);
# endif
#endif
}
Expand Down Expand Up @@ -1269,7 +1269,7 @@ void Sdl2Ui::vGetConfig(Game_ConfigVideo& cfg) const {
#ifdef EMSCRIPTEN
cfg.renderer.Lock("SDL2 (Software, Emscripten)");
#elif defined(__wii__)
cfg.renderer.Lock("SDL2 (Software, Wii)");
cfg.renderer.Lock("SDL2 (Software, Wii)");
#elif defined(__WIIU__)
cfg.renderer.Lock("SDL2 (Software, Wii U)");
#else
Expand Down Expand Up @@ -1304,7 +1304,7 @@ void Sdl2Ui::vGetConfig(Game_ConfigVideo& cfg) const {
cfg.pause_when_focus_lost.Lock(false);
cfg.pause_when_focus_lost.SetOptionVisible(false);
#elif defined(__wii__)
cfg.fullscreen.SetOptionVisible(false);
cfg.fullscreen.SetOptionVisible(false);
#elif defined(__WIIU__)
// Only makes the screen flicker
cfg.fullscreen.SetOptionVisible(false);
Expand Down
Loading

0 comments on commit 13e106e

Please sign in to comment.