First pass at converting to SDL3. Mostly still broken in several ways:

- only works in Linux
- sound, debugger and joystick not working (compiled out)
- QisBlitter not working (issues with render targets)
- adaptable refresh not working (not converted, and unable to test)
- text events not working (so no input in UI textboxes, etc)
- not entirely optimized
- probably some other stuff.

It does create a launcher and selecting a ROM works.  Toggling fullscreen
also works.
This commit is contained in:
Stephen Anthony 2025-05-15 15:52:37 -02:30
parent c217990d6d
commit c02aa1ea0a
26 changed files with 488 additions and 432 deletions

26
configure vendored
View File

@ -6,7 +6,7 @@
# * command line options to... # * command line options to...
# - override the host settings (for cross compiles # - override the host settings (for cross compiles
# - whether to do a debug build (with -g) or an optimized build (-O3 etc.) # - whether to do a debug build (with -g) or an optimized build (-O3 etc.)
# * detect whether the chosen backend is available (e.g. call sdl2-config) # * detect whether the chosen backend is available
# * .... # * ....
@ -54,7 +54,6 @@ _rm_rec="$_rm -r"
_zip="zip -q" _zip="zip -q"
_cp=cp _cp=cp
_windowspath="" _windowspath=""
_sdlconfig=sdl2-config
_sdlpath="$PATH" _sdlpath="$PATH"
_prefix=/usr/local _prefix=/usr/local
@ -817,8 +816,8 @@ fi
# #
# Now, add the appropriate defines/libraries/headers # Now, add the appropriate defines/libraries/headers
# #
echo #echo
find_sdlconfig #find_sdlconfig
SRC="src" SRC="src"
SRC_OS="$SRC/os" SRC_OS="$SRC/os"
@ -845,15 +844,18 @@ HTTP_LIB="$SRC_LIB/httplib"
INCLUDES="-I$CORE -I$COMMON -I$TV -I$TIA -I$TIA_FRAME_MANAGER -I$ELF -I$JSON -I$SQLITE_REPO" INCLUDES="-I$CORE -I$COMMON -I$TV -I$TIA -I$TIA_FRAME_MANAGER -I$ELF -I$JSON -I$SQLITE_REPO"
INCLUDES="$INCLUDES `$_sdlconfig --cflags`" #INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
if test "$_build_static" = yes ; then #if test "$_build_static" = yes ; then
_sdl_conf_libs="--static-libs" # _sdl_conf_libs="--static-libs"
LDFLAGS="-static $LDFLAGS" # LDFLAGS="-static $LDFLAGS"
else #else
_sdl_conf_libs="--libs" # _sdl_conf_libs="--libs"
fi #fi
#if test "$_libpng" = yes ; then #FIXME:
LIBS="$LIBS `$_pkg_config --libs sdl3`"
#fi
LIBS="$LIBS `$_sdlconfig $_sdl_conf_libs`"
LD=$CXX LD=$CXX
case $_host_os in case $_host_os in

View File

@ -30,15 +30,19 @@ EventHandlerSDL::EventHandlerSDL(OSystem& osystem)
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
{ {
ostringstream buf; ostringstream buf;
#if 0 //FIXME: come back to this
myQwertz = int{'y'} == static_cast<int> myQwertz = int{'y'} == static_cast<int>
(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(KBDK_Z))); (SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(KBDK_Z)));
#else
myQwertz = false;
#endif
buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY"); buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY");
Logger::debug(buf.view()); Logger::debug(buf.view());
} }
#endif #endif
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) if(!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
{ {
ostringstream buf; ostringstream buf;
buf << "ERROR: Couldn't initialize SDL joystick support: " buf << "ERROR: Couldn't initialize SDL joystick support: "
@ -63,12 +67,14 @@ EventHandlerSDL::~EventHandlerSDL()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandlerSDL::enableTextEvents(bool enable) void EventHandlerSDL::enableTextEvents(bool enable)
{ {
#if 0 // FIXME: needs a window ptr; refactor to pass this into the method
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
if(enable) if(enable)
SDL_StartTextInput(); SDL_StartTextInput();
else else
SDL_StopTextInput(); SDL_StopTextInput();
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -98,31 +104,31 @@ void EventHandlerSDL::pollEvent()
switch(myEvent.type) switch(myEvent.type)
{ {
// keyboard events // keyboard events
case SDL_KEYUP: case SDL_EVENT_KEY_UP:
case SDL_KEYDOWN: case SDL_EVENT_KEY_DOWN:
{ {
handleKeyEvent(static_cast<StellaKey>(myEvent.key.keysym.scancode), handleKeyEvent(static_cast<StellaKey>(myEvent.key.scancode),
static_cast<StellaMod>(myEvent.key.keysym.mod), static_cast<StellaMod>(myEvent.key.mod),
myEvent.key.type == SDL_KEYDOWN, myEvent.type == SDL_EVENT_KEY_DOWN,
myEvent.key.repeat); myEvent.key.repeat);
break; break;
} }
case SDL_TEXTINPUT: case SDL_EVENT_TEXT_INPUT:
{ {
handleTextEvent(*(myEvent.text.text)); handleTextEvent(*(myEvent.text.text));
break; break;
} }
case SDL_MOUSEMOTION: case SDL_EVENT_MOUSE_MOTION:
{ {
handleMouseMotionEvent(myEvent.motion.x, myEvent.motion.y, handleMouseMotionEvent(myEvent.motion.x, myEvent.motion.y,
myEvent.motion.xrel, myEvent.motion.yrel); myEvent.motion.xrel, myEvent.motion.yrel);
break; break;
} }
case SDL_MOUSEBUTTONDOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_MOUSEBUTTONUP: case SDL_EVENT_MOUSE_BUTTON_UP:
{ {
// ToDo: check support of more buttons and double-click // ToDo: check support of more buttons and double-click
MouseButton b{MouseButton::NONE}; MouseButton b{MouseButton::NONE};
@ -140,19 +146,23 @@ void EventHandlerSDL::pollEvent()
default: default:
break; break;
} }
handleMouseButtonEvent(b, myEvent.button.type == SDL_MOUSEBUTTONDOWN, handleMouseButtonEvent(b, myEvent.button.type == SDL_EVENT_MOUSE_BUTTON_DOWN,
myEvent.button.x, myEvent.button.y); myEvent.button.x, myEvent.button.y);
break; break;
} }
case SDL_MOUSEWHEEL: case SDL_EVENT_MOUSE_WHEEL:
{ {
int x{0}, y{0}; // TODO: SDL now uses float for mouse coords, but the core still
// uses int throughout; maybe this is sufficient?
float x{0.F}, y{0.F};
SDL_GetMouseState(&x, &y); // we need mouse position too SDL_GetMouseState(&x, &y); // we need mouse position too
if(myEvent.wheel.y < 0) if(myEvent.wheel.y < 0)
handleMouseButtonEvent(MouseButton::WHEELDOWN, true, x, y); handleMouseButtonEvent(MouseButton::WHEELDOWN, true,
static_cast<int>(x), static_cast<int>(y));
else if(myEvent.wheel.y > 0) else if(myEvent.wheel.y > 0)
handleMouseButtonEvent(MouseButton::WHEELUP, true, x, y); handleMouseButtonEvent(MouseButton::WHEELUP, true,
static_cast<int>(x), static_cast<int>(y));
break; break;
} }
@ -202,57 +212,50 @@ void EventHandlerSDL::pollEvent()
} }
#endif #endif
case SDL_QUIT: case SDL_EVENT_QUIT:
{ {
handleEvent(Event::Quit); handleEvent(Event::Quit);
break; // SDL_QUIT break;
} }
case SDL_WINDOWEVENT: case SDL_EVENT_WINDOW_SHOWN:
switch(myEvent.window.event) handleSystemEvent(SystemEvent::WINDOW_SHOWN);
{ break;
case SDL_WINDOWEVENT_SHOWN: case SDL_EVENT_WINDOW_HIDDEN:
handleSystemEvent(SystemEvent::WINDOW_SHOWN); handleSystemEvent(SystemEvent::WINDOW_HIDDEN);
break; break;
case SDL_WINDOWEVENT_HIDDEN: case SDL_EVENT_WINDOW_EXPOSED:
handleSystemEvent(SystemEvent::WINDOW_HIDDEN); handleSystemEvent(SystemEvent::WINDOW_EXPOSED);
break; break;
case SDL_WINDOWEVENT_EXPOSED: case SDL_EVENT_WINDOW_MOVED:
handleSystemEvent(SystemEvent::WINDOW_EXPOSED); handleSystemEvent(SystemEvent::WINDOW_MOVED,
break; myEvent.window.data1, myEvent.window.data1);
case SDL_WINDOWEVENT_MOVED: break;
handleSystemEvent(SystemEvent::WINDOW_MOVED, case SDL_EVENT_WINDOW_RESIZED:
myEvent.window.data1, myEvent.window.data1); handleSystemEvent(SystemEvent::WINDOW_RESIZED,
break; myEvent.window.data1, myEvent.window.data1);
case SDL_WINDOWEVENT_RESIZED: break;
handleSystemEvent(SystemEvent::WINDOW_RESIZED, case SDL_EVENT_WINDOW_MINIMIZED:
myEvent.window.data1, myEvent.window.data1); handleSystemEvent(SystemEvent::WINDOW_MINIMIZED);
break; break;
case SDL_WINDOWEVENT_MINIMIZED: case SDL_EVENT_WINDOW_MAXIMIZED:
handleSystemEvent(SystemEvent::WINDOW_MINIMIZED); handleSystemEvent(SystemEvent::WINDOW_MAXIMIZED);
break; break;
case SDL_WINDOWEVENT_MAXIMIZED: case SDL_EVENT_WINDOW_RESTORED:
handleSystemEvent(SystemEvent::WINDOW_MAXIMIZED); handleSystemEvent(SystemEvent::WINDOW_RESTORED);
break; break;
case SDL_WINDOWEVENT_RESTORED: case SDL_EVENT_WINDOW_MOUSE_ENTER:
handleSystemEvent(SystemEvent::WINDOW_RESTORED); handleSystemEvent(SystemEvent::WINDOW_ENTER);
break; break;
case SDL_WINDOWEVENT_ENTER: case SDL_EVENT_WINDOW_MOUSE_LEAVE:
handleSystemEvent(SystemEvent::WINDOW_ENTER); handleSystemEvent(SystemEvent::WINDOW_LEAVE);
break; break;
case SDL_WINDOWEVENT_LEAVE: case SDL_EVENT_WINDOW_FOCUS_GAINED:
handleSystemEvent(SystemEvent::WINDOW_LEAVE); handleSystemEvent(SystemEvent::WINDOW_FOCUS_GAINED);
break; break;
case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_LOST:
handleSystemEvent(SystemEvent::WINDOW_FOCUS_GAINED); handleSystemEvent(SystemEvent::WINDOW_FOCUS_LOST);
break; break;
case SDL_WINDOWEVENT_FOCUS_LOST:
handleSystemEvent(SystemEvent::WINDOW_FOCUS_LOST);
break;
default:
break;
}
break; // SDL_WINDOWEVENT
default: default:
break; break;
@ -260,13 +263,14 @@ void EventHandlerSDL::pollEvent()
} }
} }
#ifdef JOYSTICK_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL::JoystickSDL::JoystickSDL(int idx) EventHandlerSDL::JoystickSDL::JoystickSDL(int idx)
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
// NOLINTNEXTLINE: we want to initialize here, not in the member list // NOLINTNEXTLINE: we want to initialize here, not in the member list
myStick = SDL_JoystickOpen(idx); myStick = SDL_OpenJoystick(idx);
if(myStick) if(myStick)
{ {
// In Windows, all XBox controllers using the XInput API seem to name // In Windows, all XBox controllers using the XInput API seem to name
@ -274,13 +278,15 @@ EventHandlerSDL::JoystickSDL::JoystickSDL(int idx)
// it also appends " #x", where x seems to vary. Obviously this wreaks // it also appends " #x", where x seems to vary. Obviously this wreaks
// havoc with the idea that a joystick will always have the same name. // havoc with the idea that a joystick will always have the same name.
// So we truncate the number. // So we truncate the number.
const char* const sdlname = SDL_JoystickName(myStick); const char* const sdlname = SDL_GetJoystickName(myStick);
const string& desc = BSPF::startsWithIgnoreCase(sdlname, "XInput Controller") const string& desc = BSPF::startsWithIgnoreCase(sdlname, "XInput Controller")
? "XInput Controller" : sdlname; ? "XInput Controller" : sdlname;
initialize(SDL_JoystickInstanceID(myStick), desc, initialize(SDL_GetJoystickID(myStick), desc,
SDL_JoystickNumAxes(myStick), SDL_JoystickNumButtons(myStick), SDL_GetNumJoystickAxes(myStick),
SDL_JoystickNumHats(myStick), SDL_JoystickNumBalls(myStick)); SDL_GetNumJoystickButtons(myStick),
SDL_GetNumJoystickHats(myStick),
SDL_GetNumJoystickBalls(myStick));
} }
} }
@ -292,3 +298,4 @@ EventHandlerSDL::JoystickSDL::~JoystickSDL()
if(SDL_WasInit(SDL_INIT_JOYSTICK) && myStick) if(SDL_WasInit(SDL_INIT_JOYSTICK) && myStick)
SDL_JoystickClose(myStick); SDL_JoystickClose(myStick);
} }
#endif

View File

@ -58,6 +58,7 @@ class EventHandlerSDL : public EventHandler
private: private:
SDL_Event myEvent{0}; SDL_Event myEvent{0};
#ifdef JOYSTICK_SUPPORT
// A thin wrapper around a basic PhysicalJoystick, holding the pointer to // A thin wrapper around a basic PhysicalJoystick, holding the pointer to
// the underlying SDL joystick device. // the underlying SDL joystick device.
class JoystickSDL : public PhysicalJoystick class JoystickSDL : public PhysicalJoystick
@ -77,6 +78,7 @@ class EventHandlerSDL : public EventHandler
JoystickSDL& operator=(const JoystickSDL&) = delete; JoystickSDL& operator=(const JoystickSDL&) = delete;
JoystickSDL& operator=(JoystickSDL&&) = delete; JoystickSDL& operator=(JoystickSDL&&) = delete;
}; };
#endif
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported

View File

@ -35,7 +35,7 @@ FBBackendSDL::FBBackendSDL(OSystem& osystem)
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
// Initialize SDL context // Initialize SDL context
if(SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) if(!SDL_InitSubSystem(SDL_INIT_VIDEO))
{ {
ostringstream buf; ostringstream buf;
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError(); buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError();
@ -47,7 +47,7 @@ FBBackendSDL::FBBackendSDL(OSystem& osystem)
// It's done this way (vs directly accessing a FBSurfaceSDL object) // It's done this way (vs directly accessing a FBSurfaceSDL object)
// since the structure may be needed before any FBSurface's have // since the structure may be needed before any FBSurface's have
// been created // been created
myPixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888); myPixelFormat = SDL_GetPixelFormatDetails(SDL_PIXELFORMAT_ARGB8888);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -55,8 +55,6 @@ FBBackendSDL::~FBBackendSDL()
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_FreeFormat(myPixelFormat);
if(myRenderer) if(myRenderer)
{ {
SDL_DestroyRenderer(myRenderer); SDL_DestroyRenderer(myRenderer);
@ -69,7 +67,7 @@ FBBackendSDL::~FBBackendSDL()
SDL_DestroyWindow(myWindow); SDL_DestroyWindow(myWindow);
myWindow = nullptr; myWindow = nullptr;
} }
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER); SDL_QuitSubSystem(SDL_INIT_VIDEO);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -80,15 +78,27 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
// Get number of displays (for most systems, this will be '1') // Get number of displays (for most systems, this will be '1')
myNumDisplays = SDL_GetNumVideoDisplays(); int count = 0;
SDL_DisplayID* displays = SDL_GetDisplays(&count);
if(displays && count > 0)
myNumDisplays = static_cast<uInt32>(count);
else
return;
// First get the maximum fullscreen desktop resolution // Get the maximum fullscreen and windowed desktop resolutions
SDL_DisplayMode display{}; for(uInt32 i = 0; i < myNumDisplays; ++i)
for(int i = 0; i < myNumDisplays; ++i)
{ {
SDL_GetDesktopDisplayMode(i, &display); // Fullscreen mode
fullscreenRes.emplace_back(display.w, display.h); const SDL_DisplayMode* fsmode = SDL_GetDesktopDisplayMode(displays[i]);
fullscreenRes.emplace_back(fsmode->w, fsmode->h);
// Windowed mode
SDL_Rect r{};
if(SDL_GetDisplayUsableBounds(displays[i], &r))
windowedRes.emplace_back(r.w, r.h);
#if 0 //FIXME: debug code, not yet converted to SDL3
SDL_DisplayMode display{};
// evaluate fullscreen display modes (debug only for now) // evaluate fullscreen display modes (debug only for now)
const int numModes = SDL_GetNumDisplayModes(i); const int numModes = SDL_GetNumDisplayModes(i);
ostringstream s; ostringstream s;
@ -113,46 +123,21 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
s << " " << lastRes << ": "; s << " " << lastRes << ": ";
} }
s << mode.refresh_rate << "Hz"; s << mode.refresh_rate << "Hz";
if(mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate) if(mode.w == display.w && mode.h == display.h &&
mode.refresh_rate == display.refresh_rate)
s << "* "; s << "* ";
else else
s << " "; s << " ";
} }
Logger::debug(s.view()); Logger::debug(s.view());
#endif
} }
SDL_free(displays);
// Now get the maximum windowed desktop resolution
// Try to take into account taskbars, etc, if available
#if SDL_VERSION_ATLEAST(2,0,5)
// Take window title-bar into account; SDL_GetDisplayUsableBounds doesn't do that
int wTop = 0, wLeft = 0, wBottom = 0, wRight = 0;
SDL_Window* tmpWindow = SDL_CreateWindow("", 0, 0, 0, 0, SDL_WINDOW_HIDDEN);
if(tmpWindow != nullptr)
{
SDL_GetWindowBordersSize(tmpWindow, &wTop, &wLeft, &wBottom, &wRight);
SDL_DestroyWindow(tmpWindow);
}
SDL_Rect r{};
for(int i = 0; i < myNumDisplays; ++i)
{
// Display bounds minus dock
SDL_GetDisplayUsableBounds(i, &r); // Requires SDL-2.0.5 or higher
r.h -= (wTop + wBottom);
windowedRes.emplace_back(r.w, r.h);
}
#else
for(int i = 0; i < myNumDisplays; ++i)
{
SDL_GetDesktopDisplayMode(i, &display);
windowedRes.emplace_back(display.w, display.h);
}
#endif
struct RenderName struct RenderName
{ {
string sdlName; string_view sdlName;
string stellaName; string_view stellaName;
}; };
// Create name map for all currently known SDL renderers // Create name map for all currently known SDL renderers
static const std::array<RenderName, 8> RENDERER_NAMES = {{ static const std::array<RenderName, 8> RENDERER_NAMES = {{
@ -169,22 +154,22 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
const int numDrivers = SDL_GetNumRenderDrivers(); const int numDrivers = SDL_GetNumRenderDrivers();
for(int i = 0; i < numDrivers; ++i) for(int i = 0; i < numDrivers; ++i)
{ {
SDL_RendererInfo info; const char* const rendername = SDL_GetRenderDriver(i);
if(SDL_GetRenderDriverInfo(i, &info) == 0) if(rendername)
{ {
// Map SDL names into nicer Stella names (if available) // Map SDL names into nicer Stella names (if available)
bool found = false; bool found = false;
for(const auto& render: RENDERER_NAMES) for(const auto& render: RENDERER_NAMES)
{ {
if(render.sdlName == info.name) if(render.sdlName == rendername)
{ {
VarList::push_back(renderers, render.stellaName, info.name); VarList::push_back(renderers, render.stellaName, rendername);
found = true; found = true;
break; break;
} }
} }
if(!found) if(!found)
VarList::push_back(renderers, info.name, info.name); VarList::push_back(renderers, rendername, rendername);
} }
} }
} }
@ -194,8 +179,7 @@ bool FBBackendSDL::isCurrentWindowPositioned() const
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
return !myCenter return myWindow && !fullScreen() && !myCenter;
&& myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -210,11 +194,11 @@ Common::Point FBBackendSDL::getCurrentWindowPos() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 FBBackendSDL::getCurrentDisplayIndex() const uInt32 FBBackendSDL::getCurrentDisplayID() const
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
return SDL_GetWindowDisplayIndex(myWindow); return SDL_GetDisplayForWindow(myWindow);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -223,13 +207,13 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
// cerr << mode << '\n';
// If not initialized by this point, then immediately fail // If not initialized by this point, then immediately fail
if(SDL_WasInit(SDL_INIT_VIDEO) == 0) if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
return false; return false;
const bool fullScreen = mode.fsIndex != -1; const uInt32 displayIndex = std::min<uInt32>(myNumDisplays, winIdx);
const Int32 displayIndex = std::min(myNumDisplays - 1, winIdx);
int posX = 0, posY = 0; int posX = 0, posY = 0;
myCenter = myOSystem.settings().getBool("center"); myCenter = myOSystem.settings().getBool("center");
@ -259,11 +243,12 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
posY = BSPF::clamp(posY, y0 + 50, y1 - 50); posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
} }
#if 0 // FIXME: adaptable
#ifdef ADAPTABLE_REFRESH_SUPPORT #ifdef ADAPTABLE_REFRESH_SUPPORT
SDL_DisplayMode adaptedSdlMode{}; SDL_DisplayMode adaptedSdlMode{};
const int gameRefreshRate = const int gameRefreshRate =
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0; myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
const bool shouldAdapt = fullScreen const bool shouldAdapt = mode.fullscreen
&& myOSystem.settings().getBool("tia.fs_refresh") && myOSystem.settings().getBool("tia.fs_refresh")
&& gameRefreshRate && gameRefreshRate
// take care of 59.94 Hz // take care of 59.94 Hz
@ -274,21 +259,19 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
#else #else
const bool adaptRefresh = false; const bool adaptRefresh = false;
#endif #endif
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI #endif
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN :
SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
// Don't re-create the window if its display and size hasn't changed, // Don't re-create the window if its display and size hasn't changed,
// as it's not necessary, and causes flashing in fullscreen mode // as it's not necessary, and causes flashing in fullscreen mode
if(myWindow) if(myWindow)
{ {
const int d = SDL_GetWindowDisplayIndex(myWindow); const uInt32 d = getCurrentDisplayID();
int w{0}, h{0}; int w{0}, h{0};
SDL_GetWindowSize(myWindow, &w, &h); SDL_GetWindowSize(myWindow, &w, &h);
if(d != displayIndex || if(d != displayIndex ||
std::cmp_not_equal(w, mode.screenS.w) || std::cmp_not_equal(w, mode.screenS.w) ||
std::cmp_not_equal(h, mode.screenS.h) || adaptRefresh) std::cmp_not_equal(h, mode.screenS.h) /*|| adaptRefresh*/) //FIXME
{ {
// Renderer has to be destroyed *before* the window gets destroyed to avoid memory leaks // Renderer has to be destroyed *before* the window gets destroyed to avoid memory leaks
SDL_DestroyRenderer(myRenderer); SDL_DestroyRenderer(myRenderer);
@ -306,8 +289,27 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
} }
else else
{ {
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY, // Re-create with new properties
mode.screenS.w, mode.screenS.h, flags); const SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING,
myScreenTitle.c_str());
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, posX);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, posY);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER,
mode.screenS.w);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER,
mode.screenS.h);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN,
true);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
mode.fullscreen);
SDL_SetBooleanProperty(props,
SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN,
true);
// FIXME: adaptable (does it need a property??)
myWindow = SDL_CreateWindowWithProperties(props);
SDL_DestroyProperties(props);
if(myWindow == nullptr) if(myWindow == nullptr)
{ {
const string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError()); const string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
@ -318,6 +320,7 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
setWindowIcon(); setWindowIcon();
} }
#if 0 // FIXME: adaptable
#ifdef ADAPTABLE_REFRESH_SUPPORT #ifdef ADAPTABLE_REFRESH_SUPPORT
if(adaptRefresh) if(adaptRefresh)
{ {
@ -339,15 +342,26 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
cerr << setSdlMode.refresh_rate << "Hz\n"; cerr << setSdlMode.refresh_rate << "Hz\n";
} }
} }
#endif
#endif #endif
return createRenderer(); const bool result = createRenderer();
if(result)
{
// TODO: Checking for fullscreen status later returns invalid results,
// so we check and cache it here
myIsFullscreen = SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN;
SDL_ShowWindow(myWindow);
}
return result;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex, bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
SDL_DisplayMode& adaptedSdlMode) SDL_DisplayMode& adaptedSdlMode)
{ {
#if 0 // FIXME: adaptable
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_DisplayMode sdlMode; SDL_DisplayMode sdlMode;
@ -402,6 +416,8 @@ bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
// Only change if the display supports a better refresh rate // Only change if the display supports a better refresh rate
return adapt; return adapt;
#endif
return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -411,32 +427,40 @@ bool FBBackendSDL::createRenderer()
// A new renderer is only created when necessary: // A new renderer is only created when necessary:
// - no renderer existing // - no renderer existing
// - different renderer flags
// - different renderer name // - different renderer name
// - different renderer vsync
const bool enableVSync = myOSystem.settings().getBool("vsync") &&
!myOSystem.settings().getBool("turbo");
const string& video = myOSystem.settings().getString("video");
bool recreate = myRenderer == nullptr; bool recreate = myRenderer == nullptr;
uInt32 renderFlags = SDL_RENDERER_ACCELERATED; if(myRenderer)
const string& video = myOSystem.settings().getString("video"); // Render hint {
SDL_RendererInfo renderInfo{}; recreate = recreate || video != SDL_GetRendererName(myRenderer);
if(myOSystem.settings().getBool("vsync") SDL_PropertiesID props = SDL_GetRendererProperties(myRenderer);
&& !myOSystem.settings().getBool("turbo")) // V'synced blits option const bool currentVSync = SDL_GetNumberProperty(props,
renderFlags |= SDL_RENDERER_PRESENTVSYNC; SDL_PROP_RENDERER_VSYNC_NUMBER, 0) != 0;
recreate = recreate || currentVSync != enableVSync;
// check renderer flags and name }
recreate |= (SDL_GetRendererInfo(myRenderer, &renderInfo) != 0)
|| ((renderInfo.flags & (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != renderFlags
|| (video != renderInfo.name));
if(recreate) if(recreate)
{ {
//cerr << "Create new renderer for buffer type #" << int(myBufferType) << '\n';
if(myRenderer) if(myRenderer)
SDL_DestroyRenderer(myRenderer); SDL_DestroyRenderer(myRenderer);
// Re-create with new properties
SDL_PropertiesID props = SDL_CreateProperties();
if(!video.empty()) if(!video.empty())
SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str()); SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING,
video.c_str());
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER,
enableVSync ? 1 : 0);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER,
myWindow);
myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags); myRenderer = SDL_CreateRendererWithProperties(props);
SDL_DestroyProperties(props);
detectFeatures(); detectFeatures();
determineDimensions(); determineDimensions();
@ -450,10 +474,9 @@ bool FBBackendSDL::createRenderer()
} }
clear(); clear();
SDL_RendererInfo renderinfo; const char* const detectedvideo = SDL_GetRendererName(myRenderer);
if(detectedvideo)
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0) myOSystem.settings().setValue("video", detectedvideo);
myOSystem.settings().setValue("video", renderinfo.name);
return true; return true;
} }
@ -466,7 +489,7 @@ void FBBackendSDL::setTitle(string_view title)
myScreenTitle = title; myScreenTitle = title;
if(myWindow) if(myWindow)
SDL_SetWindowTitle(myWindow, string{title}.c_str()); SDL_SetWindowTitle(myWindow, myScreenTitle.c_str());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -476,16 +499,21 @@ string FBBackendSDL::about() const
ostringstream out; ostringstream out;
out << "Video system: " << SDL_GetCurrentVideoDriver() << '\n'; out << "Video system: " << SDL_GetCurrentVideoDriver() << '\n';
SDL_RendererInfo info;
if(SDL_GetRendererInfo(myRenderer, &info) >= 0) SDL_PropertiesID props = SDL_GetRendererProperties(myRenderer);
if(props != 0)
{ {
out << " Renderer: " << info.name << '\n'; out << " Renderer: "
if(info.max_texture_width > 0 && info.max_texture_height > 0) << SDL_GetStringProperty(props, SDL_PROP_RENDERER_NAME_STRING, "")
out << " Max texture: " << info.max_texture_width << "x" << '\n';
<< info.max_texture_height << '\n'; const int maxTexSize =
SDL_GetNumberProperty(props, SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 0);
if(maxTexSize > 0)
out << " Max texture: " << maxTexSize << "x" << maxTexSize << '\n';
const bool usingVSync = SDL_GetNumberProperty(props,
SDL_PROP_RENDERER_VSYNC_NUMBER, 0) != 0;
out << " Flags: " out << " Flags: "
<< ((info.flags & SDL_RENDERER_PRESENTVSYNC) ? "+" : "-") << "vsync, " << (usingVSync ? "+" : "-") << "vsync"
<< ((info.flags & SDL_RENDERER_ACCELERATED) ? "+" : "-") << "accel"
<< '\n'; << '\n';
} }
return out.str(); return out.str();
@ -496,7 +524,8 @@ void FBBackendSDL::showCursor(bool show)
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE); if(show) SDL_ShowCursor();
else SDL_HideCursor();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -504,7 +533,7 @@ void FBBackendSDL::grabMouse(bool grab)
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE); SDL_SetWindowMouseGrab(myWindow, grab);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -513,7 +542,7 @@ bool FBBackendSDL::fullScreen() const
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
#ifdef WINDOWED_SUPPORT #ifdef WINDOWED_SUPPORT
return SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP; return myIsFullscreen; // TODO: should query SDL directly
#else #else
return true; return true;
#endif #endif
@ -524,11 +553,11 @@ int FBBackendSDL::refreshRate() const
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
const uInt32 displayIndex = SDL_GetWindowDisplayIndex(myWindow); const SDL_DisplayID displayID = getCurrentDisplayID();
SDL_DisplayMode sdlMode; const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) == 0) if(mode)
return sdlMode.refresh_rate; return mode->refresh_rate;
if(myWindow != nullptr) if(myWindow != nullptr)
Logger::error("Could not retrieve current display mode"); Logger::error("Could not retrieve current display mode");
@ -552,10 +581,10 @@ void FBBackendSDL::setWindowIcon()
#include "stella_icon.hxx" #include "stella_icon.hxx"
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(stella_icon, 32, 32, 32, SDL_Surface* surface =
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000); SDL_CreateSurfaceFrom(32, 32, SDL_PIXELFORMAT_ARGB8888, stella_icon, 32 * 4);
SDL_SetWindowIcon(myWindow, surface); SDL_SetWindowIcon(myWindow, surface);
SDL_FreeSurface(surface); SDL_DestroySurface(surface);
#endif #endif
} }
@ -575,6 +604,10 @@ unique_ptr<FBSurface> FBBackendSDL::createSurface(
void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch, void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
const Common::Rect& rect) const const Common::Rect& rect) const
{ {
// FIXME: this method needs to be refactored to return an FBSurface,
// since SDL_RenderReadPixels now returns an SDL_Surface
// PNGLibrary is the only user of this; that will need to be refactored too
#if 0
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_Rect r; SDL_Rect r;
@ -582,6 +615,7 @@ void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
r.w = rect.w(); r.h = rect.h(); r.w = rect.w(); r.h = rect.h();
SDL_RenderReadPixels(myRenderer, &r, 0, buffer, static_cast<int>(pitch)); SDL_RenderReadPixels(myRenderer, &r, 0, buffer, static_cast<int>(pitch));
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -609,25 +643,9 @@ bool FBBackendSDL::detectRenderTargetSupport()
if(myRenderer == nullptr) if(myRenderer == nullptr)
return false; return false;
SDL_RendererInfo info; // All texture modes except software support render targets
SDL_GetRendererInfo(myRenderer, &info); const char* const detectedvideo = SDL_GetRendererName(myRenderer);
return detectedvideo && !BSPF::equalsIgnoreCase(detectedvideo, "software");
if(!(info.flags & SDL_RENDERER_TARGETTEXTURE))
return false;
SDL_Texture* tex =
SDL_CreateTexture(myRenderer, myPixelFormat->format,
SDL_TEXTUREACCESS_TARGET, 16, 16);
if(!tex)
return false;
const int sdlError = SDL_SetRenderTarget(myRenderer, tex);
SDL_SetRenderTarget(myRenderer, nullptr);
SDL_DestroyTexture(tex);
return sdlError == 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -643,5 +661,5 @@ void FBBackendSDL::determineDimensions()
myRenderH = myWindowH; myRenderH = myWindowH;
} }
else else
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH); SDL_GetCurrentRenderOutputSize(myRenderer, &myRenderW, &myRenderH);
} }

View File

@ -55,7 +55,7 @@ class FBBackendSDL : public FBBackend
/** /**
Get the SDL pixel format. Get the SDL pixel format.
*/ */
const SDL_PixelFormat& pixelFormat() const { return *myPixelFormat; } const SDL_PixelFormatDetails& pixelFormat() const { return *myPixelFormat; }
/** /**
Does the renderer support render targets? Does the renderer support render targets?
@ -99,7 +99,7 @@ class FBBackendSDL : public FBBackend
@param b The blue component of the color @param b The blue component of the color
*/ */
FORCE_INLINE void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const override FORCE_INLINE void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const override
{ SDL_GetRGB(pixel, myPixelFormat, r, g, b); } { SDL_GetRGB(pixel, myPixelFormat, nullptr, r, g, b); }
/** /**
This method is called to retrieve the R/G/B/A data from the given pixel. This method is called to retrieve the R/G/B/A data from the given pixel.
@ -111,7 +111,7 @@ class FBBackendSDL : public FBBackend
@param a The alpha component of the color. @param a The alpha component of the color.
*/ */
FORCE_INLINE void getRGBA(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b, uInt8* a) const override FORCE_INLINE void getRGBA(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b, uInt8* a) const override
{ SDL_GetRGBA(pixel, myPixelFormat, r, g, b, a); } { SDL_GetRGBA(pixel, myPixelFormat, nullptr, r, g, b, a); }
/** /**
This method is called to map a given R/G/B triple to the screen palette. This method is called to map a given R/G/B triple to the screen palette.
@ -121,7 +121,7 @@ class FBBackendSDL : public FBBackend
@param b The blue component of the color. @param b The blue component of the color.
*/ */
uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override
{ return SDL_MapRGB(myPixelFormat, r, g, b); } { return SDL_MapRGB(myPixelFormat, nullptr, r, g, b); }
/** /**
This method is called to map a given R/G/B/A triple to the screen palette. This method is called to map a given R/G/B/A triple to the screen palette.
@ -132,7 +132,7 @@ class FBBackendSDL : public FBBackend
@param a The alpha component of the color. @param a The alpha component of the color.
*/ */
uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const override uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const override
{ return SDL_MapRGBA(myPixelFormat, r, g, b, a); } { return SDL_MapRGBA(myPixelFormat, nullptr, r, g, b, a); }
/** /**
This method is called to get a copy of the specified ARGB data from the This method is called to get a copy of the specified ARGB data from the
@ -167,10 +167,9 @@ class FBBackendSDL : public FBBackend
This method is called to query the video hardware for the index This method is called to query the video hardware for the index
of the display the current window is displayed on of the display the current window is displayed on
@return the current display index or a negative value if no @return the current display index or a 0 if no window is displayed
window is displayed
*/ */
Int32 getCurrentDisplayIndex() const override; uInt32 getCurrentDisplayID() const override;
/** /**
Clear the frame buffer. Clear the frame buffer.
@ -286,7 +285,14 @@ class FBBackendSDL : public FBBackend
SDL_Renderer* myRenderer{nullptr}; SDL_Renderer* myRenderer{nullptr};
// Used by mapRGB (when palettes are created) // Used by mapRGB (when palettes are created)
SDL_PixelFormat* myPixelFormat{nullptr}; const SDL_PixelFormatDetails* myPixelFormat{nullptr};
// Are we in fullscreen mode?
// There seem to be issues with creating the window and renderer separately,
// and doing so means we can't query the window for fullscreen status
// So we do it at window creation and cache the result
// TODO: Is this a bug in SDL?
bool myIsFullscreen{false};
// Center setting of current window // Center setting of current window
bool myCenter{false}; bool myCenter{false};
@ -298,7 +304,7 @@ class FBBackendSDL : public FBBackend
string myScreenTitle; string myScreenTitle;
// Number of displays // Number of displays
int myNumDisplays{1}; uInt32 myNumDisplays{0};
// Window and renderer dimensions // Window and renderer dimensions
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0}; int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};

View File

@ -59,7 +59,7 @@ FBSurfaceSDL::~FBSurfaceSDL()
if(mySurface) if(mySurface)
{ {
SDL_FreeSurface(mySurface); SDL_DestroySurface(mySurface);
mySurface = nullptr; mySurface = nullptr;
} }
} }
@ -75,7 +75,7 @@ void FBSurfaceSDL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId colo
tmp.y = y; tmp.y = y;
tmp.w = w; tmp.w = w;
tmp.h = h; tmp.h = h;
SDL_FillRect(mySurface, &tmp, myPalette[color]); SDL_FillSurfaceRect(mySurface, &tmp, myPalette[color]);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -183,7 +183,7 @@ void FBSurfaceSDL::invalidate()
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_FillRect(mySurface, nullptr, 0); SDL_FillSurfaceRect(mySurface, nullptr, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -199,7 +199,7 @@ void FBSurfaceSDL::invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
tmp.h = h; tmp.h = h;
// Note: Transparency has to be 0 to clear the rectangle foreground // Note: Transparency has to be 0 to clear the rectangle foreground
// without affecting the background display. // without affecting the background display.
SDL_FillRect(mySurface, &tmp, 0); SDL_FillSurfaceRect(mySurface, &tmp, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -214,7 +214,7 @@ void FBSurfaceSDL::resize(uInt32 width, uInt32 height)
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
if(mySurface) if(mySurface)
SDL_FreeSurface(mySurface); SDL_DestroySurface(mySurface);
// NOTE: Currently, a resize changes a 'static' surface to 'streaming' // NOTE: Currently, a resize changes a 'static' surface to 'streaming'
// No code currently does this, but we should at least check for it // No code currently does this, but we should at least check for it
@ -230,10 +230,8 @@ void FBSurfaceSDL::createSurface(uInt32 width, uInt32 height, const uInt32* data
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
// Create a surface in the same format as the parent GL class // Create a surface in the same format as the parent GL class
const SDL_PixelFormat& pf = myBackend.pixelFormat(); const SDL_PixelFormatDetails& pf = myBackend.pixelFormat();
mySurface = SDL_CreateSurface(width, height, pf.format);
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
//SDL_SetSurfaceBlendMode(mySurface, SDL_BLENDMODE_ADD); // default: SDL_BLENDMODE_BLEND //SDL_SetSurfaceBlendMode(mySurface, SDL_BLENDMODE_ADD); // default: SDL_BLENDMODE_BLEND
// We start out with the src and dst rectangles containing the same // We start out with the src and dst rectangles containing the same
@ -246,7 +244,7 @@ void FBSurfaceSDL::createSurface(uInt32 width, uInt32 height, const uInt32* data
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
// These *must* be set for the parent class // These *must* be set for the parent class
myPixels = static_cast<uInt32*>(mySurface->pixels); myPixels = static_cast<uInt32*>(mySurface->pixels);
myPitch = mySurface->pitch / pf.BytesPerPixel; myPitch = mySurface->pitch / pf.bytes_per_pixel;
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
myIsStatic = data != nullptr; myIsStatic = data != nullptr;

View File

@ -43,8 +43,7 @@ namespace {
StellaMod::KBDM_RGUI, StellaMod::KBDM_RGUI,
StellaMod::KBDM_NUM, StellaMod::KBDM_NUM,
StellaMod::KBDM_CAPS, StellaMod::KBDM_CAPS,
StellaMod::KBDM_MODE, StellaMod::KBDM_MODE
StellaMod::KBDM_RESERVED
}) { }) {
if((mask & mod) != mod) continue; if((mask & mod) != mod) continue;

View File

@ -78,10 +78,6 @@ class AudioSettings;
implementations for the various ports of Stella, and always returns a implementations for the various ports of Stella, and always returns a
valid object based on the specific port and restrictions on that port. valid object based on the specific port and restrictions on that port.
As of SDL2, this code is greatly simplified. However, it remains here
in case we ever have multiple backend implementations again (should
not be necessary since SDL2 covers this nicely).
@author Stephen Anthony @author Stephen Anthony
*/ */
class MediaFactory class MediaFactory
@ -181,15 +177,6 @@ class MediaFactory
#endif #endif
} }
static bool supportsURL()
{
#if defined(SDL_SUPPORT)
return SDLSupportsURL();
#else
return false;
#endif
}
static bool openURL(const string& url) static bool openURL(const string& url)
{ {
#if defined(SDL_SUPPORT) #if defined(SDL_SUPPORT)

View File

@ -33,48 +33,30 @@
#pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wreserved-identifier" #pragma clang diagnostic ignored "-Wreserved-identifier"
#pragma clang diagnostic ignored "-Wswitch-default" #pragma clang diagnostic ignored "-Wswitch-default"
#include <SDL.h> #include <SDL3/SDL.h>
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined(BSPF_WINDOWS) #elif defined(BSPF_WINDOWS)
#pragma warning(push, 0) #pragma warning(push, 0)
#include <SDL.h> #include <SDL3/SDL.h>
#pragma warning(pop) #pragma warning(pop)
#else #else
#include <SDL.h> #include <SDL3/SDL.h>
#endif #endif
/*
* Seems to be needed for ppc64le, doesn't hurt other archs
* Note that this is a problem in SDL2, which includes <altivec.h>
* https://bugzilla.redhat.com/show_bug.cgi?id=1419452
*/
#undef vector
#undef pixel
#undef bool
static inline string SDLVersion() static inline string SDLVersion()
{ {
ostringstream buf; ostringstream buf;
SDL_version ver; const int ver = SDL_GetVersion();
SDL_GetVersion(&ver); buf << "SDL "
buf << "SDL " << static_cast<int>(ver.major) << "." << static_cast<int>(ver.minor) << SDL_VERSIONNUM_MAJOR(ver) << "."
<< "." << static_cast<int>(ver.patch); << SDL_VERSIONNUM_MINOR(ver) << "."
<< SDL_VERSIONNUM_MICRO(ver);
return buf.str(); return buf.str();
} }
static inline bool SDLSupportsURL()
{
return SDL_VERSION_ATLEAST(2,0,14);
}
static inline bool SDLOpenURL(const string& url) static inline bool SDLOpenURL(const string& url)
{ {
#if SDL_VERSION_ATLEAST(2,0,14) return SDL_OpenURL(url.c_str());
return SDL_OpenURL(url.c_str()) == 0;
#else
cerr << "OpenURL requires at least SDL 2.0.14\n";
return false;
#endif
} }
#endif // SDL_LIB_HXX #endif // SDL_LIB_HXX

View File

@ -104,7 +104,7 @@ bool SoundSDL::openDevice()
SDL_AudioSpec desired; SDL_AudioSpec desired;
desired.freq = myAudioSettings.sampleRate(); desired.freq = myAudioSettings.sampleRate();
desired.format = AUDIO_F32SYS; desired.format = SDL_AUDIO_F32;
desired.channels = 2; desired.channels = 2;
desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize()); desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize());
desired.callback = callback; desired.callback = callback;
@ -218,7 +218,12 @@ bool SoundSDL::pause(bool enable)
const bool wasPaused = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED; const bool wasPaused = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED;
if(myIsInitializedFlag) if(myIsInitializedFlag)
{ {
SDL_PauseAudioDevice(myDevice, enable ? 1 : 0); if (enable ? 1 : 0) {
SDL_PauseAudioDevice(myDevice);
}
else {
SDL_ResumeAudioDevice(myDevice);
}
myWavHandler.pause(enable); myWavHandler.pause(enable);
} }
return wasPaused; return wasPaused;
@ -415,7 +420,7 @@ bool SoundSDL::WavHandlerSDL::play(
{ {
if(myBuffer) if(myBuffer)
{ {
SDL_FreeWAV(myBuffer); SDL_free(myBuffer);
myBuffer = nullptr; myBuffer = nullptr;
} }
SDL_zero(mySpec); SDL_zero(mySpec);
@ -457,7 +462,7 @@ void SoundSDL::WavHandlerSDL::stop()
// Clean up // Clean up
myRemaining = 0; myRemaining = 0;
SDL_CloseAudioDevice(myDevice); myDevice = 0; SDL_CloseAudioDevice(myDevice); myDevice = 0;
SDL_FreeWAV(myBuffer); myBuffer = nullptr; SDL_free(myBuffer); myBuffer = nullptr;
} }
if(myCvtBuffer) if(myCvtBuffer)
{ {
@ -537,7 +542,12 @@ SoundSDL::WavHandlerSDL::~WavHandlerSDL()
void SoundSDL::WavHandlerSDL::pause(bool state) const void SoundSDL::WavHandlerSDL::pause(bool state) const
{ {
if(myDevice) if(myDevice)
SDL_PauseAudioDevice(myDevice, state ? 1 : 0); if (state ? 1 : 0) {
SDL_PauseAudioDevice(myDevice);
}
else {
SDL_ResumeAudioDevice(myDevice);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -221,16 +221,16 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
KBDK_F23 = 114, KBDK_F23 = 114,
KBDK_F24 = 115, KBDK_F24 = 115,
KBDK_EXECUTE = 116, KBDK_EXECUTE = 116,
KBDK_HELP = 117, KBDK_HELP = 117, /**< AL Integrated Help Center */
KBDK_MENU = 118, KBDK_MENU = 118, /**< Menu (show menu) */
KBDK_SELECT = 119, KBDK_SELECT = 119,
KBDK_STOP = 120, KBDK_STOP = 120, /**< AC Stop */
KBDK_AGAIN = 121, /**< redo */ KBDK_AGAIN = 121, /**< AC Redo/Repeat */
KBDK_UNDO = 122, KBDK_UNDO = 122, /**< AC Undo */
KBDK_CUT = 123, KBDK_CUT = 123, /**< AC Cut */
KBDK_COPY = 124, KBDK_COPY = 124, /**< AC Copy */
KBDK_PASTE = 125, KBDK_PASTE = 125, /**< AC Paste */
KBDK_FIND = 126, KBDK_FIND = 126, /**< AC Find */
KBDK_MUTE = 127, KBDK_MUTE = 127,
KBDK_VOLUMEUP = 128, KBDK_VOLUMEUP = 128,
KBDK_VOLUMEDOWN = 129, KBDK_VOLUMEDOWN = 129,
@ -261,9 +261,9 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
KBDK_LANG8 = 151, /**< reserved */ KBDK_LANG8 = 151, /**< reserved */
KBDK_LANG9 = 152, /**< reserved */ KBDK_LANG9 = 152, /**< reserved */
KBDK_ALTERASE = 153, /**< Erase-Eaze */ KBDK_ALTERASE = 153, /**< Erase-Eaze */
KBDK_SYSREQ = 154, KBDK_SYSREQ = 154,
KBDK_CANCEL = 155, KBDK_CANCEL = 155, /**< AC Cancel */
KBDK_CLEAR = 156, KBDK_CLEAR = 156,
KBDK_PRIOR = 157, KBDK_PRIOR = 157,
KBDK_RETURN2 = 158, KBDK_RETURN2 = 158,
@ -330,10 +330,10 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
KBDK_RALT = 230, /**< alt gr, option */ KBDK_RALT = 230, /**< alt gr, option */
KBDK_RGUI = 231, /**< windows, command (apple), meta */ KBDK_RGUI = 231, /**< windows, command (apple), meta */
KBDK_MODE = 257, /**< ALT-GR(aph) key on non-American keyboards KBDK_MODE = 257, /**< I'm not sure if this is really not covered
* This is like pressing KBDK_RALT + KBDK_RCTRL * by any of the above, but since there's a
* on some keyboards * special SDL_KMOD_MODE for it I'm adding it here
*/ */
/* @} *//* Usage page 0x07 */ /* @} *//* Usage page 0x07 */
@ -341,77 +341,98 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
* \name Usage page 0x0C * \name Usage page 0x0C
* *
* These values are mapped from usage page 0x0C (USB consumer page). * These values are mapped from usage page 0x0C (USB consumer page).
*
* There are way more keys in the spec than we can represent in the
* current scancode range, so pick the ones that commonly come up in
* real world usage.
*/ */
/* @{ */ /* @{ */
KBDK_AUDIONEXT = 258, KBDK_SLEEP = 258, /**< Sleep */
KBDK_AUDIOPREV = 259, KBDK_WAKE = 259, /**< Wake */
KBDK_AUDIOSTOP = 260,
KBDK_AUDIOPLAY = 261, KBDK_CHANNEL_INCREMENT = 260, /**< Channel Increment */
KBDK_AUDIOMUTE = 262, KBDK_CHANNEL_DECREMENT = 261, /**< Channel Decrement */
KBDK_MEDIASELECT = 263,
KBDK_WWW = 264, KBDK_MEDIA_PLAY = 262, /**< Play */
KBDK_MAIL = 265, KBDK_MEDIA_PAUSE = 263, /**< Pause */
KBDK_CALCULATOR = 266, KBDK_MEDIA_RECORD = 264, /**< Record */
KBDK_COMPUTER = 267, KBDK_MEDIA_FAST_FORWARD = 265, /**< Fast Forward */
KBDK_AC_SEARCH = 268, KBDK_MEDIA_REWIND = 266, /**< Rewind */
KBDK_AC_HOME = 269, KBDK_MEDIA_NEXT_TRACK = 267, /**< Next Track */
KBDK_AC_BACK = 270, KBDK_MEDIA_PREVIOUS_TRACK = 268, /**< Previous Track */
KBDK_AC_FORWARD = 271, KBDK_MEDIA_STOP = 269, /**< Stop */
KBDK_AC_STOP = 272, KBDK_MEDIA_EJECT = 270, /**< Eject */
KBDK_AC_REFRESH = 273, KBDK_MEDIA_PLAY_PAUSE = 271, /**< Play / Pause */
KBDK_AC_BOOKMARKS = 274, KBDK_MEDIA_SELECT = 272, /* Media Select */
KBDK_AC_NEW = 273, /**< AC New */
KBDK_AC_OPEN = 274, /**< AC Open */
KBDK_AC_CLOSE = 275, /**< AC Close */
KBDK_AC_EXIT = 276, /**< AC Exit */
KBDK_AC_SAVE = 277, /**< AC Save */
KBDK_AC_PRINT = 278, /**< AC Print */
KBDK_AC_PROPERTIES = 279, /**< AC Properties */
KBDK_AC_SEARCH = 280, /**< AC Search */
KBDK_AC_HOME = 281, /**< AC Home */
KBDK_AC_BACK = 282, /**< AC Back */
KBDK_AC_FORWARD = 283, /**< AC Forward */
KBDK_AC_STOP = 284, /**< AC Stop */
KBDK_AC_REFRESH = 285, /**< AC Refresh */
KBDK_AC_BOOKMARKS = 286, /**< AC Bookmarks */
/* @} *//* Usage page 0x0C */ /* @} *//* Usage page 0x0C */
/** /**
* \name Walther keys * \name Mobile keys
* *
* These are values that Christian Walther added (for mac keyboard?). * These are values that are often used on mobile phones.
*/ */
/* @{ */ /* @{ */
KBDK_BRIGHTNESSDOWN = 275, KBDK_SOFTLEFT = 287, /**< Usually situated below the display on phones and
KBDK_BRIGHTNESSUP = 276, used as a multi-function feature key for selecting
KBDK_DISPLAYSWITCH = 277, /**< display mirroring/dual display a software defined function shown on the bottom left
switch, video mode switch */ of the display. */
KBDK_KBDILLUMTOGGLE = 278, KBDK_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
KBDK_KBDILLUMDOWN = 279, used as a multi-function feature key for selecting
KBDK_KBDILLUMUP = 280, a software defined function shown on the bottom right
KBDK_EJECT = 281, of the display. */
KBDK_SLEEP = 282, KBDK_CALL = 289, /**< Used for accepting phone calls. */
KBDK_ENDCALL = 290, /**< Used for rejecting phone calls. */
KBDK_APP1 = 283, /* @} *//* Mobile keys */
KBDK_APP2 = 284,
/* @} *//* Walther keys */
/* Add any other keys here. */ /* Add any other keys here. */
KBDK_LAST = 512 /**< not a key, just marks the number of scancodes KBDK_RESERVED = 400, /**< 400-500 reserved for dynamic keycodes */
for array bounds */
KBDK_COUNT = 512 /**< not a key, just marks the number of scancodes for array bounds */
}; };
// This comes directly from SDL_keycode.h // This comes directly from SDL_keycode.h
enum StellaMod: uInt16 enum StellaMod: uInt16
{ {
KBDM_NONE = 0x0000, KBDM_NONE = 0x0000U, /**< no modifier is applicable. */
KBDM_LSHIFT = 0x0001, KBDM_LSHIFT = 0x0001U, /**< the left Shift key is down. */
KBDM_RSHIFT = 0x0002, KBDM_RSHIFT = 0x0002U, /**< the right Shift key is down. */
KBDM_LCTRL = 0x0040, KBDM_LEVEL5 = 0x0004U, /**< the Level 5 Shift key is down. */
KBDM_RCTRL = 0x0080, KBDM_LCTRL = 0x0040U, /**< the left Ctrl (Control) key is down. */
KBDM_LALT = 0x0100, KBDM_RCTRL = 0x0080U, /**< the right Ctrl (Control) key is down. */
KBDM_RALT = 0x0200, KBDM_LALT = 0x0100U, /**< the left Alt key is down. */
KBDM_LGUI = 0x0400, KBDM_RALT = 0x0200U, /**< the right Alt key is down. */
KBDM_RGUI = 0x0800, KBDM_LGUI = 0x0400U, /**< the left GUI key (often the Windows key) is down. */
KBDM_NUM = 0x1000, KBDM_RGUI = 0x0800U, /**< the right GUI key (often the Windows key) is down. */
KBDM_CAPS = 0x2000, KBDM_NUM = 0x1000U, /**< the Num Lock key (may be located on an extended keypad) is down. */
KBDM_MODE = 0x4000, KBDM_CAPS = 0x2000U, /**< the Caps Lock key is down. */
KBDM_RESERVED = 0x8000, KBDM_MODE = 0x4000U, /**< the !AltGr key is down. */
KBDM_CTRL = (KBDM_LCTRL|KBDM_RCTRL), KBDM_SCROLL = 0x8000U, /**< the Scroll Lock key is down. */
KBDM_SHIFT = (KBDM_LSHIFT|KBDM_RSHIFT), KBDM_CTRL = (KBDM_LCTRL | KBDM_RCTRL), /**< Any Ctrl key is down. */
KBDM_ALT = (KBDM_LALT|KBDM_RALT), KBDM_SHIFT = (KBDM_LSHIFT | KBDM_RSHIFT), /**< Any Shift key is down. */
KBDM_GUI = (KBDM_LGUI|KBDM_RGUI) KBDM_ALT = (KBDM_LALT | KBDM_RALT), /**< Any Alt key is down. */
KBDM_GUI = (KBDM_LGUI | KBDM_RGUI) /**< Any GUI key is down. */
}; };
// Test if specified modifier is pressed // Test if specified modifier is pressed

View File

@ -29,17 +29,17 @@ void VideoModeHandler::setImageSize(const Common::Size& image)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoModeHandler::setDisplaySize(const Common::Size& display, Int32 fsIndex) void VideoModeHandler::setDisplaySize(const Common::Size& display, bool fullscreen)
{ {
myDisplay = display; myDisplay = display;
myFSIndex = fsIndex; myFullscreen = fullscreen;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const VideoModeHandler::Mode& const VideoModeHandler::Mode&
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode, Bezel::Info bezelInfo) VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode, Bezel::Info bezelInfo)
{ {
const bool windowedRequested = myFSIndex == -1; const bool windowedRequested = !myFullscreen;
// TIA mode allows zooming at non-integral factors in most cases // TIA mode allows zooming at non-integral factors in most cases
if(inTIAMode) if(inTIAMode)
@ -53,7 +53,7 @@ const VideoModeHandler::Mode&
// Image and screen (aka window) dimensions are the same // Image and screen (aka window) dimensions are the same
// Overscan is not applicable in this mode // Overscan is not applicable in this mode
myMode = Mode(myImage.w, myImage.h, myMode = Mode(myImage.w, myImage.h,
Mode::Stretch::Fill, myFSIndex, Mode::Stretch::Fill, myFullscreen,
desc.view(), zoom, bezelInfo); desc.view(), zoom, bezelInfo);
} }
else else
@ -74,7 +74,7 @@ const VideoModeHandler::Mode&
{ {
myMode = Mode(myImage.w, myImage.h, myMode = Mode(myImage.w, myImage.h,
myDisplay.w, myDisplay.h, myDisplay.w, myDisplay.h,
Mode::Stretch::Preserve, myFSIndex, Mode::Stretch::Preserve, myFullscreen,
"Fullscreen: Preserve aspect, no stretch", "Fullscreen: Preserve aspect, no stretch",
zoom, overscan, bezelInfo); zoom, overscan, bezelInfo);
} }
@ -82,7 +82,7 @@ const VideoModeHandler::Mode&
{ {
myMode = Mode(myImage.w, myImage.h, myMode = Mode(myImage.w, myImage.h,
myDisplay.w, myDisplay.h, myDisplay.w, myDisplay.h,
Mode::Stretch::Fill, myFSIndex, Mode::Stretch::Fill, myFullscreen,
"Fullscreen: Ignore aspect, full stretch", "Fullscreen: Ignore aspect, full stretch",
zoom, overscan, bezelInfo); zoom, overscan, bezelInfo);
} }
@ -94,31 +94,31 @@ const VideoModeHandler::Mode&
myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None); myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None);
else else
myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h, myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h,
Mode::Stretch::None, myFSIndex); Mode::Stretch::None, myFullscreen);
} }
return myMode; return myMode;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode, VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
Int32 fsindex, string_view desc, bool fullscreen, string_view desc,
double zoomLevel, Bezel::Info bezelInfo) double zoomLevel, Bezel::Info bezelInfo)
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel, 1., bezelInfo) : Mode(iw, ih, iw, ih, smode, fullscreen, desc, zoomLevel, 1., bezelInfo)
{ {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
Stretch smode, Int32 fsindex, string_view desc, Stretch smode, bool fs, string_view desc,
double zoomLevel, double overscan, Bezel::Info bezelInfo) double zoomLevel, double overscan, Bezel::Info bezelInfo)
: screenS{sw, sh}, : screenS{sw, sh},
stretch{smode}, stretch{smode},
description{desc}, description{desc},
zoom{zoomLevel}, //hZoom{zoomLevel}, vZoom{zoomLevel}, zoom{zoomLevel}, //hZoom{zoomLevel}, vZoom{zoomLevel},
fsIndex{fsindex} fullscreen{fs}
{ {
// Now resize based on windowed/fullscreen mode and stretch factor // Now resize based on windowed/fullscreen mode and stretch factor
if(fsIndex != -1) // fullscreen mode if(fullscreen)
{ {
switch(stretch) switch(stretch)
{ {
@ -174,9 +174,9 @@ VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
const uInt32 wx = bezelInfo.window().x() * iw / bezelInfo.window().w(); const uInt32 wx = bezelInfo.window().x() * iw / bezelInfo.window().w();
const uInt32 wy = bezelInfo.window().y() * ih / bezelInfo.window().h(); const uInt32 wy = bezelInfo.window().y() * ih / bezelInfo.window().h();
const uInt32 bezelW = std::min(screenS.w, const uInt32 bezelW = std::min(screenS.w,
static_cast<uInt32>(std::round(iw * bezelInfo.ratioW()))); static_cast<uInt32>(std::round(iw * bezelInfo.ratioW())));
const uInt32 bezelH = std::min(screenS.h, const uInt32 bezelH = std::min(screenS.h,
static_cast<uInt32>(std::round(ih * bezelInfo.ratioH()))); static_cast<uInt32>(std::round(ih * bezelInfo.ratioH())));
// Center image (no bezel) or move image relative to centered bezel // Center image (no bezel) or move image relative to centered bezel
imageR.moveTo(((screenS.w - bezelW) >> 1) + wx, ((screenS.h - bezelH) >> 1) + wy); imageR.moveTo(((screenS.w - bezelW) >> 1) + wx, ((screenS.h - bezelH) >> 1) + wy);

View File

@ -46,14 +46,14 @@ class VideoModeHandler
Stretch stretch{Mode::Stretch::None}; Stretch stretch{Mode::Stretch::None};
string description; string description;
double zoom{1.}; double zoom{1.};
Int32 fsIndex{-1}; // -1 indicates windowed mode bool fullscreen{false}; // false indicates windowed mode
Mode() = default; Mode() = default;
Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode, Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
Int32 fsindex = -1, string_view desc = "", bool fullscreen = false, string_view desc = "",
double zoomLevel = 1., double overscan = 1., double zoomLevel = 1., double overscan = 1.,
Bezel::Info bezelInfo = Bezel::Info()); Bezel::Info bezelInfo = Bezel::Info());
Mode(uInt32 iw, uInt32 ih, Stretch smode, Int32 fsindex = -1, Mode(uInt32 iw, uInt32 ih, Stretch smode, bool fullscreen = false,
string_view desc = "", double zoomLevel = 1., string_view desc = "", double zoomLevel = 1.,
Bezel::Info bezelInfo = Bezel::Info()); Bezel::Info bezelInfo = Bezel::Info());
@ -63,7 +63,7 @@ class VideoModeHandler
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" : << " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
vm.stretch == Stretch::Fill ? "fill" : "none") vm.stretch == Stretch::Fill ? "fill" : "none")
<< " desc=" << vm.description << " zoom=" << vm.zoom << " desc=" << vm.description << " zoom=" << vm.zoom
<< " fsIndex= " << vm.fsIndex; << " fullscreen= " << vm.fullscreen;
return os; return os;
} }
}; };
@ -84,10 +84,10 @@ class VideoModeHandler
Set the size of the display. This could be either the desktop size, Set the size of the display. This could be either the desktop size,
or the size of the monitor currently active. or the size of the monitor currently active.
@param display The dimensions of the enclosing display @param display The dimensions of the enclosing display
@param fsIndex Fullscreen mode in use (-1 indicates windowed mode) @param fullscreen Whether to use fullscreen or windowed mode
*/ */
void setDisplaySize(const Common::Size& display, Int32 fsIndex = -1); void setDisplaySize(const Common::Size& display, bool fullscreen);
/** /**
Build a video mode based on the given parameters, assuming that Build a video mode based on the given parameters, assuming that
@ -103,7 +103,7 @@ class VideoModeHandler
private: private:
Common::Size myImage, myDisplay; Common::Size myImage, myDisplay;
Int32 myFSIndex{-1}; bool myFullscreen{false};
Mode myMode; Mode myMode;

View File

@ -726,16 +726,12 @@ NLOHMANN_JSON_SERIALIZE_ENUM(StellaKey, {
{StellaKey::KBDK_RALT, "ralt"}, {StellaKey::KBDK_RALT, "ralt"},
{StellaKey::KBDK_RGUI, "rgui"}, {StellaKey::KBDK_RGUI, "rgui"},
{StellaKey::KBDK_MODE, "mode"}, {StellaKey::KBDK_MODE, "mode"},
{StellaKey::KBDK_AUDIONEXT, "audionext"}, {StellaKey::KBDK_MEDIA_NEXT_TRACK, "audionext"},
{StellaKey::KBDK_AUDIOPREV, "audioprev"}, {StellaKey::KBDK_MEDIA_PREVIOUS_TRACK, "audioprev"},
{StellaKey::KBDK_AUDIOSTOP, "audiostop"}, {StellaKey::KBDK_MEDIA_STOP, "audiostop"},
{StellaKey::KBDK_AUDIOPLAY, "audioplay"}, {StellaKey::KBDK_MEDIA_PLAY, "audioplay"},
{StellaKey::KBDK_AUDIOMUTE, "audiomute"}, {StellaKey::KBDK_MUTE, "audiomute"},
{StellaKey::KBDK_MEDIASELECT, "mediaselect"}, {StellaKey::KBDK_MEDIA_SELECT, "mediaselect"},
{StellaKey::KBDK_WWW, "www"},
{StellaKey::KBDK_MAIL, "mail"},
{StellaKey::KBDK_CALCULATOR, "calculator"},
{StellaKey::KBDK_COMPUTER, "computer"},
{StellaKey::KBDK_AC_SEARCH, "ac_search"}, {StellaKey::KBDK_AC_SEARCH, "ac_search"},
{StellaKey::KBDK_AC_HOME, "ac_home"}, {StellaKey::KBDK_AC_HOME, "ac_home"},
{StellaKey::KBDK_AC_BACK, "ac_back"}, {StellaKey::KBDK_AC_BACK, "ac_back"},
@ -743,17 +739,9 @@ NLOHMANN_JSON_SERIALIZE_ENUM(StellaKey, {
{StellaKey::KBDK_AC_STOP, "ac_stop"}, {StellaKey::KBDK_AC_STOP, "ac_stop"},
{StellaKey::KBDK_AC_REFRESH, "ac_refresh"}, {StellaKey::KBDK_AC_REFRESH, "ac_refresh"},
{StellaKey::KBDK_AC_BOOKMARKS, "ac_bookmarks"}, {StellaKey::KBDK_AC_BOOKMARKS, "ac_bookmarks"},
{StellaKey::KBDK_BRIGHTNESSDOWN, "brightnessdown"}, {StellaKey::KBDK_MEDIA_EJECT, "eject"},
{StellaKey::KBDK_BRIGHTNESSUP, "brightnessup"},
{StellaKey::KBDK_DISPLAYSWITCH, "displayswitch"},
{StellaKey::KBDK_KBDILLUMTOGGLE, "kbdillumtoggle"},
{StellaKey::KBDK_KBDILLUMDOWN, "kbdillumdown"},
{StellaKey::KBDK_KBDILLUMUP, "kbdillumup"},
{StellaKey::KBDK_EJECT, "eject"},
{StellaKey::KBDK_SLEEP, "sleep"}, {StellaKey::KBDK_SLEEP, "sleep"},
{StellaKey::KBDK_APP1, "app1"}, {StellaKey::KBDK_COUNT, "last"}
{StellaKey::KBDK_APP2, "app2"},
{StellaKey::KBDK_LAST, "last"}
}) })
NLOHMANN_JSON_SERIALIZE_ENUM(StellaMod, { NLOHMANN_JSON_SERIALIZE_ENUM(StellaMod, {
@ -769,7 +757,6 @@ NLOHMANN_JSON_SERIALIZE_ENUM(StellaMod, {
{StellaMod::KBDM_NUM, "num"}, {StellaMod::KBDM_NUM, "num"},
{StellaMod::KBDM_CAPS, "caps"}, {StellaMod::KBDM_CAPS, "caps"},
{StellaMod::KBDM_MODE, "mode"}, {StellaMod::KBDM_MODE, "mode"},
{StellaMod::KBDM_RESERVED, "reserved"},
{StellaMod::KBDM_CTRL, "ctrl"}, {StellaMod::KBDM_CTRL, "ctrl"},
{StellaMod::KBDM_SHIFT, "shift"}, {StellaMod::KBDM_SHIFT, "shift"},
{StellaMod::KBDM_ALT, "alt"}, {StellaMod::KBDM_ALT, "alt"},

View File

@ -49,14 +49,17 @@ void BilinearBlitter::reinitialize(
myStaticData == staticData myStaticData == staticData
); );
myStaticData = staticData; myAttributes = attributes;
mySrcRect = srcRect; myStaticData = staticData;
myAttributes = attributes;
myDstRect.x = myFB.scaleX(destRect.x); mySrcRect = srcRect;
myDstRect.y = myFB.scaleY(destRect.y); SDL_RectToFRect(&mySrcRect, &mySrcFRect);
myDstRect.w = myFB.scaleX(destRect.w);
myDstRect.h = myFB.scaleY(destRect.h); myDstRect.x = myFB.scaleX(destRect.x);
myDstRect.y = myFB.scaleY(destRect.y);
myDstRect.w = myFB.scaleX(destRect.w);
myDstRect.h = myFB.scaleY(destRect.h);
SDL_RectToFRect(&myDstRect, &myDstFRect);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -68,7 +71,9 @@ void BilinearBlitter::free()
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
const std::array<SDL_Texture*, 2> textures = { myTexture, mySecondaryTexture }; const std::array<SDL_Texture*, 2> textures = {
myTexture, mySecondaryTexture
};
for (SDL_Texture* texture: textures) { for (SDL_Texture* texture: textures) {
if (!texture) continue; if (!texture) continue;
@ -93,10 +98,9 @@ void BilinearBlitter::blit(SDL_Surface& surface)
mySecondaryTexture = texture; mySecondaryTexture = texture;
} }
SDL_RenderCopy(myFB.renderer(), texture, &mySrcRect, &myDstRect); SDL_RenderTexture(myFB.renderer(), texture, &mySrcFRect, &myDstFRect);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BilinearBlitter::recreateTexturesIfNecessary() void BilinearBlitter::recreateTexturesIfNecessary()
{ {
@ -110,16 +114,22 @@ void BilinearBlitter::recreateTexturesIfNecessary()
free(); free();
} }
const SDL_TextureAccess texAccess = myStaticData == nullptr ? SDL_TEXTUREACCESS_STREAMING : SDL_TEXTUREACCESS_STATIC; const SDL_TextureAccess texAccess = myStaticData == nullptr
? SDL_TEXTUREACCESS_STREAMING
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myInterpolate ? "1" : "0"); : SDL_TEXTUREACCESS_STATIC;
myTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, myTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
texAccess, mySrcRect.w, mySrcRect.h); texAccess, mySrcRect.w, mySrcRect.h);
SDL_SetTextureScaleMode(myTexture, myInterpolate
? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
if (myStaticData == nullptr) { if (myStaticData == nullptr) {
mySecondaryTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, mySecondaryTexture = SDL_CreateTexture(myFB.renderer(),
myFB.pixelFormat().format,
texAccess, mySrcRect.w, mySrcRect.h); texAccess, mySrcRect.w, mySrcRect.h);
SDL_SetTextureScaleMode(mySecondaryTexture, myInterpolate
? SDL_SCALEMODE_LINEAR
: SDL_SCALEMODE_NEAREST);
} else { } else {
mySecondaryTexture = nullptr; mySecondaryTexture = nullptr;
SDL_UpdateTexture(myTexture, nullptr, myStaticData->pixels, myStaticData->pitch); SDL_UpdateTexture(myTexture, nullptr, myStaticData->pixels, myStaticData->pitch);

View File

@ -46,6 +46,7 @@ class BilinearBlitter : public Blitter {
SDL_Texture* myTexture{nullptr}; SDL_Texture* myTexture{nullptr};
SDL_Texture* mySecondaryTexture{nullptr}; SDL_Texture* mySecondaryTexture{nullptr};
SDL_Rect mySrcRect{0, 0, 0, 0}, myDstRect{0, 0, 0, 0}; SDL_Rect mySrcRect{0, 0, 0, 0}, myDstRect{0, 0, 0, 0};
SDL_FRect mySrcFRect{0.F, 0.F, 0.F, 0.F}, myDstFRect{0.F, 0.F, 0.F, 0.F};
FBSurface::Attributes myAttributes; FBSurface::Attributes myAttributes;
bool myInterpolate{false}; bool myInterpolate{false};

View File

@ -19,6 +19,19 @@
#include "ThreadDebugging.hxx" #include "ThreadDebugging.hxx"
#include "QisBlitter.hxx" #include "QisBlitter.hxx"
static void P(const char* str, const SDL_Rect r, const SDL_FRect fr)
{
cerr << str << ": "
<< r.x << "," << r.y << " " << r.w << "x" << r.h << " => "
<< fr.x << "," << fr.y << " " << fr.w << "x" << fr.h << '\n';
}
static void PF(const char* str, const SDL_FRect r, const SDL_FRect fr)
{
cerr << str << ": "
<< r.x << "," << r.y << " " << r.w << "x" << r.h << " => "
<< fr.x << "," << fr.y << " " << fr.w << "x" << fr.h << '\n';
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QisBlitter::QisBlitter(FBBackendSDL& fb) QisBlitter::QisBlitter(FBBackendSDL& fb)
: myFB{fb} : myFB{fb}
@ -56,14 +69,17 @@ void QisBlitter::reinitialize(
myStaticData == staticData myStaticData == staticData
); );
myStaticData = staticData; myAttributes = attributes;
mySrcRect = srcRect; myStaticData = staticData;
myAttributes = attributes;
myDstRect.x = myFB.scaleX(destRect.x); mySrcRect = srcRect;
myDstRect.y = myFB.scaleY(destRect.y); SDL_RectToFRect(&mySrcRect, &mySrcFRect);
myDstRect.w = myFB.scaleX(destRect.w);
myDstRect.h = myFB.scaleY(destRect.h); myDstRect.x = myFB.scaleX(destRect.x);
myDstRect.y = myFB.scaleY(destRect.y);
myDstRect.w = myFB.scaleX(destRect.w);
myDstRect.h = myFB.scaleY(destRect.h);
SDL_RectToFRect(&myDstRect, &myDstFRect);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -76,7 +92,7 @@ void QisBlitter::free()
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
const std::array<SDL_Texture*, 3> textures = { const std::array<SDL_Texture*, 3> textures = {
mySrcTexture, myIntermediateTexture, mySecondaryIntermedateTexture mySrcTexture, myIntermediateTexture, mySecondaryIntermediateTexture
}; };
for (SDL_Texture* texture: textures) { for (SDL_Texture* texture: textures) {
if (!texture) continue; if (!texture) continue;
@ -101,15 +117,16 @@ void QisBlitter::blit(SDL_Surface& surface)
blitToIntermediate(); blitToIntermediate();
myIntermediateTexture = mySecondaryIntermedateTexture; myIntermediateTexture = mySecondaryIntermediateTexture;
mySecondaryIntermedateTexture = intermediateTexture; mySecondaryIntermediateTexture = intermediateTexture;
SDL_Texture* temporary = mySrcTexture; SDL_Texture* temporary = mySrcTexture;
mySrcTexture = mySecondarySrcTexture; mySrcTexture = mySecondarySrcTexture;
mySecondarySrcTexture = temporary; mySecondarySrcTexture = temporary;
} }
SDL_RenderCopy(myFB.renderer(), intermediateTexture, &myIntermediateRect, &myDstRect); SDL_RenderTexture(myFB.renderer(), intermediateTexture,
&myIntermediateFRect, &myDstFRect);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -117,15 +134,16 @@ void QisBlitter::blitToIntermediate()
{ {
ASSERT_MAIN_THREAD; ASSERT_MAIN_THREAD;
SDL_Rect r = mySrcRect; SDL_FRect r{};
r.x = r.y = 0; SDL_RectToFRect(&mySrcRect, &r);
r.x = r.y = 0.F;
SDL_SetRenderTarget(myFB.renderer(), myIntermediateTexture); SDL_SetRenderTarget(myFB.renderer(), myIntermediateTexture);
SDL_SetRenderDrawColor(myFB.renderer(), 0, 0, 0, 255); SDL_SetRenderDrawColor(myFB.renderer(), 0, 0, 0, 255);
SDL_RenderClear(myFB.renderer()); SDL_RenderClear(myFB.renderer());
SDL_RenderCopy(myFB.renderer(), mySrcTexture, &r, &myIntermediateRect); SDL_RenderTexture(myFB.renderer(), mySrcTexture, &r, &myIntermediateFRect);
SDL_SetRenderTarget(myFB.renderer(), nullptr); SDL_SetRenderTarget(myFB.renderer(), nullptr);
} }
@ -143,36 +161,40 @@ void QisBlitter::recreateTexturesIfNecessary()
free(); free();
} }
const SDL_TextureAccess texAccess = const SDL_TextureAccess texAccess = myStaticData == nullptr
myStaticData == nullptr ? SDL_TEXTUREACCESS_STREAMING : SDL_TEXTUREACCESS_STATIC; ? SDL_TEXTUREACCESS_STREAMING
: SDL_TEXTUREACCESS_STATIC;
myIntermediateRect.w = (myDstRect.w / mySrcRect.w) * mySrcRect.w; myIntermediateRect.w = (myDstRect.w / mySrcRect.w) * mySrcRect.w;
myIntermediateRect.h = (myDstRect.h / mySrcRect.h) * mySrcRect.h; myIntermediateRect.h = (myDstRect.h / mySrcRect.h) * mySrcRect.h;
myIntermediateRect.x = 0; myIntermediateRect.x = 0;
myIntermediateRect.y = 0; myIntermediateRect.y = 0;
SDL_RectToFRect(&myIntermediateRect, &myIntermediateFRect);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
mySrcTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, mySrcTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
texAccess, mySrcRect.w, mySrcRect.h); texAccess, mySrcRect.w, mySrcRect.h);
SDL_SetTextureScaleMode(mySrcTexture, SDL_SCALEMODE_NEAREST);
if (myStaticData == nullptr) { if (myStaticData == nullptr) {
mySecondarySrcTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, mySecondarySrcTexture = SDL_CreateTexture(myFB.renderer(),
texAccess, mySrcRect.w, mySrcRect.h); myFB.pixelFormat().format, texAccess, mySrcRect.w, mySrcRect.h);
SDL_SetTextureScaleMode(mySecondarySrcTexture, SDL_SCALEMODE_NEAREST);
} else { } else {
mySecondarySrcTexture = nullptr; mySecondarySrcTexture = nullptr;
} }
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
myIntermediateTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, myIntermediateTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
SDL_TEXTUREACCESS_TARGET, myIntermediateRect.w, myIntermediateRect.h); SDL_TEXTUREACCESS_TARGET, myIntermediateRect.w, myIntermediateRect.h);
SDL_SetTextureScaleMode(myIntermediateTexture, SDL_SCALEMODE_LINEAR);
if (myStaticData == nullptr) { if (myStaticData == nullptr) {
mySecondaryIntermedateTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format, mySecondaryIntermediateTexture = SDL_CreateTexture(myFB.renderer(),
SDL_TEXTUREACCESS_TARGET, myIntermediateRect.w, myIntermediateRect.h); myFB.pixelFormat().format, SDL_TEXTUREACCESS_TARGET,
myIntermediateRect.w, myIntermediateRect.h);
SDL_SetTextureScaleMode(mySecondaryIntermediateTexture,
SDL_SCALEMODE_LINEAR);
} else { } else {
mySecondaryIntermedateTexture = nullptr; mySecondaryIntermediateTexture = nullptr;
SDL_UpdateTexture(mySrcTexture, nullptr, myStaticData->pixels, myStaticData->pitch); SDL_UpdateTexture(mySrcTexture, nullptr, myStaticData->pixels, myStaticData->pitch);
blitToIntermediate(); blitToIntermediate();
@ -182,7 +204,7 @@ void QisBlitter::recreateTexturesIfNecessary()
const auto blendAlpha = static_cast<uInt8>(myAttributes.blendalpha * 2.55); const auto blendAlpha = static_cast<uInt8>(myAttributes.blendalpha * 2.55);
const std::array<SDL_Texture*, 2> textures = { const std::array<SDL_Texture*, 2> textures = {
myIntermediateTexture, mySecondaryIntermedateTexture myIntermediateTexture, mySecondaryIntermediateTexture
}; };
for (SDL_Texture* texture: textures) { for (SDL_Texture* texture: textures) {
if (!texture) continue; if (!texture) continue;

View File

@ -49,9 +49,14 @@ class QisBlitter : public Blitter {
SDL_Texture* mySrcTexture{nullptr}; SDL_Texture* mySrcTexture{nullptr};
SDL_Texture* mySecondarySrcTexture{nullptr}; SDL_Texture* mySecondarySrcTexture{nullptr};
SDL_Texture* myIntermediateTexture{nullptr}; SDL_Texture* myIntermediateTexture{nullptr};
SDL_Texture* mySecondaryIntermedateTexture{nullptr}; SDL_Texture* mySecondaryIntermediateTexture{nullptr};
SDL_Rect mySrcRect{0, 0, 0, 0}, myIntermediateRect{0, 0, 0, 0}, myDstRect{0, 0, 0, 0}; SDL_Rect mySrcRect{0, 0, 0, 0},
myIntermediateRect{0, 0, 0, 0},
myDstRect{0, 0, 0, 0};
SDL_FRect mySrcFRect{0.F, 0.F, 0.F, 0.F},
myIntermediateFRect{0.F, 0.F, 0.F, 0.F},
myDstFRect{0.F, 0.F, 0.F, 0.F};
FBSurface::Attributes myAttributes; FBSurface::Attributes myAttributes;
bool myTexturesAreAllocated{false}; bool myTexturesAreAllocated{false};

View File

@ -191,10 +191,9 @@ class FBBackend
This method is called to query the video hardware for the index This method is called to query the video hardware for the index
of the display the current window is displayed on. of the display the current window is displayed on.
@return The current display index or a negative value if no @return The current display id or a 0 if no window is displayed
window is displayed
*/ */
virtual Int32 getCurrentDisplayIndex() const = 0; virtual uInt32 getCurrentDisplayID() const = 0;
/** /**
This method is called to create a surface with the given attributes. This method is called to create a surface with the given attributes.

View File

@ -135,7 +135,7 @@ int FrameBuffer::displayId(BufferType bufferType) const
int display = 0; int display = 0;
if(bufferType == myBufferType) if(bufferType == myBufferType)
display = myBackend->getCurrentDisplayIndex(); display = myBackend->getCurrentDisplayID();
else else
display = myOSystem.settings().getInt(getDisplayKey(bufferType != BufferType::None display = myOSystem.settings().getInt(getDisplayKey(bufferType != BufferType::None
? bufferType : myBufferType)); ? bufferType : myBufferType));
@ -1096,7 +1096,7 @@ void FrameBuffer::saveCurrentWindowPosition() const
if(myBackend) if(myBackend)
{ {
myOSystem.settings().setValue( myOSystem.settings().setValue(
getDisplayKey(), myBackend->getCurrentDisplayIndex()); getDisplayKey(), myBackend->getCurrentDisplayID());
if(myBackend->isCurrentWindowPositioned()) if(myBackend->isCurrentWindowPositioned())
myOSystem.settings().setValue( myOSystem.settings().setValue(
getPositionKey(), myBackend->getCurrentWindowPos()); getPositionKey(), myBackend->getCurrentWindowPos());
@ -1319,12 +1319,12 @@ FBInitStatus FrameBuffer::applyVideoMode()
{ {
// Update display size, in case windowed/fullscreen mode has changed // Update display size, in case windowed/fullscreen mode has changed
const Settings& s = myOSystem.settings(); const Settings& s = myOSystem.settings();
const int display = displayId(); const int ID = displayId();
if(s.getBool("fullscreen")) if(s.getBool("fullscreen"))
myVidModeHandler.setDisplaySize(myFullscreenDisplays[display], display); myVidModeHandler.setDisplaySize(myFullscreenDisplays[ID], true);
else else
myVidModeHandler.setDisplaySize(myAbsDesktopSize[display]); myVidModeHandler.setDisplaySize(myAbsDesktopSize[ID], false);
const bool inTIAMode = myOSystem.eventHandler().inTIAMode(); const bool inTIAMode = myOSystem.eventHandler().inTIAMode();

View File

@ -304,7 +304,7 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id
{ {
const string& url = myDesc[id]->getUrl(); const string& url = myDesc[id]->getUrl();
if(url != EmptyString && MediaFactory::supportsURL()) if(url != EmptyString)
MediaFactory::openURL(url); MediaFactory::openURL(url);
break; break;
} }

View File

@ -176,7 +176,7 @@ void Dialog::initHelp()
_helpWidget->setToolTip("Click or press " + key + " for help."); _helpWidget->setToolTip("Click or press " + key + " for help.");
} }
if(hasHelp() && MediaFactory::supportsURL()) if(hasHelp())
_helpWidget->clearFlags(Widget::FLAG_INVISIBLE); _helpWidget->clearFlags(Widget::FLAG_INVISIBLE);
else else
_helpWidget->setFlags(Widget::FLAG_INVISIBLE); _helpWidget->setFlags(Widget::FLAG_INVISIBLE);

View File

@ -1378,7 +1378,7 @@ void GameInfoDialog::updateLink()
|| startsWithIgnoreCase(link, "https://") || startsWithIgnoreCase(link, "https://")
|| startsWithIgnoreCase(link, "www."); || startsWithIgnoreCase(link, "www.");
myUrlButton->setEnabled(enable && MediaFactory::supportsURL()); myUrlButton->setEnabled(enable);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -64,7 +64,7 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
myUpdateButton = myUpdateButton =
new ButtonWidget(this, font, xpos, ypos, updButtonWidth, buttonHeight, new ButtonWidget(this, font, xpos, ypos, updButtonWidth, buttonHeight,
"Check for Update" + ELLIPSIS, kUpdateCmd); "Check for Update" + ELLIPSIS, kUpdateCmd);
myUpdateButton->setEnabled(MediaFactory::supportsURL()); myUpdateButton->setEnabled(true);
wid.push_back(myUpdateButton); wid.push_back(myUpdateButton);
xpos = _w - closeButtonWidth - HBORDER; xpos = _w - closeButtonWidth - HBORDER;

View File

@ -277,7 +277,7 @@ void LauncherDialog::addPathWidgets(int& ypos)
buttonWidth, buttonHeight, helpIcon, kHelpCmd); buttonWidth, buttonHeight, helpIcon, kHelpCmd);
const string key = instance().eventHandler().getMappingDesc(Event::UIHelp, EventMode::kMenuMode); const string key = instance().eventHandler().getMappingDesc(Event::UIHelp, EventMode::kMenuMode);
myHelpButton->setToolTip("Click for help. (" + key + ")"); myHelpButton->setToolTip("Click for help. (" + key + ")");
myHelpButton->setEnabled(MediaFactory::supportsURL()); myHelpButton->setEnabled(true);
wid.push_back(myHelpButton); wid.push_back(myHelpButton);
} }
ypos += lineHeight + Dialog::vGap() * 2; ypos += lineHeight + Dialog::vGap() * 2;

View File

@ -104,7 +104,7 @@ class FBBackendLIBRETRO : public FBBackend
void readPixels(uInt8*, size_t, const Common::Rect&) const override { } void readPixels(uInt8*, size_t, const Common::Rect&) const override { }
bool isCurrentWindowPositioned() const override { return true; } bool isCurrentWindowPositioned() const override { return true; }
Common::Point getCurrentWindowPos() const override { return Common::Point{}; } Common::Point getCurrentWindowPos() const override { return Common::Point{}; }
Int32 getCurrentDisplayIndex() const override { return 0; } uInt32 getCurrentDisplayID() const override { return 0; }
void clear() override { } void clear() override { }
bool setVideoMode(const VideoModeHandler::Mode&, bool setVideoMode(const VideoModeHandler::Mode&,
int, const Common::Point&) override { return true; } int, const Common::Point&) override { return true; }